diff --git a/src/ecc/formal/fv_ecc_block_overview.pdf b/src/ecc/formal/fv_ecc_block_overview.pdf new file mode 100644 index 000000000..5454274fd Binary files /dev/null and b/src/ecc/formal/fv_ecc_block_overview.pdf differ diff --git a/src/ecc/formal/properties/coverpoints/fv_add_sub_alter_coverpoints.sv b/src/ecc/formal/properties/coverpoints/fv_add_sub_alter_coverpoints.sv new file mode 100644 index 000000000..e0ee82079 --- /dev/null +++ b/src/ecc/formal/properties/coverpoints/fv_add_sub_alter_coverpoints.sv @@ -0,0 +1,45 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_add_sub_alter_coverpoints_m( + input logic clk, + input logic reset_n, + input logic zeroize +); + + default clocking default_clk @(posedge clk); endclocking + + //Cover zeroize: + cover_zeroize: cover property(disable iff(!reset_n) ecc_add_sub_mod_alter.zeroize ); + + cover_prime_p: cover property(disable iff(!reset_n) (ecc_add_sub_mod_alter.prime_i==384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff)); + cover_prime_q: cover property(disable iff(!reset_n)(ecc_add_sub_mod_alter.prime_i==384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973)); + cover_add_en: cover property(disable iff(!reset_n) ecc_add_sub_mod_alter.add_en_i==1); + cover_add_disable: cover property(disable iff(!reset_n) ecc_add_sub_mod_alter.add_en_i==0); + cover_r0_0: cover property(disable iff(!reset_n || zeroize) ecc_add_sub_mod_alter.r0=='0); + cover_r0_1: cover property(disable iff(!reset_n || zeroize) ecc_add_sub_mod_alter.r0=='1); + cover_r0_greater_prime: cover property(disable iff(!reset_n || zeroize) ecc_add_sub_mod_alter.r0 > ecc_add_sub_mod_alter.prime_i); + + +endmodule + +bind ecc_add_sub_mod_alter fv_add_sub_alter_coverpoints_m fv_add_sub_alter_coverpoints( + .clk(clk), + .reset_n(reset_n), + .zeroize(zeroize) +); diff --git a/src/ecc/formal/properties/coverpoints/fv_arith_unit_coverpoints.sv b/src/ecc/formal/properties/coverpoints/fv_arith_unit_coverpoints.sv new file mode 100644 index 000000000..d024e4294 --- /dev/null +++ b/src/ecc/formal/properties/coverpoints/fv_arith_unit_coverpoints.sv @@ -0,0 +1,86 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_arith_unit_coverpoints_m( + input logic clk, + input logic reset_n, + input logic zeroize +); + + default clocking default_clk @(posedge clk); endclocking + + //Cover zeroize: + cover_zeroize: cover property(disable iff(!reset_n) ecc_arith_unit.zeroize ); + + //cover wea + cover_wea: cover property(disable iff(!reset_n) ( + ecc_arith_unit.ecc_instr_s.opcode.add_en + ##3 + ecc_arith_unit.ram_tdp_file_i.wea)); + + //cover web + cover_wem: cover property(disable iff(!reset_n) + ecc_arith_unit.ecc_instr_s.opcode.mult_en + ##41 + ecc_arith_unit.web_mux_s); + + //cover req_digit when keygen cmd + cover_req_digit_keygen: cover property(disable iff(!reset_n) + ecc_arith_unit.ecc_cmd_i== 3'b001 //KEYGEN_CMD + ##1 + ecc_arith_unit.req_digit[->576]); + + //cover req_digit when signing cmd + cover_req_digit_signing: cover property(disable iff(!reset_n) + ecc_arith_unit.ecc_cmd_i==3'b010 //SIGN_CMD + ##1 + ecc_arith_unit.req_digit[->576]); + + + //cover wr_op_sel_i when ecc_cmd_i is received + cover_wr_op_sel_i: cover property(disable iff(!reset_n) + (ecc_arith_unit.ecc_cmd_i!=3'b0 && !ecc_arith_unit.wr_op_sel_i)); + + //cover wr_en_i when ecc_cmd_i is received + cover_wr_en_i: cover property(disable iff(!reset_n || zeroize) + (ecc_arith_unit.ecc_cmd_i!=3'b0 && !ecc_arith_unit.wr_en_i)); + + //cover sca_en_i + cover_sca_en_always: cover property(disable iff(!reset_n || zeroize) + ecc_arith_unit.sca_en_i ==1); + + //cover digit_in be the MSB bit of secret key + cover_digit_in_msb_secret_key: cover property(disable iff(!reset_n || zeroize) + ecc_arith_unit.req_digit + ##1 + ecc_arith_unit.digit_in == $past(ecc_arith_unit.secret_key[(ecc_arith_unit.REG_SIZE+ecc_arith_unit.RND_SIZE)-1])); + + //cover secret key is shifted with req_digit + cover_req_digit_secret_key: cover property(disable iff(!reset_n || zeroize) + ecc_arith_unit.req_digit + ##1 + ecc_arith_unit.secret_key == $past({ecc_arith_unit.secret_key[(ecc_arith_unit.REG_SIZE+ecc_arith_unit.RND_SIZE)-2 : 0], ecc_arith_unit.secret_key[(ecc_arith_unit.REG_SIZE+ecc_arith_unit.RND_SIZE)-1]})); + + +endmodule + +bind ecc_arith_unit fv_ecc_arith_unit_coverpoints_m fv_ecc_arith_unit_coverpoints( + .clk(clk), + .reset_n(reset_n), + .zeroize(zeroize) +); \ No newline at end of file diff --git a/src/ecc/formal/properties/coverpoints/fv_ecc_dsa_ctrl_coverpoints.sv b/src/ecc/formal/properties/coverpoints/fv_ecc_dsa_ctrl_coverpoints.sv new file mode 100644 index 000000000..51915d28f --- /dev/null +++ b/src/ecc/formal/properties/coverpoints/fv_ecc_dsa_ctrl_coverpoints.sv @@ -0,0 +1,130 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_dsa_ctrl_coverpoints( + input logic clk, + input logic reset_n, + input logic zeroize +); + + + default clocking default_clk @(posedge clk); endclocking + + //cover zeroize + cover_zeroize: cover property(disable iff(!reset_n) ecc_dsa_ctrl.zeroize_reg ); + +//cover seed_reg + + cover_seed_reg_max: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.seed_reg == 384'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + cover_seed_reg_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.seed_reg =='0); + +//cover nonce_reg + + + cover_nonce_reg_max: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.nonce_reg== 384'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + cover_nonce_reg_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.nonce_reg =='0); + +//cover msg_reg + + cover_msg_reg_max: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.msg_reg == 384'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + cover_msg_reg_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.msg_reg =='0); + + +//cover privkey_reg + + cover_privkey_reg_less_grp_order: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.privkey_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973); + cover_privkey_reg_grt_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.privkey_reg >'0); + +//cover scalar_G_reg + + cover_scalar_G_reg_less_grp_order: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_G_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973); + cover_scalar_G_reg_grt_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_G_reg >'0); + cover_scalar_G_reg_grp_order_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_G_reg == 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972); + cover_scalar_G_reg_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_G_reg == 1); + +//cover scalar_PK_reg + + cover_scalar_PK_reg_less_grp_order: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_PK_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973); + cover_scalar_PK_reg_grt_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_PK_reg >'0); + cover_scalar_PK_reg_grp_order_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_PK_reg == 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972); + cover_scalar_PK_reg_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_PK_reg == 1); + +//cover r_reg + + cover_r_reg_less_grp_order: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.r_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973); + cover_r_reg_grt_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.r_reg >'0); + cover_r_reg_grp_order_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.r_reg == 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972); + cover_r_reg_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.r_reg == 1); + +//cover s_reg + cover_s_reg_less_grp_order: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.s_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973); + cover_s_reg_grt_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.s_reg >'0); + cover_s_reg_grp_order_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.s_reg == 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972); + cover_s_reg_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.s_reg == 1); + + +//cover IV_reg + cover_IV_reg_less_grp_order: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.IV_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973); + cover_IV_reg_grt_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.IV_reg >'0); + cover_IV_reg_grp_order_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.IV_reg == 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972); + cover_IV_reg_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.IV_reg == 1); + +//cover pubkeyx_reg + cover_pubkeyx_reg_less_prime: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.pubkeyx_reg < 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff); + cover_pubkeyx_reg_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.pubkeyx_reg =='0); + cover_pubkeyx_reg_prime_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.pubkeyx_reg == 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe); + cover_pubkeyx_reg_grt_prime: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.pubkeyx_reg > 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff); + +//cover pubkeyy_reg + cover_pubkeyy_reg_less_prime: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.pubkeyy_reg < 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff); + cover_pubkeyy_reg_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.pubkeyy_reg =='0); + cover_pubkeyy_reg_prime_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.pubkeyy_reg == 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe); + cover_pubkeyy_reg_grt_prime: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.pubkeyy_reg > 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff); + + +//cover scalar_out_reg + cover_scalar_out_reg_eq_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_out_reg==1); + cover_scalar_out_reg_grp_order_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_out_reg==384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972); + cover_scalar_out_reg_grp_mult: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_out_reg==(1+((2**192)-1)*384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973) ); + cover_scalar_out_reg_grp_order_mult_1: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.scalar_out_reg==(384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972 +((2**192)-1)*384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973) ); + + + +//cover lambda_reg + + cover_lambda_reg_max: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.lambda_reg == 384'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + cover_lambda_reg_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.lambda_reg =='0); + + + +//cover masking_rnd_reg + + cover_masking_rnd_reg_max: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.masking_rnd_reg == 384'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + cover_masking_rnd_reg_zero: cover property(disable iff(!reset_n || zeroize) ecc_dsa_ctrl.masking_rnd_reg =='0); + + + + + +endmodule + +bind ecc_dsa_ctrl fv_ecc_dsa_ctrl_coverpoints fv_ecc_dsa_ctrl_coverpoints_inst ( + .clk(clk), + .reset_n(reset_n), + .zeroize(ecc_dsa_ctrl.zeroize_reg) +); \ No newline at end of file diff --git a/src/ecc/formal/properties/coverpoints/fv_ecc_montgomerymultiplier_coverpoints.sv b/src/ecc/formal/properties/coverpoints/fv_ecc_montgomerymultiplier_coverpoints.sv new file mode 100644 index 000000000..feaf4d2a7 --- /dev/null +++ b/src/ecc/formal/properties/coverpoints/fv_ecc_montgomerymultiplier_coverpoints.sv @@ -0,0 +1,49 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_montgomerymultiplier_coverpoints_m( + input logic clk, + input logic reset_n, + input logic zeroize +); + + default clocking default_clk @(posedge clk); endclocking + +//Cover zeroize: + cover_zeroize: cover property(disable iff(!reset_n) ecc_montgomerymultiplier.zeroize ); + cover_prime_p: cover property(disable iff(!reset_n || zeroize) (ecc_montgomerymultiplier.n_i==384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff)); + cover_group_order: cover property(disable iff(!reset_n || zeroize)(ecc_montgomerymultiplier.n_i==384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973)); + cover_n_prime_i_prime_mu : cover property(disable iff(!reset_n|| zeroize) ecc_montgomerymultiplier.n_prime_i == 32'h00000001); + cover_n_prime_i_group_order_mu : cover property(disable iff(!reset_n|| zeroize) ecc_montgomerymultiplier.n_prime_i == 32'he88fdc45); + cover_opa_i_0 : cover property(disable iff(!reset_n|| zeroize) (ecc_montgomerymultiplier.opa_i == '0)&&(ecc_montgomerymultiplier.opb_i == '0 || ecc_montgomerymultiplier.opb_i == (ecc_montgomerymultiplier.n_i-1)) ); + cover_opa_i_prime_minus_1 : cover property(disable iff(!reset_n|| zeroize) (ecc_montgomerymultiplier.opa_i == (ecc_montgomerymultiplier.n_i-1))&&(ecc_montgomerymultiplier.opb_i == '0 || ecc_montgomerymultiplier.opb_i == (ecc_montgomerymultiplier.n_i-1)) ); + cover_opb_i_0 : cover property(disable iff(!reset_n|| zeroize) (ecc_montgomerymultiplier.opb_i == '0)&&(ecc_montgomerymultiplier.opa_i == '0 || ecc_montgomerymultiplier.opa_i == (ecc_montgomerymultiplier.n_i-1)) ); + cover_opb_i_prime_minus_1 : cover property(disable iff(!reset_n|| zeroize) (ecc_montgomerymultiplier.opb_i == (ecc_montgomerymultiplier.n_i-1))&&(ecc_montgomerymultiplier.opa_i == '0 || ecc_montgomerymultiplier.opa_i == (ecc_montgomerymultiplier.n_i-1)) ); + cover_sub_b_o_zero: cover property(disable iff(!reset_n || zeroize) ecc_montgomerymultiplier.ready_o && ecc_montgomerymultiplier.sub_b_o[2*(ecc_montgomerymultiplier.PE_UNITS+1)]==0); + cover_sub_b_o_one: cover property(disable iff(!reset_n || zeroize) ecc_montgomerymultiplier.ready_o && ecc_montgomerymultiplier.sub_b_o[2*(ecc_montgomerymultiplier.PE_UNITS+1)]== 1); + cover_p_sub_internal: cover property (disable iff(!reset_n || zeroize) !$past(!reset_n || zeroize) && ecc_montgomerymultiplier.ready_o && (ecc_montgomerymultiplier.p_subtracted_internal == ( ecc_montgomerymultiplier.p_internal - ecc_montgomerymultiplier.n_i))); + + + +endmodule + +bind ecc_montgomerymultiplier fv_ecc_montgomerymultiplier_coverpoints_m fv_ecc_montgomerymultiplier_coverpoints( + .clk(clk), + .reset_n(reset_n), + .zeroize(zeroize) +); \ No newline at end of file diff --git a/src/ecc/formal/properties/coverpoints/fv_ecc_pm_ctrl_coverpoints_m.sv b/src/ecc/formal/properties/coverpoints/fv_ecc_pm_ctrl_coverpoints_m.sv new file mode 100644 index 000000000..60c89d2a7 --- /dev/null +++ b/src/ecc/formal/properties/coverpoints/fv_ecc_pm_ctrl_coverpoints_m.sv @@ -0,0 +1,145 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_pm_ctrl_coverpoints_m import ecc_pm_uop_pkg::*;( + input logic clk, + input logic reset_n, + input logic zeroize +); + + default clocking default_clk @(posedge clk); endclocking + + //cover zeroize + cover_zeroize: cover property(disable iff(!reset_n) ecc_pm_ctrl.zeroize ); + + //cover sca_en_i + cover_sca_en_always: cover property(disable iff(!reset_n || zeroize) + ecc_pm_ctrl.sca_en_i ==1); + + + //cover req_digit when keygen cmd + cover_req_digit_keygen: cover property(disable iff(!reset_n || zeroize) + ecc_pm_ctrl.ecc_cmd_i==KEYGEN_CMD && + ecc_pm_ctrl.prog_cntr == NOP + ##1 + ecc_pm_ctrl.req_digit_o[->576]); + + //cover req_digit when signing cmd + cover_req_digit_signing: cover property(disable iff(!reset_n|| zeroize) + ecc_pm_ctrl.ecc_cmd_i==SIGN_CMD && + ecc_pm_ctrl.prog_cntr == NOP + ##1 + + ecc_pm_ctrl.req_digit_o[->576]); + + //cover req_digit when verifying cmd + cover_req_digit_verifying1: cover property(disable iff(!reset_n|| zeroize) + ecc_pm_ctrl.ecc_cmd_i== VER_PART1_CMD && + ecc_pm_ctrl.prog_cntr == NOP + ##1 + ecc_pm_ctrl.req_digit_o[->384]); + + cover_req_digit_verifying2: cover property(disable iff(!reset_n|| zeroize) + ecc_pm_ctrl.prog_cntr== PM_INIT_PK_S && + ecc_pm_ctrl.ecc_cmd_reg == VER_PART2_CMD + ##1 + ecc_pm_ctrl.req_digit_o[->384]); + + /* + // Keygen Sequence + + cover_keygen_sequence: cover property(disable iff(!reset_n || zeroize) keygen_sequence); + + sequence keygen_sequence; + ecc_pm_ctrl.ecc_cmd_i == KEYGEN_CMD + ##0 ecc_pm_ctrl.prog_cntr == NOP + ##1 ecc_pm_ctrl.prog_cntr == PM_INIT_G_S + ##123 ecc_pm_ctrl.prog_cntr == PM_INIT_S + ##16 ecc_pm_ctrl.prog_cntr == PA_S + ##789 ecc_pm_ctrl.prog_cntr == PD_S + ##910443 ecc_pm_ctrl.prog_cntr == INV_S + ##21201 ecc_pm_ctrl.prog_cntr == CONV_S + ##167 ecc_pm_ctrl.prog_cntr == CONV_E + ##1 ecc_pm_ctrl.prog_cntr == NOP; + endsequence + + + // Signing Sequence + + cover_signing_sequence: cover property(disable iff(!reset_n || zeroize) signing_sequence); + sequence signing_sequence; + ecc_pm_ctrl.ecc_cmd_i == SIGN_CMD + ##0 ecc_pm_ctrl.prog_cntr == NOP + ##1 ecc_pm_ctrl.prog_cntr == PM_INIT_G_S + ##123 ecc_pm_ctrl.prog_cntr == PM_INIT_S + ##16 ecc_pm_ctrl.prog_cntr == PA_S + ##789 ecc_pm_ctrl.prog_cntr == PD_S + ##910443 ecc_pm_ctrl.prog_cntr == INV_S + ##21201 ecc_pm_ctrl.prog_cntr == CONV_S + ##168 ecc_pm_ctrl.prog_cntr == SIGN0_S + ##311 ecc_pm_ctrl.prog_cntr == INVq_S + ##21205 ecc_pm_ctrl.prog_cntr == SIGN1_S + ##131 ecc_pm_ctrl.prog_cntr == NOP; + endsequence + + // Verify Sequence + cover_verify_part0_sequence: cover property(disable iff(!reset_n || zeroize) verify_part0_sequence); + sequence verify_part0_sequence; + ecc_pm_ctrl.ecc_cmd_i == VER_PART0_CMD + ##0 ecc_pm_ctrl.prog_cntr == NOP + ##1 ecc_pm_ctrl.prog_cntr == VER0_P0_S + ##127 ecc_pm_ctrl.prog_cntr == INVq_S + ##21205 ecc_pm_ctrl.prog_cntr == VER0_P1_S + ##168 ecc_pm_ctrl.prog_cntr == NOP; + endsequence + + cover_verify_part1_sequence: cover property(disable iff(!reset_n || zeroize) verify_part1_sequence); + sequence verify_part1_sequence; + ecc_pm_ctrl.ecc_cmd_i == VER_PART1_CMD + ##0 ecc_pm_ctrl.prog_cntr == NOP + ##1 ecc_pm_ctrl.prog_cntr == PM_INIT_G_S + ##123 ecc_pm_ctrl.prog_cntr == PM_INIT_S + ##16 ecc_pm_ctrl.prog_cntr == PA_S + ##789 ecc_pm_ctrl.prog_cntr == PD_S + ##606699 ecc_pm_ctrl.prog_cntr == NOP; + endsequence + + cover_verify_part2_sequence: cover property(disable iff(!reset_n || zeroize) verify_part2_sequence); + + sequence verify_part2_sequence; + ecc_pm_ctrl.ecc_cmd_i == VER_PART2_CMD + ##0 ecc_pm_ctrl.prog_cntr == NOP + ##1 ecc_pm_ctrl.prog_cntr == VER1_ST_S + ##12 ecc_pm_ctrl.prog_cntr == PM_INIT_PK_S + ##86 ecc_pm_ctrl.prog_cntr == PM_INIT_S + ##16 ecc_pm_ctrl.prog_cntr == PA_S + ##789 ecc_pm_ctrl.prog_cntr == PD_S + ##606699 ecc_pm_ctrl.prog_cntr == VER2_PA_S + ##793 ecc_pm_ctrl.prog_cntr == INV_S + ##21201 ecc_pm_ctrl.prog_cntr == CONV_S + ##168 ecc_pm_ctrl.prog_cntr == NOP; + endsequence + +*/ +endmodule + + bind ecc_pm_ctrl fv_ecc_pm_ctrl_coverpoints_m fv_ecc_pm_ctrl_coverpoints( + .clk(clk), + .reset_n(reset_n), + .zeroize(zeroize) + ); diff --git a/src/ecc/formal/properties/ecc_reduced_instantiations.sv b/src/ecc/formal/properties/ecc_reduced_instantiations.sv new file mode 100644 index 000000000..c292f3430 --- /dev/null +++ b/src/ecc/formal/properties/ecc_reduced_instantiations.sv @@ -0,0 +1,117 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +module ecc_reduced_instantiations #( + parameter REG_SIZE = 48, + parameter RADIX = 4 +) +( + // Clock and reset. + input wire clk, + input wire reset_n, + input wire zeroize, + + // DATA PORT + input wire start_i, + input wire [REG_SIZE-1:0] opa_i, + input wire [REG_SIZE-1:0] opb_i, + input wire [REG_SIZE-1:0] n_i, + input wire [RADIX-1:0] n_prime_i, // only need the last few bits + output logic [REG_SIZE-1:0] p_o, + output logic ready_o, + + input wire start_in, + // DATA PORT + input wire [RADIX-1:0] a_in, + input wire [RADIX-1:0] b_in, + input wire [RADIX-1:0] p_in, + input wire [RADIX-1:0] s_in, + input wire [RADIX-1:0] n_prime_in, + input wire odd, + + output logic [RADIX-1:0] a_out, + output logic [RADIX-1:0] m_out, + output logic [RADIX :0] c_out +); + +ecc_montgomerymultiplier #( + .REG_SIZE(48), + .RADIX(4) + ) + ecc_montmult_reduced ( + // Clock and reset. + .clk(clk), + .reset_n(reset_n), + .zeroize(zeroize), + + // DATA PORT + .start_i(start_i), + .opa_i(opa_i), + .opb_i(opb_i), + .n_i(n_i), + .n_prime_i(n_prime_i), + .p_o(p_o), + .ready_o(ready_o) + ); + +ecc_pe_first #(.RADIX(4)) ecc_pe_first_reduced( + .clk(clk), + .reset_n(reset_n), + .zeroize(zeroize), + + .start_in(start_in), + .a_in(a_in), + .b_in(b_in), + .p_in(p_in), + .s_in(s_in), + .n_prime_in(n_prime_in), + + .odd(odd), + .a_out(a_out), + .m_out(m_out), + + .c_out(c_out) + ); + + ecc_scalar_blinding #( + .REG_SIZE(24), + .RND_SIZE(12), + .RADIX(2) + ) + ecc_scalar_blinding_reduced( + .clk(clk), + .zeroize(zeroize), + .reset_n(reset_n), + .en_i(/* open */), + .data_i(/* open */), + .rnd_i(/* open */), + .data_o(/* open */), + .busy_o(/* open */) + ); + +endmodule + + +bind ecc_dsa_ctrl ecc_reduced_instantiations ecc_reduced_instantiation_inst ( + .clk(clk), + .reset_n(reset_n), + .zeroize(ecc_dsa_ctrl.zeroize_reg) +); + + diff --git a/src/ecc/formal/properties/fv_add_sub_alter.sv b/src/ecc/formal/properties/fv_add_sub_alter.sv new file mode 100644 index 000000000..dc283e0aa --- /dev/null +++ b/src/ecc/formal/properties/fv_add_sub_alter.sv @@ -0,0 +1,138 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_add_sub_alter_m( + input bit rst_n, + input bit clk, + input bit unsigned [383:0] opa_i, + input bit unsigned [383:0] opb_i, + input bit unsigned [383:0] prime_i, + input bit add_en_i, + input bit sub_en_i, + input bit unsigned [383:0] res_o, + input bit ready_o +); + +function logic[383:0] neg_mod (input logic[383:0] a,input logic[383:0] b,input logic[383:0] c); +logic[383:0] d; + if(a + res_o == 0 && + ready_o == 0; +endproperty + + + + +/////////////////////////////////////////////////////////// +// Property to check (a-b)%c, where the case it holds is // +// when we have add_en pulse,sub_i for 3 cycles // +/////////////////////////////////////////////////////////// + + + +sub_a: assert property (disable iff(!rst_n) sub_p); +property sub_p; +logic [383:0] fv_result; + ##0 add_en_i && sub_en_i + ##0 (1'b1, fv_result = neg_mod(opa_i,opb_i,prime_i)) +|-> + ##2 + (res_o== fv_result) && + (res_o < prime_i) && + ready_o + ; +endproperty + + +/////////////////////////////////////////////////////////// +// Property to check (a+b)%c, where the case it holds is // +// when we have add_en pulse,no sub_en_i for 3 cycles // +/////////////////////////////////////////////////////////// + + + + +add_a: assert property (disable iff(!rst_n) add_p); +property add_p; +logic [383:0] fv_result; + ##0 add_en_i && !sub_en_i + ##0 (1'b1, fv_result = ((385'(opa_i + opb_i)%prime_i))) +|-> + ##2 + res_o== fv_result && + (res_o < prime_i) && + ready_o + ; +endproperty + + +/////////////////////////////////////////////////////////////// +// Property to check the if there isn't any cmd for 2 // +// consecutive cycles then the res would have previous value // +// and ready should be deasserted +/////////////////////////////////////////////////////////////// + + + +no_cmd_a: assert property (disable iff(!rst_n) no_cmd_p); +property no_cmd_p; + !(add_en_i || sub_en_i) + ##1 + !(add_en_i || sub_en_i) +|=> + //res_o== $past(res_o) && + ready_o == 0 +; +endproperty + + +endmodule + + + +bind ecc_add_sub_mod_alter fv_add_sub_alter_m fv_add_sub_alter( + .rst_n(reset_n && !zeroize), + .clk(clk), + .opa_i(opa_i), + .opb_i(opb_i), + .prime_i(prime_i), + .add_en_i(add_en_i), + .sub_en_i(sub_i), + .res_o(res_o), + .ready_o(ready_o) +); diff --git a/src/ecc/formal/properties/fv_add_sub_constraints.sv b/src/ecc/formal/properties/fv_add_sub_constraints.sv new file mode 100644 index 000000000..53c6c327d --- /dev/null +++ b/src/ecc/formal/properties/fv_add_sub_constraints.sv @@ -0,0 +1,70 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_add_sub_constraints ( + input logic clk, + input logic rst_n, + + input logic add_en_i, + input logic sub_i, + input logic[383:0] prime_i, + input logic[383:0] opa_i, + input logic[383:0] opb_i + +); + +default clocking default_clk @(posedge clk); endclocking +//--------------------------------// +// Can be any of the 2 primes // +//--------------------------------// + +prime_as_p_q: assume property((prime_i==384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973) || (prime_i==384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff) ); + +//--------------------------------------// +// stable operands once cmd initiated // +//--------------------------------------// + +stable_operands: assume property(add_en_i |-> ((opa_i < prime_i) && (opb_i < prime_i) ##1($stable(opa_i) && $stable(opb_i) && $stable(prime_i))[*2])); + + +//----------------------------------------------// +// cmd sequence: // +// if add then no add and sub for next 2 cycles // +// if sub then no add but sub for next 2 cycles // +//----------------------------------------------// + +if_add_then_cmd_is_pulse: assume property(add_en_i && !sub_i|=> (!add_en_i && !sub_i )[*2]); +if_sub_then_stays_for_2cycles: assume property(add_en_i && sub_i |=> (!add_en_i && sub_i )[*2]); + + +//---------------------------------------------// +// Inputs zero during reset // +//----------------------------------------------// + +inputs_zero_during_reset: assume property($past(!rst_n) |-> opa_i==0 && opb_i==0 && !add_en_i && !sub_i); + +endmodule +bind ecc_add_sub_mod_alter fv_add_sub_constraints fv_constraints_m ( + .clk(clk), + .rst_n(reset_n && !zeroize), + .add_en_i(add_en_i), + .sub_i(sub_i), + .prime_i(prime_i), + .opa_i(opa_i), + .opb_i(opb_i) +); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_dsa_ctrl_constraints.sv b/src/ecc/formal/properties/fv_dsa_ctrl_constraints.sv new file mode 100644 index 000000000..09d962409 --- /dev/null +++ b/src/ecc/formal/properties/fv_dsa_ctrl_constraints.sv @@ -0,0 +1,204 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_dsa_ctrl_constraints_m + import ecc_params_pkg::*; + import ecc_dsa_uop_pkg::*; + import ecc_reg_pkg::*; + import kv_defines_pkg::*; #( + parameter PM_DLY = 5, + parameter SCA_DLY = 3, + parameter HMAC_DLY = 4 + ) + ( + // Clock and reset. + input wire clk, + input wire reset_n, + input wire cptra_pwrgood, + + // Reg ports. + input ecc_reg__out_t hwif_out, + input ecc_reg__in_t hwif_in, + + // KV interface + input kv_read_t [1:0] kv_read, + input kv_write_t kv_write, + input kv_rd_resp_t [1:0] kv_rd_resp, + input kv_wr_resp_t kv_wr_resp, + + //PCR Signing + input pcr_signing_t pcr_signing_data, + + // Interrupts (from ecc_reg) + input logic error_intr, + input logic notif_intr, + input logic debugUnlock_or_scan_mode_switch + ); + + default clocking default_clk @(posedge clk); endclocking + + //////////////////////////////////////////////////// + // stability of the primary inputs + //////////////////////////////////////////////////// + + logic fv_end_step; + logic fv_new_inp; + always_comb begin: end_step + fv_end_step = (ecc_dsa_ctrl.prog_cntr == DSA_KG_E-1)||(ecc_dsa_ctrl.prog_cntr == DSA_SGN_E-1)||(ecc_dsa_ctrl.prog_cntr == DSA_VER_E-1); + end + always_ff @(posedge clk, negedge reset_n) begin + if(!reset_n) begin + fv_new_inp <= 0; + end + else if (hwif_out.ECC_CTRL.ZEROIZE.value || debugUnlock_or_scan_mode_switch) begin + fv_new_inp <= 0; + end + else begin + if(hwif_in.ecc_ready) begin + fv_new_inp <= 1; + end + else if(fv_end_step) begin + fv_new_inp <= 0; + end + end + end + + + + + property stable_input_p(inp); + fv_new_inp |-> $stable(inp); + endproperty + +for (genvar word=0; word < 12; word++)begin + stable_privkey: assume property(stable_input_p(hwif_out.ECC_PRIVKEY_IN[11-word].PRIVKEY_IN.value)); + stable_seed: assume property(stable_input_p(hwif_out.ECC_SEED[11-word].SEED.value)); + stable_nonce: assume property(stable_input_p(hwif_out.ECC_NONCE[11-word].NONCE.value)); + stable_msg: assume property(stable_input_p(hwif_out.ECC_MSG[11-word].MSG.value)); + stable_pubkx: assume property(stable_input_p(hwif_out.ECC_PUBKEY_X[11-word].PUBKEY_X.value)); + stable_pubky: assume property(stable_input_p(hwif_out.ECC_PUBKEY_Y[11-word].PUBKEY_Y.value)); + stable_r: assume property(stable_input_p(hwif_out.ECC_SIGN_R[11-word].SIGN_R.value)); + stable_s: assume property(stable_input_p(hwif_out.ECC_SIGN_S[11-word].SIGN_S.value)); + stable_IV: assume property(stable_input_p(hwif_out.ECC_IV[11-word].IV.value)); + stable_cmd: assume property(stable_input_p(hwif_out.ECC_CTRL.CTRL.value)); + stable_pcr: assume property(stable_input_p(hwif_out.ECC_CTRL.PCR_SIGN.value)); +end + + + property no_cmd_when_not_ready_p; + !fv_new_inp + |-> + hwif_out.ECC_CTRL.CTRL.value == '0; + endproperty + + no_cmd: assume property(no_cmd_when_not_ready_p); + +`ifndef TOP + + //////////////////////////////////////////////////// + // Reduced working model for busy in order to check the + // design doesn't have deadlock + //////////////////////////////////////////////////// + + logic [5:0] pm_cntr; + logic [5:0] sca_cntr; + logic [5:0] hmac_cntr; + logic pm_busy; + logic sca_busy; + logic hmc_busy; + + always_ff @(posedge clk, negedge reset_n) begin + if(!reset_n) begin + pm_busy <= 0; + hmc_busy <= 0; + sca_busy <= 0; + pm_cntr <= 0; + hmac_cntr <= 0; + sca_cntr <= 0; + end + else if (hwif_out.ECC_CTRL.ZEROIZE.value || debugUnlock_or_scan_mode_switch) begin + pm_busy <= 0; + hmc_busy <= 0; + sca_busy <= 0; + pm_cntr <= 0; + hmac_cntr <= 0; + sca_cntr <= 0; + end + else begin + if(ecc_dsa_ctrl.pm_cmd_reg!=no_cmd)begin + pm_cntr <= PM_DLY; + end + if(ecc_dsa_ctrl.hmac_init) begin + hmac_cntr <= HMAC_DLY; + end + + if(ecc_dsa_ctrl.scalar_sca_en) begin + sca_cntr <= SCA_DLY; + end + if(pm_cntr > 0) begin + pm_busy <= 1; + pm_cntr <= pm_cntr-1; + end + if(pm_cntr == 0) begin + pm_busy <= 0; + end + if(sca_cntr > 0) begin + sca_busy <= 1; + sca_cntr <= sca_cntr-1; + end + if(sca_cntr == 0) begin + sca_busy <= 0; + end + if(hmac_cntr > 0) begin + hmc_busy <= 1; + hmac_cntr <= hmac_cntr-1; + end + if(hmac_cntr == 0) begin + hmc_busy <= 0; + end + end + end + + + pm_busy_assume: assume property(ecc_dsa_ctrl.pm_busy_o == pm_busy); + sca_busy_assume: assume property(ecc_dsa_ctrl.scalar_sca_busy_o == sca_busy); + hmac_busy_assume: assume property(ecc_dsa_ctrl.hmac_busy == hmc_busy); + +`endif + + +endmodule + +bind ecc_dsa_ctrl fv_dsa_ctrl_constraints_m fv_dsa_ctrl_constraints ( + .clk(clk), + .reset_n(reset_n), + .cptra_pwrgood(cptra_pwrgood), + + .hwif_out(hwif_out), + .hwif_in(hwif_in), + + .kv_read(kv_read), + .kv_rd_resp(kv_rd_resp), + .kv_write(kv_write), + .kv_wr_resp(kv_wr_resp), + .pcr_signing_data(pcr_signing_data), + + .error_intr(error_intr), + .notif_intr(notif_intr), + .debugUnlock_or_scan_mode_switch(debugUnlock_or_scan_mode_switch) + ); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_ecc_arith_unit.sv b/src/ecc/formal/properties/fv_ecc_arith_unit.sv new file mode 100644 index 000000000..674a06b54 --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_arith_unit.sv @@ -0,0 +1,263 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_arith_unit + #( + parameter REG_SIZE = 384, + parameter RND_SIZE = 192, + parameter RADIX = 32, + parameter ADDR_WIDTH = 6, + parameter [REG_SIZE-1 : 0] p_prime = 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff, + parameter [RADIX-1 : 0] p_mu = 32'h00000001, + parameter [REG_SIZE-1 : 0] q_grouporder = 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973, + parameter [RADIX-1 : 0] q_mu = 32'he88fdc45 + ) + ( + // Clock and reset. + input wire clk, + input wire rst_n, + + + // DATA PORT + input wire [2 : 0] ecc_cmd_i, + input wire sca_en_i, + input wire [ADDR_WIDTH-1 : 0] addr_i, + input wire wr_op_sel_i, + input wire wr_en_i, + input wire rd_reg_i, + input wire [(REG_SIZE+RND_SIZE)-1 : 0] data_i, + input wire [REG_SIZE-1: 0] data_o, + input wire busy_o + ); + + + default clocking default_clk @(posedge clk); endclocking + +no_busy_assume: assume property($past(!rst_n) |-> !ecc_arith_unit.ecc_busy_s); // used only when pm_ctrl is blackboxed + sequence reset_sequence; + !rst_n ##1 rst_n; + endsequence + + +//////////////////////////////////////////// +// reset property, when reset data_o // +// are zero // +//////////////////////////////////////////// + + + property reset_p; + $past(!rst_n) + |-> + busy_o == '0 && //open wire when black boxed + data_o == '0 && + ecc_arith_unit.reg_dinb_r == '0 && + ecc_arith_unit.reg_addr_r == '0 && + ecc_arith_unit.reg_web_r == 0 && + ecc_arith_unit.secret_key == '0; + endproperty + + reset_a : assert property(reset_p); + + +//////////////////////////////////////////// +// if read reg enabled then data_o has // +// the mem out of b // +//////////////////////////////////////////// + + property dout_p; + rd_reg_i + |=> + data_o == $past(ecc_arith_unit.opb_s); + endproperty + dout_a: assert property(disable iff(!rst_n) dout_p); + + property no_dout_p; + !rd_reg_i + |=> + data_o == '0; + endproperty + no_dout_a: assert property(disable iff(!rst_n) no_dout_p); + + +//////////////////////////////////////////// +// If busy then the mux determines inputs // +// for the ram // +//////////////////////////////////////////// + + + property busy_mux; + ecc_arith_unit.ecc_busy_s + |-> + ecc_arith_unit.addrb_mux_s == ecc_arith_unit.ecc_instr_s.opb_addr && + ecc_arith_unit.web_mux_s == ecc_arith_unit.ecc_instr_s.opcode.mult_we && + ecc_arith_unit.dinb_mux_s ==ecc_arith_unit.mult_res_s; + endproperty + + busy_mux_a: assert property(disable iff(!rst_n) busy_mux); + + +//If not busy then ram addrb takes addr_i + property not_busy_addr_mux_p; + !ecc_arith_unit.ecc_busy_s + |-> + ecc_arith_unit.addrb_mux_s == ecc_arith_unit.reg_addr_r; + + endproperty + not_busy_addr_mux_a: assert property(disable iff(!rst_n) not_busy_addr_mux_p); + + + +//If not busy and the previous cycle there isn't wr_op_sel then web takes wr_en_i + property not_busy_web_mux_p; + !wr_op_sel_i + ##1 !ecc_arith_unit.ecc_busy_s + |-> + ecc_arith_unit.web_mux_s == $past(wr_en_i); + endproperty + not_busy_web_mux_a: assert property(disable iff(!rst_n) not_busy_web_mux_p); + + + +//if not busy and in the previous clcok tick there is wr_en_i and no wr_op_sel then dinb takes data_i + property not_busy_dinb_mux_p; + wr_en_i && + !wr_op_sel_i + ##1 !ecc_arith_unit.ecc_busy_s + |-> + ecc_arith_unit.dinb_mux_s == REG_SIZE'($past(data_i)); + + endproperty + not_busy_dinb_mux_a: assert property(disable iff(!rst_n) not_busy_dinb_mux_p); + + +//If mod_q_sel is set then the prime should be selected as group order + property prime_selection_as_q_p; + ecc_arith_unit.ecc_instr_s.opcode.mod_q_sel + |-> + ecc_arith_unit.adder_prime == q_grouporder && + ecc_arith_unit.mult_mu == q_mu; + endproperty + prime_selection_as_q_a: assert property(disable iff(!rst_n)prime_selection_as_q_p); + +//If mod_q_sel is not set then the prime should be selected as the p (prime) + property prime_selection_as_p_p; + !ecc_arith_unit.ecc_instr_s.opcode.mod_q_sel + |-> + ecc_arith_unit.adder_prime == p_prime && + ecc_arith_unit.mult_mu == p_mu; + endproperty + prime_selection_as_p_a: assert property(disable iff(!rst_n)prime_selection_as_p_p); + +//If req_digit is set and no wr_en then the secret_key should be shifted + property req_digit_p; + ecc_arith_unit.req_digit && + !wr_en_i + |=> + ecc_arith_unit.secret_key == ($past({ecc_arith_unit.secret_key[(REG_SIZE+RND_SIZE)-2 : 0], ecc_arith_unit.secret_key[(REG_SIZE+RND_SIZE)-1]})); + endproperty + req_digit_a: assert property(disable iff(!rst_n)req_digit_p); + + +//If req_digit isn't set then and no wr_En then the secret_key should hold the previous value + property no_req_digit_p; + !ecc_arith_unit.req_digit && + !wr_en_i + |=> + ecc_arith_unit.secret_key == $past( ecc_arith_unit.secret_key); + endproperty + no_req_digit_a: assert property(disable iff(!rst_n) no_req_digit_p); + + +//If wr_en is set and the wr_op_Sel is set then secret_key should take the value of +//data_i and reg_dinb_r should hold the previous value + property wr_en_op_sel_p; + wr_en_i && + wr_op_sel_i + |=> + ecc_arith_unit.secret_key == $past(data_i)&& + ecc_arith_unit.reg_dinb_r == $past(ecc_arith_unit.reg_dinb_r); + endproperty + wr_en_op_sel_a: assert property(disable iff(!rst_n)wr_en_op_sel_p); + + +//If wr_en is set and the wr_op_Sel isn't set then secret_key shouldhold the previous value +//and reg_dinb_r should take the data_i + property wr_en_no_op_sel_p; + wr_en_i && + !wr_op_sel_i + |=> + ecc_arith_unit.secret_key == $past( ecc_arith_unit.secret_key) && + ecc_arith_unit.reg_dinb_r == $past(data_i[REG_SIZE-1 : 0]); + endproperty + wr_en_no_op_sel_a: assert property(disable iff(!rst_n)wr_en_no_op_sel_p); + + +//If no wr_En then reg_dinb_r should hold the previous value + property no_wr_en_i_p; + !wr_en_i + |=> + ecc_arith_unit.reg_dinb_r == $past(ecc_arith_unit.reg_dinb_r); + endproperty + no_wr_en_i_a: assert property(disable iff(!rst_n)no_wr_en_i_p); + + +//reg_addr_r always takes the addr_i + // Helper logic for reset reg to use in disable iff + logic fv_rst_n_reg; + always_ff @(posedge clk) begin + fv_rst_n_reg <= rst_n; + end + + property reg_addr_r_p; + ecc_arith_unit.reg_addr_r == $past(addr_i); + endproperty + reg_addr_r_a: assert property(disable iff(!rst_n || !fv_rst_n_reg)reg_addr_r_p); + + +//digit_in is always equal to the MSB bit of the secretkey, which when shifted becomes secret_key[0] + property digit_in_p; + ecc_arith_unit.digit_in == ecc_arith_unit.secret_key[0]; + endproperty + digit_in_a: assert property(disable iff(!rst_n)digit_in_p); + +endmodule + +bind ecc_arith_unit fv_ecc_arith_unit#( + .REG_SIZE(REG_SIZE), + .RND_SIZE(RND_SIZE), + .RADIX(RADIX), + .ADDR_WIDTH(ADDR_WIDTH), + .p_prime(p_prime), + .p_mu(p_mu), + .q_grouporder(q_grouporder), + .q_mu(q_mu) + ) + fv_ecc_arith_unit_inst ( + .clk(clk), + .rst_n(reset_n && !zeroize), + .ecc_cmd_i(ecc_cmd_i), + .sca_en_i(sca_en_i), + .addr_i(addr_i), + .wr_op_sel_i(wr_op_sel_i), + + .wr_en_i(wr_en_i), + .rd_reg_i(rd_reg_i), + .data_i(data_i), + .data_o(data_o), + .busy_o(busy_o) + ); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_ecc_dsa_ctrl.sv b/src/ecc/formal/properties/fv_ecc_dsa_ctrl.sv new file mode 100644 index 000000000..cf0a85a76 --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_dsa_ctrl.sv @@ -0,0 +1,1428 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_dsa_ctrl_m + import ecc_params_pkg::*; + import ecc_dsa_uop_pkg::*; + import ecc_reg_pkg::*; + import kv_defines_pkg::*; + ( + // Clock and reset. + input logic clk, + input logic reset_n, + input logic cptra_pwrgood, + // Reg ports. + input ecc_reg__out_t hwif_out, + input ecc_reg__in_t hwif_in, //output + + // KV interface + input kv_read_t [1:0] kv_read, //output + input kv_write_t kv_write, //output + input kv_rd_resp_t [1:0] kv_rd_resp, + input kv_wr_resp_t kv_wr_resp, + + //PCR Signing + input pcr_signing_t pcr_signing_data, + + // Interrupts (from ecc_reg) + input logic error_intr, //output + input logic notif_intr, //output + input logic debugUnlock_or_scan_mode_switch + ); + + localparam CYC_CNT = 4; // Equivalent to cycle count in DUT + + default clocking default_clk @(posedge clk); endclocking + + + //////////////////////////////////////////// + // Helper logic used for defining zeroize + //////////////////////////////////////////// + + logic fv_zeroize; + + always_comb begin: logic_zeroize + fv_zeroize = hwif_out.ECC_CTRL.ZEROIZE.value || debugUnlock_or_scan_mode_switch; + end + + //////////////////////////////////////////// + // Helper logic used in disabling the proofs + // once the error is set in the design + // then fv_error_set stays asserted until reset_n or zeroize + //////////////////////////////////////////// + + logic fv_error_set, fv_error; + always_ff @(posedge clk, negedge reset_n) begin + if(!reset_n) begin + fv_error_set <= 0; + end + else if(fv_zeroize) begin + fv_error_set <= 0; + end + else begin + if(ecc_dsa_ctrl.error_flag) begin + fv_error_set <= 1; + end + end + end + + + //////////////////////////////////////////// + // Helper logic for write_reg look up + + logic [(REG_SIZE+RND_SIZE)-1 : 0] fv_write_reg; + logic [DSA_OPR_ADDR_WIDTH-1:0] fv_reg_id; + + assign fv_reg_id = ecc_dsa_ctrl.prog_instr.reg_id; + + always_comb begin: fv_write_reg_logic + fv_write_reg = '0; + if(ecc_dsa_ctrl.prog_instr.opcode == DSA_UOP_WR_CORE) begin + unique casez (fv_reg_id) + CONST_ZERO_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ZERO_CONST}; + CONST_ONE_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ONE_CONST}; + CONST_E_a_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, E_a_MONT}; + CONST_E_b_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, E_b_MONT}; + CONST_E_3b_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, E_3b_MONT}; + CONST_ONE_p_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ONE_p_MONT}; + CONST_R2_p_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, R2_p_MONT}; + CONST_G_X_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, G_X_MONT}; + CONST_G_Y_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, G_Y_MONT}; + CONST_R2_q_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, R2_q_MONT}; + CONST_ONE_q_MONT_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ONE_q_MONT}; + MSG_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.msg_reduced_reg}; + PRIVKEY_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.privkey_reg}; + PUBKEYX_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.pubkeyx_reg}; + PUBKEYY_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.pubkeyy_reg}; + R_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.r_reg}; + S_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.s_reg}; + SCALAR_G_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.scalar_G_reg}; + LAMBDA_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.lambda_reg}; + MASKING_ID : fv_write_reg = {ecc_dsa_ctrl.zero_pad, ecc_dsa_ctrl.masking_rnd_reg}; + default : fv_write_reg = '0; + endcase + end + else if(ecc_dsa_ctrl.prog_instr.opcode == DSA_UOP_WR_SCALAR) begin + unique casez (fv_reg_id) + SCALAR_G_ID : fv_write_reg = (ecc_dsa_ctrl.scalar_G_reg << RND_SIZE); + SCALAR_PK_ID : fv_write_reg = (ecc_dsa_ctrl.scalar_PK_reg << RND_SIZE); + SCALAR_ID : fv_write_reg = ecc_dsa_ctrl.scalar_out_reg; // SCA + default : fv_write_reg = '0; + endcase + end + + end + + + //////////////////////////////////////////// + // Helper logic for read_reg look up + + logic [DSA_PROG_ADDR_W-1 : 0] fv_prog_cntr_reg; + logic fv_hw_privkey_we; + logic fv_hw_pubkeyx_we; + logic fv_hw_pubkeyy_we; + logic fv_hw_r_we; + logic fv_hw_s_we; + logic fv_hw_scalar_G_we ; + logic fv_hw_scalar_PK_we; + logic fv_hw_verify_r_we; + logic fv_hw_pk_chk_we; + + always_ff @(posedge clk) begin + fv_prog_cntr_reg <= ecc_dsa_ctrl.prog_cntr; + end + + always_comb begin: wr_en_logic + fv_hw_privkey_we = 0; + fv_hw_pubkeyx_we = 0; + fv_hw_pubkeyy_we = 0; + fv_hw_r_we = 0; + fv_hw_s_we = 0; + fv_hw_scalar_G_we = 0; + fv_hw_scalar_PK_we = 0; + fv_hw_verify_r_we = 0; + fv_hw_pk_chk_we = 0; + if (ecc_dsa_ctrl.prog_instr.opcode == DSA_UOP_RD_CORE && fv_prog_cntr_reg!= ecc_dsa_ctrl.prog_cntr) begin + unique casez (fv_reg_id) + PRIVKEY_ID : fv_hw_privkey_we = 1; + PUBKEYX_ID : fv_hw_pubkeyx_we = 1; + PUBKEYY_ID : fv_hw_pubkeyy_we = 1; + R_ID : fv_hw_r_we = 1; + S_ID : fv_hw_s_we = 1; + SCALAR_G_ID : fv_hw_scalar_G_we = 1; + SCALAR_PK_ID : fv_hw_scalar_PK_we = 1; + VERIFY_R_ID : fv_hw_verify_r_we = 1; + PK_VALID_ID : fv_hw_pk_chk_we = 1; + default : + begin + fv_hw_privkey_we = 0; + fv_hw_pubkeyx_we = 0; + fv_hw_pubkeyy_we = 0; + fv_hw_r_we = 0; + fv_hw_s_we = 0; + fv_hw_scalar_G_we = 0; + fv_hw_scalar_PK_we = 0; + fv_hw_verify_r_we = 0; + fv_hw_pk_chk_we = 0; + end + endcase + end + end + + sequence reset_sequence; + (!reset_n || fv_zeroize) ##1 reset_n && !fv_zeroize; + endsequence + + + //////////////////////////////////////////// + // reset property, when reset all the o/p // + // are zero // + //////////////////////////////////////////// + + property reset_p; + $past(!reset_n || fv_zeroize) + |-> + + ecc_dsa_ctrl.prog_cntr == DSA_RESET && + ecc_dsa_ctrl.cycle_cnt == '0 && + ecc_dsa_ctrl.pm_cmd_reg == '0 && + hwif_in.ECC_STATUS.VALID.next == '0 && + ecc_dsa_ctrl.scalar_G_sel == '0 && + ecc_dsa_ctrl.hmac_mode == '0 && + ecc_dsa_ctrl.hmac_init == '0 && + ecc_dsa_ctrl.scalar_sca_en == '0 && + ecc_dsa_ctrl.keygen_process == '0 && + ecc_dsa_ctrl.signing_process == '0 && + ecc_dsa_ctrl.scalar_G_reg == '0 && + ecc_dsa_ctrl.scalar_PK_reg == '0 && + ecc_dsa_ctrl.pk_chk_reg == '0 && + ecc_dsa_ctrl.kv_reg == '0 && + ecc_dsa_ctrl.scalar_in_reg == '0 && + ecc_dsa_ctrl.verifying_process == '0 && + ecc_dsa_ctrl.kv_read_data_present == '0; + endproperty + + reset_a : assert property(reset_p); + + + //////////////////////////////////////////// + // zeroize property, when set the resp. o/p // + // are zero // + //////////////////////////////////////////// + + + property zeroize_p(word); + (fv_zeroize) + |-> + hwif_in.ECC_PRIVKEY_IN[word].PRIVKEY_IN.hwclr && + hwif_in.ECC_PRIVKEY_OUT[word].PRIVKEY_OUT.hwclr && + hwif_in.ECC_NONCE[word].NONCE.hwclr && + hwif_in.ECC_MSG[word].MSG.hwclr && + hwif_in.ECC_PUBKEY_X[word].PUBKEY_X.hwclr && + hwif_in.ECC_PUBKEY_Y[word].PUBKEY_Y.hwclr && + hwif_in.ECC_SIGN_R[word].SIGN_R.hwclr && + hwif_in.ECC_SIGN_S[word].SIGN_S.hwclr && + hwif_in.ECC_VERIFY_R[word].VERIFY_R.hwclr && + hwif_in.ECC_IV[word].IV.hwclr && + hwif_in.ECC_SEED[word].SEED.hwclr ; + endproperty + + + property no_zeroize_p(word); + !(fv_zeroize) + |-> + ! hwif_in.ECC_PRIVKEY_IN[word].PRIVKEY_IN.hwclr && + ! hwif_in.ECC_PRIVKEY_OUT[word].PRIVKEY_OUT.hwclr && + ! hwif_in.ECC_NONCE[word].NONCE.hwclr && + ! hwif_in.ECC_MSG[word].MSG.hwclr && + ! hwif_in.ECC_PUBKEY_X[word].PUBKEY_X.hwclr && + ! hwif_in.ECC_PUBKEY_Y[word].PUBKEY_Y.hwclr && + ! hwif_in.ECC_SIGN_R[word].SIGN_R.hwclr && + ! hwif_in.ECC_VERIFY_R[word].VERIFY_R.hwclr && + ! hwif_in.ECC_IV[word].IV.hwclr; + endproperty + + + // seed clr when there isn't any zeroize depends on the keyvault read status + property no_zeroize_seed_clr_p(word); + !(fv_zeroize) + |-> + hwif_in.ECC_SEED[word].SEED.hwclr == (ecc_dsa_ctrl.privkey_out_we && ecc_dsa_ctrl.kv_read_data_present); + endproperty + + for(genvar i=0 ;i< REG_NUM_DWORDS;i++) begin + no_zeroize_a: assert property(no_zeroize_p(i)); + zeroize_a: assert property(zeroize_p(i)); + no_zeroize_seed_clr_a: assert property(disable iff(fv_error_set)no_zeroize_seed_clr_p(i)); + end + + + + + // Store constant values once the reset or zeorize triggered. + + + property store_const_after_reset_p; + ecc_dsa_ctrl.prog_cntr == DSA_RESET + |-> + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 1 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 2 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 3 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 4 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 5 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 6 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 7 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 8 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 9 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 10 + ##CYC_CNT ecc_dsa_ctrl.prog_cntr == 11; + endproperty + store_const_after_reset_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)store_const_after_reset_p); + + + property store_const_end_p; + (ecc_dsa_ctrl.prog_cntr == 11) [*CYC_CNT] + |=> + ecc_dsa_ctrl.prog_cntr == DSA_NOP; + endproperty + + store_const_end_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)store_const_end_p); + + + // Before start of operations these constants are stored and stays stable until unless reset or zeroize + property stable_const_mem_p; + ecc_dsa_ctrl.prog_cntr >= DSA_NOP + |-> + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[0]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[1]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[2]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[3]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[4]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[5]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[6]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[7]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[28]) && + $stable(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.mem[29]); + endproperty + stable_const_mem_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)stable_const_mem_p); + + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [DSA_PROG_ADDR_W-1 : 0] counter_const_a, counter_const_b; + logic triggered_counter_const_a,triggered_counter_const_b; + + + counter_const_a_assume: assume property(disable iff(!reset_n || fv_zeroize) (counter_const_a >=0) && (counter_const_a <=DSA_NOP) && $stable(counter_const_a)); + counter_const_b_assume: assume property(disable iff(!reset_n || fv_zeroize) (counter_const_b <=DSA_NOP) && (counter_const_b > counter_const_a) && $stable(counter_const_b)); + + + always_ff @(posedge clk, negedge reset_n) begin + if(!reset_n ||fv_zeroize ) begin + triggered_counter_const_a <= 0; + triggered_counter_const_b <= 0; + end + else begin + + if(ecc_dsa_ctrl.prog_cntr==counter_const_a) + triggered_counter_const_a <=1; + if (ecc_dsa_ctrl.prog_cntr==counter_const_b) + triggered_counter_const_b <= 1; + end + end + + + property counter_const_liveness_p(trigered); + ecc_dsa_ctrl.prog_cntr == DSA_RESET && + !(ecc_dsa_ctrl.error_flag_edge) && + !(ecc_dsa_ctrl.subcomponent_busy) + |-> + s_eventually(trigered); + endproperty + + counter_const_a_liveness_a: assert property(disable iff(!reset_n || fv_zeroize|| fv_error_set)counter_const_liveness_p(triggered_counter_const_a)); + counter_const_b_liveness_a: assert property(disable iff(!reset_n || fv_zeroize|| fv_error_set) counter_const_liveness_p(triggered_counter_const_b)); + + + property order_check_p(triggered_a,triggered_b); + triggered_b + |=> + $past(triggered_a); + endproperty + counter_integrity_const_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) order_check_p(triggered_counter_const_a,triggered_counter_const_b)); + + + + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + +`ifdef REDUCED_PM_CTRL + + // This property works on the reduced version of the pm_ctrl + property keygen_sequence_p; + hwif_out.ECC_CTRL.CTRL.value == KEYGEN && + ecc_dsa_ctrl.prog_cntr == DSA_NOP && + !(ecc_dsa_ctrl.error_flag_edge) && + !(ecc_dsa_ctrl.subcomponent_busy) + |=> + ecc_dsa_ctrl.prog_cntr == DSA_KG_S + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 1 + ##2 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 2 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 3 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 4 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 5 + ##2 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 6 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 7 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 8 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 9 + ##26 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 10 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 11 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_KG_S+ 12 + ; + endproperty + + keygen_sequence_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)keygen_sequence_p); + `endif + + + // Proves the liveliness that once the cmd is triggered eventually it would have a valid + property sequence_valid_p(cmd); + hwif_out.ECC_CTRL.CTRL.value == cmd && + ecc_dsa_ctrl.prog_cntr == DSA_NOP && + !(ecc_dsa_ctrl.error_flag_edge) && + !(ecc_dsa_ctrl.subcomponent_busy) + |-> + s_eventually(hwif_in.ECC_STATUS.VALID.next); + endproperty + + keygen_sequence_valid_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)sequence_valid_p(KEYGEN)); + signing_sequence_valid_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)sequence_valid_p(SIGN)); + verify_sequence_valid_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)sequence_valid_p(VERIFY)); + + + // At the last step of the cmd sequence, the valid signal should be asserted + property valid_set_end_seq_p(end_st); + ecc_dsa_ctrl.prog_cntr == end_st + ##1 ecc_dsa_ctrl.prog_cntr != fv_prog_cntr_reg + |-> + hwif_in.ECC_STATUS.VALID.next; + endproperty + keygen_valid_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)valid_set_end_seq_p(DSA_KG_E)); + signing_valid_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)valid_set_end_seq_p(DSA_SGN_E)); + verify_valid_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)valid_set_end_seq_p(DSA_VER_E)); + + + //If the prog_cntr isn't in last step of the sequences and the DSA_NOP then valid should be deasserted + property no_valid_p; + (ecc_dsa_ctrl.prog_cntr != DSA_KG_E && + ecc_dsa_ctrl.prog_cntr != DSA_SGN_E && + ecc_dsa_ctrl.prog_cntr != DSA_VER_E && + ecc_dsa_ctrl.prog_cntr != DSA_NOP) //Review: After the completion of seq. if no new input is set then the valid stays + |=> + !hwif_in.ECC_STATUS.VALID.next; + endproperty + no_valid_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)no_valid_p); + + // TODO: ready and valid together + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [DSA_PROG_ADDR_W-1 : 0] counter_keygen_a, counter_keygen_b; + logic triggered_counter_keygen_a,triggered_counter_keygen_b; + + + counter_keygen_a_assume: assume property(disable iff(!reset_n || fv_zeroize) (counter_keygen_a >=DSA_KG_S) && (counter_keygen_a <=DSA_KG_E) && $stable(counter_keygen_a)); + counter_keygen_b_assume: assume property(disable iff(!reset_n || fv_zeroize) (counter_keygen_b <=DSA_KG_E) && (counter_keygen_b > counter_keygen_a) && $stable(counter_keygen_b)); + + + always_ff @(posedge clk, negedge reset_n) begin + if(!reset_n ||fv_zeroize ) begin + triggered_counter_keygen_a <= 0; + triggered_counter_keygen_b <= 0; + end + else begin + + if(ecc_dsa_ctrl.prog_cntr==counter_keygen_a) + triggered_counter_keygen_a <=1; + if (ecc_dsa_ctrl.prog_cntr==counter_keygen_b) + triggered_counter_keygen_b <= 1; + end + end + + property counter_liveness_p(cmd,trigered); + hwif_out.ECC_CTRL.CTRL.value == cmd && + ecc_dsa_ctrl.prog_cntr == DSA_NOP && + !(ecc_dsa_ctrl.error_flag_edge) && + !(ecc_dsa_ctrl.subcomponent_busy) + |-> + s_eventually(trigered); + endproperty + + counter_keygen_a_liveness_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)counter_liveness_p(KEYGEN,triggered_counter_keygen_a)); + counter_keygen_b_liveness_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) counter_liveness_p(KEYGEN,triggered_counter_keygen_b)); + + counter_keygen_integrity_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) order_check_p(triggered_counter_keygen_a,triggered_counter_keygen_b)); + + + + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + +`ifdef REDUCED_PM_CTRL + // This property works on the reduced version of the pm_ctrl + property signing_sequence_p; + hwif_out.ECC_CTRL.CTRL.value == SIGN && + ecc_dsa_ctrl.prog_cntr == DSA_NOP && + !(ecc_dsa_ctrl.error_flag_edge) && + !(ecc_dsa_ctrl.subcomponent_busy) + |=> + ecc_dsa_ctrl.prog_cntr == DSA_SGN_S + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 1 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 2 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 3 + ##2 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 4 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 5 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 6 + ##2 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 7 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 8 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 9 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 10 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 11 + ##39 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 12 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 13 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_SGN_S+ 14 + ; + endproperty + + signing_sequence_a: assert property(disable iff(!reset_n || fv_zeroize || ecc_dsa_ctrl.error_flag_edge)signing_sequence_p); +`endif + + + + + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [DSA_PROG_ADDR_W-1 : 0] counter_sign_a, counter_sign_b; + logic triggered_counter_sign_a,triggered_counter_sign_b; + + + counter_sign_a_assume: assume property(disable iff(!reset_n || fv_zeroize) (counter_sign_a >=DSA_SGN_S) && (counter_sign_a <=DSA_SGN_E) && $stable(counter_sign_a)); + counter_sign_b_assume: assume property(disable iff(!reset_n || fv_zeroize) (counter_sign_b <=DSA_SGN_E) && (counter_sign_b > counter_sign_a) && $stable(counter_sign_b)); + + always_ff @(posedge clk, negedge reset_n) begin + if(!reset_n || fv_zeroize ) begin + triggered_counter_sign_a <= 0; + triggered_counter_sign_b <= 0; + end + else begin + + if(ecc_dsa_ctrl.prog_cntr==counter_sign_a) + triggered_counter_sign_a <=1; + if (ecc_dsa_ctrl.prog_cntr==counter_sign_b) + triggered_counter_sign_b <= 1; + end + end + + + counter_sign_a_liveness_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)counter_liveness_p(SIGN,triggered_counter_sign_a)); + counter_sign_b_liveness_a: assert property(disable iff(!reset_n || fv_zeroize|| fv_error_set) counter_liveness_p(SIGN,triggered_counter_sign_b)); + + counter_integrity_sign_a: assert property(disable iff(!reset_n || fv_zeroize|| fv_error_set) order_check_p(triggered_counter_sign_a,triggered_counter_sign_b)); + + + + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + `ifdef REDUCED_PM_CTRL + // This property works on the reduced version of the pm_ctrl + property verify_sequence_p; + hwif_out.ECC_CTRL.CTRL.value == VERIFY && + ecc_dsa_ctrl.prog_cntr == DSA_NOP && + !(ecc_dsa_ctrl.error_flag_edge) && + !(ecc_dsa_ctrl.subcomponent_busy) + |=> + ecc_dsa_ctrl.prog_cntr == DSA_VER_S + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 1 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 2 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 3 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 4 + ##42 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 5 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 6 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 7 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 8 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 9 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 10 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 11 + ##14 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 12 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 13 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 14 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 15 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 16 + ##18 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 17 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 18 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 19 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 20 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 21 + ##34 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 22 + ##4 ecc_dsa_ctrl.prog_cntr == DSA_VER_S+ 23 + ; + endproperty + + verify_sequence_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)verify_sequence_p); +`endif + + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [DSA_PROG_ADDR_W-1 : 0] counter_verify_a, counter_verify_b; + logic triggered_counter_verify_a,triggered_counter_verify_b; + + + counter_verify_a_assume: assume property(disable iff(!reset_n || fv_zeroize) (counter_verify_a >=DSA_SGN_S) && (counter_verify_a <=DSA_SGN_E) && $stable(counter_verify_a)); + counter_verify_b_assume: assume property(disable iff(!reset_n || fv_zeroize) (counter_verify_b <=DSA_SGN_E) && (counter_verify_b > counter_verify_a) && $stable(counter_verify_b)); + + always_ff @(posedge clk, negedge reset_n) begin + if(!reset_n ||fv_zeroize ) begin + triggered_counter_verify_a <= 0; + triggered_counter_verify_b <= 0; + end + else begin + + if(ecc_dsa_ctrl.prog_cntr==counter_verify_a) + triggered_counter_verify_a <=1; + if (ecc_dsa_ctrl.prog_cntr==counter_verify_b) + triggered_counter_verify_b <= 1; + end + end + + + counter_verify_a_liveness_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)counter_liveness_p(VERIFY,triggered_counter_verify_a)); + counter_verify_b_liveness_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) counter_liveness_p(VERIFY,triggered_counter_verify_b)); + + counter_integrity_verify_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) order_check_p(triggered_counter_verify_a,triggered_counter_verify_b)); + + + + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + + + + + + //---------------------------------------------------------------------// + // Primary output // + //---------------------------------------------------------------------// + + + //Primary outputs connect to primary inputs + property output_directconnection_input_p; + hwif_in.reset_b == reset_n && + hwif_in.hard_reset_b == cptra_pwrgood && + hwif_in.ECC_NAME[0].NAME.next == ECC_CORE_NAME[31 : 0] && + hwif_in.ECC_NAME[1].NAME.next == ECC_CORE_NAME[63 : 32] && + hwif_in.ECC_VERSION[0].VERSION.next == ECC_CORE_VERSION[31 : 0] && + hwif_in.ECC_VERSION[1].VERSION.next == ECC_CORE_VERSION[63 : 32] && + error_intr == hwif_out.intr_block_rf.error_global_intr_r.intr && + notif_intr == hwif_out.intr_block_rf.notif_global_intr_r.intr && + hwif_in.ECC_CTRL.CTRL.hwclr == |hwif_out.ECC_CTRL.CTRL.value && + hwif_in.ECC_CTRL.PCR_SIGN.hwclr == hwif_out.ECC_CTRL.PCR_SIGN.value; + endproperty + + output_directconnection_input_a: assert property(output_directconnection_input_p); + + + // Primary outputs connected to the submodule outputs, here it is read_reg + property output_connectedto_submodules_p(word); + hwif_in.ECC_PRIVKEY_OUT[word].PRIVKEY_OUT.next == ecc_dsa_ctrl.read_reg[(REG_NUM_DWORDS-1)- word]&& + hwif_in.ECC_SEED[word].SEED.next == ecc_dsa_ctrl.kv_seed_write_data && + hwif_in.ECC_MSG[word].MSG.next == pcr_signing_data.pcr_hash[word] && + hwif_in.ECC_PUBKEY_Y[word].PUBKEY_Y.next == ecc_dsa_ctrl.read_reg[(REG_NUM_DWORDS-1)- word] && + hwif_in.ECC_SIGN_R[word].SIGN_R.next == ecc_dsa_ctrl.read_reg[(REG_NUM_DWORDS-1)- word] && + hwif_in.ECC_SIGN_S[word].SIGN_S.next == ecc_dsa_ctrl.read_reg[(REG_NUM_DWORDS-1)- word] && + hwif_in.ECC_VERIFY_R[word].VERIFY_R.next == ecc_dsa_ctrl.read_reg[(REG_NUM_DWORDS-1)- word] && + hwif_in.ECC_PUBKEY_X[word].PUBKEY_X.next == ecc_dsa_ctrl.read_reg[(REG_NUM_DWORDS-1)- word]; + endproperty + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + output_connectedto_submodules_a: assert property(output_connectedto_submodules_p(i)); + end + + + // If pcr sign is set then msg we and privkey_in we should be ! zeroize and privkey_in should take data from pcr_Signing + property pcr_sign_mode_p(word); + hwif_out.ECC_CTRL.PCR_SIGN.value + |-> + hwif_in.ECC_MSG[word].MSG.we == !(fv_zeroize) && + hwif_in.ECC_PRIVKEY_IN[word].PRIVKEY_IN.next == pcr_signing_data.pcr_signing_privkey[word] && + hwif_in.ECC_PRIVKEY_IN[word].PRIVKEY_IN.we == !(fv_zeroize) + ; + endproperty + + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + pcr_sign_mode_a: assert property(pcr_sign_mode_p(i)); + end + + + // If pcr sign isn't enabled then for msg no we and privkey_in is dependent on keyvault write_en + property no_pcr_sign_mode_p(word); + !hwif_out.ECC_CTRL.PCR_SIGN.value + |-> + !hwif_in.ECC_MSG[word].MSG.we && + hwif_in.ECC_PRIVKEY_IN[word].PRIVKEY_IN.next == (ecc_dsa_ctrl.kv_privkey_write_en ? ecc_dsa_ctrl.kv_privkey_write_data : ecc_dsa_ctrl.read_reg[(REG_NUM_DWORDS-1)-word] )&& + hwif_in.ECC_PRIVKEY_IN[word].PRIVKEY_IN.we == ((ecc_dsa_ctrl.kv_privkey_write_en & (ecc_dsa_ctrl.kv_privkey_write_offset == word)) & !(fv_zeroize)) + ; + endproperty + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + no_pcr_sign_mode_a: assert property(no_pcr_sign_mode_p(i)); + end + + + //If privkey_out i.e reading from the reg after the privkey computation and + //if the seed is not rom the keyvault then privkey_out we is equal to !zeroize + property privkey_out_we_p(word); + ecc_dsa_ctrl.privkey_out_we && + !(ecc_dsa_ctrl.dest_keyvault | ecc_dsa_ctrl.kv_read_data_present) + |-> + hwif_in.ECC_PRIVKEY_OUT[word].PRIVKEY_OUT.we == !(fv_zeroize); + endproperty + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + privkey_out_we_a: assert property(disable iff(fv_error_set) privkey_out_we_p(i)); + end + + + //If no privkey_out or keyvault is choose as desitination then prvkey_out we is deasserted + property no_privkey_out_we_p(word); + (!ecc_dsa_ctrl.privkey_out_we || + (ecc_dsa_ctrl.dest_keyvault | ecc_dsa_ctrl.kv_read_data_present)) + |-> + !hwif_in.ECC_PRIVKEY_OUT[word].PRIVKEY_OUT.we ; + endproperty + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + no_privkey_out_we_a: assert property(no_privkey_out_we_p(i)); + end + + + // if keyvault write is enabled and offset is equal to each word the seed we is equal to !zeroize + property seed_we_p(word); + (ecc_dsa_ctrl.kv_seed_write_en && + (ecc_dsa_ctrl.kv_seed_write_offset == word)) + |-> + hwif_in.ECC_SEED[word].SEED.we == !(fv_zeroize); + endproperty + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + seed_we_a: assert property(seed_we_p(i)); + end + + + // if keyvault write is not enabled and offset is not equal to each word then seed we is deasserted + property no_seed_we_p(word); + (!ecc_dsa_ctrl.kv_seed_write_en || + (ecc_dsa_ctrl.kv_seed_write_offset != word)) + |-> + !hwif_in.ECC_SEED[word].SEED.we; + endproperty + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + no_seed_we_a: assert property(no_seed_we_p(i)); + end + + + // Rest we are triggered with rd_core opcode and cycle_cnt=0 + property rd_core_we_p(word); + hwif_in.ECC_PUBKEY_X[word].PUBKEY_X.we == (fv_hw_pubkeyx_we & !(fv_zeroize)) && + hwif_in.ECC_PUBKEY_Y[word].PUBKEY_Y.we == (fv_hw_pubkeyy_we & !(fv_zeroize)) && + hwif_in.ECC_SIGN_S[word].SIGN_S.we == (fv_hw_s_we & !(fv_zeroize)) && + hwif_in.ECC_VERIFY_R[word].VERIFY_R.we == (fv_hw_verify_r_we & !(fv_zeroize)) && + hwif_in.ECC_SIGN_R[word].SIGN_R.we == (fv_hw_r_we & !(fv_zeroize)); + endproperty + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + rd_core_we_a: assert property(disable iff(fv_error_set)rd_core_we_p(i)); + end + + + // keyvault privkey read ctrl reg is connected to primary input kv_rd_pkey_ctrl + property kv_privkey_read_ctrl_reg_p; + ecc_dsa_ctrl.kv_privkey_read_ctrl_reg.rsvd == '0 && + ecc_dsa_ctrl.kv_privkey_read_ctrl_reg.pcr_hash_extend == hwif_out.ecc_kv_rd_pkey_ctrl.pcr_hash_extend.value && + ecc_dsa_ctrl.kv_privkey_read_ctrl_reg.read_entry == hwif_out.ecc_kv_rd_pkey_ctrl.read_entry.value && + ecc_dsa_ctrl.kv_privkey_read_ctrl_reg.read_en == hwif_out.ecc_kv_rd_pkey_ctrl.read_en.value; + endproperty + + kv_privkey_read_ctrl_reg_a: assert property(kv_privkey_read_ctrl_reg_p); + + + // keyvault seed read ctrl reg is connected to primary input kv_rd_seed_ctrl + property kv_seed_read_ctrl_reg_p; + ecc_dsa_ctrl.kv_seed_read_ctrl_reg.rsvd == '0 && + ecc_dsa_ctrl.kv_seed_read_ctrl_reg.pcr_hash_extend == hwif_out.ecc_kv_rd_seed_ctrl.pcr_hash_extend.value && + ecc_dsa_ctrl.kv_seed_read_ctrl_reg.read_entry == hwif_out.ecc_kv_rd_seed_ctrl.read_entry.value && + ecc_dsa_ctrl.kv_seed_read_ctrl_reg.read_en == hwif_out.ecc_kv_rd_seed_ctrl.read_en.value; + endproperty + + kv_seed_read_ctrl_reg_a: assert property(kv_seed_read_ctrl_reg_p); + + + // keyvault write ctrl reg is connected to primary input kv_wr_pkey_ctrl + property kv_write_ctrl_reg_p; + ecc_dsa_ctrl.kv_write_ctrl_reg.rsvd == '0 && + ecc_dsa_ctrl.kv_write_ctrl_reg.write_dest_vld[0] == hwif_out.ecc_kv_wr_pkey_ctrl.hmac_key_dest_valid.value && + ecc_dsa_ctrl.kv_write_ctrl_reg.write_dest_vld[1] == hwif_out.ecc_kv_wr_pkey_ctrl.hmac_block_dest_valid.value && + ecc_dsa_ctrl.kv_write_ctrl_reg.write_dest_vld[2] == hwif_out.ecc_kv_wr_pkey_ctrl.sha_block_dest_valid.value && + ecc_dsa_ctrl.kv_write_ctrl_reg.write_dest_vld[3] == hwif_out.ecc_kv_wr_pkey_ctrl.ecc_pkey_dest_valid.value && + ecc_dsa_ctrl.kv_write_ctrl_reg.write_dest_vld[4] == hwif_out.ecc_kv_wr_pkey_ctrl.ecc_seed_dest_valid.value && + ecc_dsa_ctrl.kv_write_ctrl_reg.write_entry == hwif_out.ecc_kv_wr_pkey_ctrl.write_entry.value && + ecc_dsa_ctrl.kv_write_ctrl_reg.write_en == hwif_out.ecc_kv_wr_pkey_ctrl.write_en.value; + endproperty + + kv_write_ctrl_reg_a: assert property(kv_write_ctrl_reg_p); + + + // kv_read data present stays asserted until privkey is generated if read_en of kv is set + property kv_read_data_present_p; + ecc_dsa_ctrl.kv_seed_read_ctrl_reg.read_en + |=> + ecc_dsa_ctrl.kv_read_data_present until_with ecc_dsa_ctrl.privkey_out_we; + endproperty + kv_read_data_present_a: assert property(disable iff(!reset_n || fv_zeroize) kv_read_data_present_p); + + + // Once kv_read_data_present is set then it deasserts if privkey is ready to be read and no new read_en + property no_kv_read_data_present_p; + ecc_dsa_ctrl.kv_read_data_present && + ecc_dsa_ctrl.privkey_out_we && + !ecc_dsa_ctrl.kv_seed_read_ctrl_reg.read_en //Review: Fails because if read_en is continously high then it won't be deasserted. + |=> + !ecc_dsa_ctrl.kv_read_data_present; + endproperty + no_kv_read_data_present_a: assert property(disable iff(!reset_n || fv_zeroize) no_kv_read_data_present_p); + + + // If privkey is ready to read and keyvault is choosen as destination then kv_reg will have the privkey + property kv_reg_p; + ecc_dsa_ctrl.privkey_out_we && + (ecc_dsa_ctrl.dest_keyvault | ecc_dsa_ctrl.kv_read_data_present) + |=> + ecc_dsa_ctrl.kv_reg == $past(ecc_dsa_ctrl.read_reg); + endproperty + + kv_reg_a: assert property(disable iff(!reset_n || fv_zeroize)kv_reg_p); + + + // kv_reg stays stable if privkey isn't ready or kv is not choosen as dest. + property stable_kv_reg_p; + !ecc_dsa_ctrl.privkey_out_we || + !(ecc_dsa_ctrl.dest_keyvault | ecc_dsa_ctrl.kv_read_data_present) + |=> + ecc_dsa_ctrl.kv_reg == $past(ecc_dsa_ctrl.kv_reg); + endproperty + + stable_kv_reg_a: assert property(disable iff(!reset_n || fv_zeroize)stable_kv_reg_p); + + + + // Primary outputs directly connected to kv(submodule) outputs + property primaryout_connected_to_kvout_p; + hwif_in.ecc_kv_rd_pkey_status.ERROR.next == ecc_dsa_ctrl.kv_privkey_error && + hwif_in.ecc_kv_rd_seed_status.ERROR.next == ecc_dsa_ctrl.kv_seed_error && + hwif_in.ecc_kv_wr_pkey_status.ERROR.next == ecc_dsa_ctrl.kv_write_error && + //ready when fsm is not busy + hwif_in.ecc_kv_rd_pkey_status.READY.next == ecc_dsa_ctrl.kv_privkey_ready && + hwif_in.ecc_kv_rd_seed_status.READY.next == ecc_dsa_ctrl.kv_seed_ready && + hwif_in.ecc_kv_wr_pkey_status.READY.next == ecc_dsa_ctrl.kv_write_ready && + //set valid when fsm is done + hwif_in.ecc_kv_rd_pkey_status.VALID.hwset == ecc_dsa_ctrl.kv_privkey_done && + hwif_in.ecc_kv_rd_seed_status.VALID.hwset == ecc_dsa_ctrl.kv_seed_done && + hwif_in.ecc_kv_wr_pkey_status.VALID.hwset == ecc_dsa_ctrl.kv_write_done && + //clear valid when new request is made + hwif_in.ecc_kv_rd_pkey_status.VALID.hwclr == hwif_out.ecc_kv_rd_pkey_ctrl.read_en.value && + hwif_in.ecc_kv_rd_seed_status.VALID.hwclr == hwif_out.ecc_kv_rd_seed_ctrl.read_en.value && + hwif_in.ecc_kv_wr_pkey_status.VALID.hwclr == hwif_out.ecc_kv_wr_pkey_ctrl.write_en.value && + //clear enable when busy + hwif_in.ecc_kv_rd_pkey_ctrl.read_en.hwclr == !ecc_dsa_ctrl.kv_privkey_ready && + hwif_in.ecc_kv_rd_seed_ctrl.read_en.hwclr == !ecc_dsa_ctrl.kv_seed_ready && + hwif_in.ecc_kv_wr_pkey_ctrl.write_en.hwclr == !ecc_dsa_ctrl.kv_write_ready; + + endproperty + + primaryout_connected_to_kvout_a: assert property(primaryout_connected_to_kvout_p); + + + // If pm_ctrl is not busy and prog_cntr is equal to DSA_NOP then ecc_ready to accept cmds + property ready_p; + !ecc_dsa_ctrl.pm_busy_o && + ecc_dsa_ctrl.prog_cntr == DSA_NOP + |-> + hwif_in.ECC_STATUS.READY.next && + hwif_in.ecc_ready; + endproperty + + ready_a: assert property(disable iff(!reset_n || fv_zeroize)ready_p); + + + // If pm_ctrl is busy or prog_cntr is in cmd execution or memory write steps then ecc isn't ready + property no_ready_p; + ecc_dsa_ctrl.pm_busy_o || + ecc_dsa_ctrl.prog_cntr != DSA_NOP + |-> + !hwif_in.ECC_STATUS.READY.next && + !hwif_in.ecc_ready; + endproperty + + no_ready_a: assert property(disable iff(!reset_n || fv_zeroize)no_ready_p); + + + + //-------------------------------------------------------// + // Notif interrupt and error sequences // + //-------------------------------------------------------// + + + logic [REG_NUM_DWORDS-1 : 0][RADIX-1:0] privkey_reg; + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + assign privkey_reg[i] = hwif_out.ECC_PRIVKEY_IN[(REG_NUM_DWORDS-1)-i].PRIVKEY_IN.value; + end + + // During sign subroutine if input privkey is zero or >= Group_order or while writing + // the outputs s and r are equal to zero error is triggered + property error_sign_p; + ((ecc_dsa_ctrl.prog_cntr <= DSA_SGN_E) && + (ecc_dsa_ctrl.prog_cntr >= DSA_SGN_S)) && + (((privkey_reg == '0) | (privkey_reg >= GROUP_ORDER)) || + (fv_hw_s_we &&(ecc_dsa_ctrl.read_reg==0)) || + (fv_hw_r_we &&(ecc_dsa_ctrl.read_reg==0))) + |=> + hwif_in.intr_block_rf.error_internal_intr_r.error_internal_sts.hwset; + endproperty + + error_sign_a: assert property(disable iff(!reset_n || fv_zeroize) error_sign_p); + + + // If keygen subroutine is the cmd then input cannot have pcr_sign, this results in error + property error_keygen_p; + (ecc_dsa_ctrl.cmd_reg== KEYGEN) && + hwif_out.ECC_CTRL.PCR_SIGN.value + |=> + hwif_in.intr_block_rf.error_internal_intr_r.error_internal_sts.hwset; + endproperty + + error_keygen_a: assert property(disable iff(!reset_n || fv_zeroize) error_keygen_p); + + + // During verifying subroutine if r and s inputs are equal to zero or greater than group order or + // the pubkey is greater than prime or + // If the cmd is just set as verify after reset then pcr_sign cannot be set along this results in error + property error_verify_p; + (((ecc_dsa_ctrl.prog_cntr <= DSA_VER_E) && + (ecc_dsa_ctrl.prog_cntr >= DSA_VER_S)) && + (((ecc_dsa_ctrl.r_reg == 0) || + (ecc_dsa_ctrl.r_reg >= GROUP_ORDER)) || + ((ecc_dsa_ctrl.s_reg == 0) || + (ecc_dsa_ctrl.s_reg >= GROUP_ORDER)) || + (ecc_dsa_ctrl.pubkeyx_reg >= PRIME) || + (ecc_dsa_ctrl.pubkeyy_reg >= PRIME))) || + ((ecc_dsa_ctrl.cmd_reg==VERIFY) & hwif_out.ECC_CTRL.PCR_SIGN.value) + |=> + hwif_in.intr_block_rf.error_internal_intr_r.error_internal_sts.hwset; + endproperty + + error_verify_a: assert property(disable iff(!reset_n || fv_zeroize) error_verify_p); + + + // Once valid signal is set then interrupt is triggered as a pulse + property notif_interrupt_p; + $rose(hwif_in.ECC_STATUS.VALID.next) + |-> + hwif_in.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.hwset + ##1 + !hwif_in.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.hwset; + endproperty + notif_interrupt_a: assert property(disable iff(!reset_n || fv_zeroize)notif_interrupt_p); + + + // If pm_ctrl busy or sca_blinding modules are busy or if hmac is not ready then subcomponent_busy is asserted + property subcomponent_busy_p; + ecc_dsa_ctrl.pm_busy_o || + ecc_dsa_ctrl.scalar_sca_busy_o || + !ecc_dsa_ctrl.hmac_ready + |-> + ecc_dsa_ctrl.subcomponent_busy; + endproperty + + subcomponent_busy_a: assert property(disable iff(!reset_n || fv_zeroize) subcomponent_busy_p); + + + // If none of the subcomponents are busy then subcomponent_busy is deasserted + property no_subcomponent_busy_p; + !ecc_dsa_ctrl.pm_busy_o && + !ecc_dsa_ctrl.scalar_sca_busy_o && + ecc_dsa_ctrl.hmac_ready + |-> + !ecc_dsa_ctrl.subcomponent_busy; + endproperty + + no_subcomponent_busy_a: assert property(disable iff(!reset_n || fv_zeroize) no_subcomponent_busy_p); + + + +//-------------------------------------------------------------------------// +// HMAC_Interface +//-------------------------------------------------------------------------// + + //If hmac_drbg is enabled from seq then if no error flag and cyc_cnt=3 hmac_init is triggered until the + // prog_cntr advances + property hmac_init_p; + ecc_dsa_ctrl.prog_instr.opcode.hmac_drbg_en && + (ecc_dsa_ctrl.prog_cntr == fv_prog_cntr_reg) && //represents CYC=2 + !ecc_dsa_ctrl.error_flag_edge + ##1 (ecc_dsa_ctrl.prog_cntr != fv_prog_cntr_reg) // represents CYC=3 + |-> + ecc_dsa_ctrl.hmac_init s_until_with (ecc_dsa_ctrl.prog_cntr != fv_prog_cntr_reg); + endproperty + + hmac_init_a: assert property(disable iff(!reset_n ||fv_zeroize)hmac_init_p); + + // If hmac_drbg en is set and the cntr is stable then hmac_init isn't set + property no_hmac_init_less3cyc_p; + ecc_dsa_ctrl.prog_instr.opcode.hmac_drbg_en && + (ecc_dsa_ctrl.prog_cntr == fv_prog_cntr_reg) && + !ecc_dsa_ctrl.error_flag_edge + ##1 (ecc_dsa_ctrl.prog_cntr == fv_prog_cntr_reg) + |-> + !ecc_dsa_ctrl.hmac_init; + endproperty + + no_hmac_init_less3cyc_a: assert property(disable iff(!reset_n ||fv_zeroize)no_hmac_init_less3cyc_p); + + + // If subcomponent busy or prog_cntr is DSA_NOP or there isn't hmac_drbg_en then no hmac_init + property no_hmac_init_p; + (!ecc_dsa_ctrl.prog_instr.opcode.hmac_drbg_en && + (ecc_dsa_ctrl.prog_cntr != fv_prog_cntr_reg)) || + ecc_dsa_ctrl.error_flag_edge || + (ecc_dsa_ctrl.prog_cntr == DSA_NOP) || + (ecc_dsa_ctrl.subcomponent_busy) + |=> + !ecc_dsa_ctrl.hmac_init ; + endproperty + + no_hmac_init_a: assert property(disable iff(!reset_n ||fv_zeroize)no_hmac_init_p); + + + // If sign subroutine is set the no subcomponent busy then hmac_mode is set + property hmac_mode_p; + (hwif_out.ECC_CTRL.CTRL.value == SIGN && + ecc_dsa_ctrl.prog_cntr == DSA_NOP ) && + !ecc_dsa_ctrl.subcomponent_busy + |=> + ecc_dsa_ctrl.hmac_mode; + endproperty + + hmac_mode_a: assert property(disable iff(!reset_n ||fv_zeroize || fv_error_set)hmac_mode_p); + + // Once hmac_mode is stays stable until keygen subroutine triggers + property continue_hmac_mode_p; + ecc_dsa_ctrl.hmac_mode + |-> + (ecc_dsa_ctrl.hmac_mode until ecc_dsa_ctrl.keygen_process); //no ovelapping condition and intial tick both cannot be occured + endproperty + continue_hmac_mode_a: assert property(disable iff(!reset_n ||fv_zeroize || fv_error_set)continue_hmac_mode_p); + + + //If keygen subroutine is set then no hmac_mode + property no_hmac_mode_p; + (hwif_out.ECC_CTRL.CTRL.value == KEYGEN && + ecc_dsa_ctrl.prog_cntr == DSA_NOP ) && + !ecc_dsa_ctrl.subcomponent_busy + |=> + !ecc_dsa_ctrl.hmac_mode; + endproperty + + no_hmac_mode_a: assert property(disable iff(!reset_n ||fv_zeroize || fv_error_set)no_hmac_mode_p); + + // Once hmac_mode deasserted stays stable until new sign subroutine is triggered + property continue_no_hmac_mode_p; + !ecc_dsa_ctrl.hmac_mode + |-> + (!ecc_dsa_ctrl.hmac_mode until ecc_dsa_ctrl.signing_process); + endproperty + continue_no_hmac_mode_a: assert property(disable iff(!reset_n ||fv_zeroize || fv_error_set)continue_no_hmac_mode_p); + + + + // Hmac inputs directly connected to the primary inputs + property hmac_input_reg_p(word); + ecc_dsa_ctrl.privkey_reg[word] == hwif_out.ECC_PRIVKEY_IN[(REG_NUM_DWORDS-1)-word].PRIVKEY_IN.value && + ecc_dsa_ctrl.seed_reg[word] == hwif_out.ECC_SEED[(REG_NUM_DWORDS-1)-word].SEED.value && + ecc_dsa_ctrl.nonce_reg[word] == hwif_out.ECC_NONCE[(REG_NUM_DWORDS-1)-word].NONCE.value && + ecc_dsa_ctrl.msg_reg[word] == hwif_out.ECC_MSG[(REG_NUM_DWORDS-1)-word].MSG.value && + ecc_dsa_ctrl.IV_reg[word] == hwif_out.ECC_IV[(REG_NUM_DWORDS-1)-word].IV.value; + endproperty + for(genvar i=0;i< REG_NUM_DWORDS;i++) begin + hmac_input_reg_a: assert property(hmac_input_reg_p(i)); + end + + + + +//-------------------------------------------------------------------------// +// Scalar_blinding +//-------------------------------------------------------------------------// + + //If sca_en is enabled from seq then if no error flag and cyc_cnt=3 scalar_en is triggered until the + // prog_cntr advances + property scalar_en_p; + ecc_dsa_ctrl.prog_instr.opcode.sca_en && + (ecc_dsa_ctrl.prog_cntr == fv_prog_cntr_reg) && + !ecc_dsa_ctrl.error_flag_edge + ##1 (ecc_dsa_ctrl.prog_cntr != fv_prog_cntr_reg) + |-> + ecc_dsa_ctrl.scalar_sca_en s_until_with (ecc_dsa_ctrl.prog_cntr != fv_prog_cntr_reg); + endproperty + + scalar_en_a: assert property(disable iff(!reset_n ||fv_zeroize)scalar_en_p); + + + + // If sca_en is set and the cntr is stable then scalar_en isn't set + property no_scalar_en_less3cyc_p; + ecc_dsa_ctrl.prog_instr.opcode.sca_en && + (ecc_dsa_ctrl.prog_cntr == fv_prog_cntr_reg) && + !ecc_dsa_ctrl.error_flag_edge + ##1 (ecc_dsa_ctrl.prog_cntr == fv_prog_cntr_reg) + |-> + !ecc_dsa_ctrl.scalar_sca_en; + endproperty + no_scalar_en_less3cyc_a: assert property(disable iff(!reset_n ||fv_zeroize)no_scalar_en_less3cyc_p); + + + + // If subcomponent busy or prog_cntr is DSA_NOP or there isn't sca_en then no scalar_en + property no_scalar_en_p; + (!ecc_dsa_ctrl.prog_instr.opcode.sca_en && + (ecc_dsa_ctrl.prog_cntr != fv_prog_cntr_reg)) || + ecc_dsa_ctrl.error_flag_edge || + (ecc_dsa_ctrl.prog_cntr == DSA_NOP) || + (ecc_dsa_ctrl.subcomponent_busy) + |=> + !ecc_dsa_ctrl.scalar_sca_en; + endproperty + no_scalar_en_a: assert property(disable iff(!reset_n ||fv_zeroize)no_scalar_en_p); + + + // Input for scalar_blinding is from scalar_g_reg + property scalar_in_reg_p; + ecc_dsa_ctrl.prog_instr.opcode.sca_en && + !ecc_dsa_ctrl.verifying_process + |=> + ecc_dsa_ctrl.scalar_in_reg == $past(ecc_dsa_ctrl.scalar_G_reg); + endproperty + + scalar_in_reg_a: assert property(disable iff(!reset_n ||fv_zeroize)scalar_in_reg_p); + + + // Input stays stable if sca not enabled or in verifying process + property stable_scalar_in_reg_p; + !ecc_dsa_ctrl.prog_instr.opcode.sca_en || + ecc_dsa_ctrl.verifying_process + |=> + ecc_dsa_ctrl.scalar_in_reg == $past(ecc_dsa_ctrl.scalar_in_reg); + endproperty + + stable_scalar_in_reg_a: assert property(disable iff(!reset_n ||fv_zeroize)stable_scalar_in_reg_p); + +//-------------------------------------------------------------------------// +// Arithmetic unit +//-------------------------------------------------------------------------// + + // If no error and prog_cntr is not equal to DSA_NOP and none of the subcomponents are busy and cyc cnt ==3 then + // pm_ctrl cmd is equal to dsa_seq opcode pm_cmd + property pm_cmd_reg_p; + !ecc_dsa_ctrl.error_flag_edge && + (ecc_dsa_ctrl.prog_cntr!= DSA_NOP) && + (!ecc_dsa_ctrl.subcomponent_busy) && + (ecc_dsa_ctrl.cycle_cnt==3) + |=> + ecc_dsa_ctrl.pm_cmd_reg == $past(ecc_dsa_ctrl.prog_instr.opcode.pm_cmd); + endproperty + pm_cmd_reg_a: assert property(disable iff(!reset_n ||fv_zeroize)pm_cmd_reg_p); + + + // If error is triggered or prog_cntr is equal to DSA_NOP or subcomponents are busy then pm_cmd ==0 + property no_pm_cmd_reg_p; + ecc_dsa_ctrl.error_flag_edge || + (ecc_dsa_ctrl.prog_cntr == DSA_NOP) || + (ecc_dsa_ctrl.subcomponent_busy) + |=> + ecc_dsa_ctrl.pm_cmd_reg =='0; + endproperty + + no_pm_cmd_reg_a: assert property(disable iff(!reset_n ||fv_zeroize)no_pm_cmd_reg_p); + + + // If cmd is acceptable but cyc cnt is less than 3 then pm_cmd stays stable + property pm_cmd_when_cyc3less_p; + !ecc_dsa_ctrl.error_flag_edge && + (ecc_dsa_ctrl.prog_cntr!= DSA_NOP) && + (!ecc_dsa_ctrl.subcomponent_busy) && + (ecc_dsa_ctrl.cycle_cnt < (CYC_CNT-1)) + |=> + ecc_dsa_ctrl.pm_cmd_reg == $past(ecc_dsa_ctrl.pm_cmd_reg); + endproperty + + pm_cmd_when_cyc3less_a: assert property(disable iff(!reset_n ||fv_zeroize)pm_cmd_when_cyc3less_p); + + +//-------------------------------------------------------------------------// +// Address Liveliness +//-------------------------------------------------------------------------// + + + property wr_core_addr_eventually_in_memory_p; + logic [DSA_OPR_ADDR_WIDTH-1 : 0] temp; + ecc_dsa_ctrl.prog_instr.opcode == DSA_UOP_WR_CORE + ##0 (1'b1, temp = ecc_dsa_ctrl.prog_instr.mem_addr) + |-> + s_eventually(ecc_dsa_ctrl.ecc_arith_unit_i.ram_tdp_file_i.addrb == temp); + endproperty + + wr_core_addr_eventually_in_memory_a: assert property(disable iff(!reset_n ||fv_zeroize)wr_core_addr_eventually_in_memory_p); + + + + + + //-------------------------------------------------------------------------// + // write_reg to the core + //-------------------------------------------------------------------------// + + + + property write_reg_p; + ecc_dsa_ctrl.prog_instr.opcode == DSA_UOP_WR_CORE + |-> + ecc_dsa_ctrl.write_reg == fv_write_reg; + endproperty + write_reg_a: assert property(write_reg_p); + + property write_reg_no_cmd_p; + ecc_dsa_ctrl.prog_instr.opcode != DSA_UOP_WR_CORE && + ecc_dsa_ctrl.prog_instr.opcode != DSA_UOP_WR_SCALAR + |-> + ecc_dsa_ctrl.write_reg == '0; + endproperty + write_reg_no_cmd_a:assert property(write_reg_no_cmd_p); + + property write_reg_sca_p; + ecc_dsa_ctrl.prog_instr.opcode == DSA_UOP_WR_SCALAR + |-> + ecc_dsa_ctrl.write_reg == fv_write_reg; + endproperty + write_reg_sca_a:assert property(write_reg_sca_p); + + //-------------------------------------------------------------------------// + // read_reg from the core + //-------------------------------------------------------------------------// + + + property we_p; + ecc_dsa_ctrl.prog_instr.opcode == DSA_UOP_RD_CORE && + ecc_dsa_ctrl.prog_cntr !=fv_prog_cntr_reg + |-> + ecc_dsa_ctrl.hw_privkey_we == fv_hw_privkey_we && + ecc_dsa_ctrl.hw_pubkeyx_we == fv_hw_pubkeyx_we && + ecc_dsa_ctrl.hw_pubkeyy_we == fv_hw_pubkeyy_we && + ecc_dsa_ctrl.hw_r_we == fv_hw_r_we && + ecc_dsa_ctrl.hw_s_we == fv_hw_s_we && + ecc_dsa_ctrl.hw_scalar_G_we == fv_hw_scalar_G_we && + ecc_dsa_ctrl.hw_scalar_PK_we == fv_hw_scalar_PK_we && + ecc_dsa_ctrl.hw_verify_r_we == fv_hw_verify_r_we && + ecc_dsa_ctrl.hw_pk_chk_we == fv_hw_pk_chk_we; + endproperty + + we_a: assert property(disable iff (fv_error_set)we_p); + + property no_rd_we_p; + (ecc_dsa_ctrl.prog_instr.opcode != DSA_UOP_RD_CORE) || + ecc_dsa_ctrl.prog_cntr ==fv_prog_cntr_reg + |-> + ecc_dsa_ctrl.hw_privkey_we == 0 && + ecc_dsa_ctrl.hw_pubkeyx_we == 0 && + ecc_dsa_ctrl.hw_pubkeyy_we == 0 && + ecc_dsa_ctrl.hw_r_we == 0 && + ecc_dsa_ctrl.hw_s_we == 0 && + ecc_dsa_ctrl.hw_scalar_G_we == 0 && + ecc_dsa_ctrl.hw_scalar_PK_we == 0 && + ecc_dsa_ctrl.hw_verify_r_we == 0 && + ecc_dsa_ctrl.hw_pk_chk_we == 0; + endproperty + no_rd_we_a: assert property(no_rd_we_p); + + + property read_reg_r_p; + fv_hw_r_we + |-> + (ecc_dsa_ctrl.read_reg != '0) && + (ecc_dsa_ctrl.read_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973); + endproperty + read_reg_r_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) read_reg_r_p); + + + property read_reg_s_p; + fv_hw_s_we + |-> + ecc_dsa_ctrl.read_reg != '0 && + ecc_dsa_ctrl.read_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973; + endproperty + read_reg_s_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) read_reg_s_p); + + + property read_reg_ver_r_p; + fv_hw_verify_r_we + |-> + ecc_dsa_ctrl.read_reg != '0 && + ecc_dsa_ctrl.read_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973; + endproperty + read_reg_ver_r_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) read_reg_ver_r_p); + + + //-----------------------------------------------------------// + // scalar_G_reg and scalar_G_sel + //-----------------------------------------------------------// + + + property hmac_drbg_in_scalar_G_reg_p; + (ecc_dsa_ctrl.prog_cntr < DSA_VER_S) + |=> + ecc_dsa_ctrl.scalar_G_reg == $past(ecc_dsa_ctrl.hmac_drbg_result) && + (ecc_dsa_ctrl.scalar_G_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973) + ; + endproperty + + hmac_drbg_in_scalar_G_reg_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) hmac_drbg_in_scalar_G_reg_p); + + + property read_reg_scalar_G_reg_p; + (ecc_dsa_ctrl.prog_cntr >= DSA_VER_S) && + fv_hw_scalar_G_we + |=> + ecc_dsa_ctrl.scalar_G_reg == $past(ecc_dsa_ctrl.read_reg)&& + (ecc_dsa_ctrl.scalar_G_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973) && + (ecc_dsa_ctrl.scalar_G_reg >'0); + endproperty + + read_reg_scalar_G_reg_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) read_reg_scalar_G_reg_p); + + property no_read_reg_scalar_G_reg_p; + (ecc_dsa_ctrl.prog_cntr >= DSA_VER_S) && + !fv_hw_scalar_G_we + |=> + ecc_dsa_ctrl.scalar_G_reg == $past(ecc_dsa_ctrl.scalar_G_reg); + endproperty + + no_read_reg_scalar_G_reg_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set) no_read_reg_scalar_G_reg_p); + + + + + //------------------------------------------------// + // scalar_Pk_reg + //------------------------------------------------// + + + property we_scalar_pk_reg_p; + fv_hw_scalar_PK_we + |=> + ecc_dsa_ctrl.scalar_PK_reg == $past(ecc_dsa_ctrl.read_reg) && + (ecc_dsa_ctrl.scalar_PK_reg < 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973) && + (ecc_dsa_ctrl.scalar_PK_reg >'0); + endproperty + + we_scalar_pk_reg_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)we_scalar_pk_reg_p); + + property no_we_scalar_pk_reg_p; + !fv_hw_scalar_PK_we + |=> + ecc_dsa_ctrl.scalar_PK_reg == $past(ecc_dsa_ctrl.scalar_PK_reg); + endproperty + + no_we_scalar_pk_reg_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)no_we_scalar_pk_reg_p); + + + //------------------------------------------------// + // pk_chk_reg + //------------------------------------------------// + + property pk_chk_reg_p; + fv_hw_pk_chk_we + |=> + ecc_dsa_ctrl.pk_chk_reg == $past(ecc_dsa_ctrl.read_reg); + endproperty + pk_chk_reg_a: assert property(disable iff(!reset_n || fv_zeroize || fv_error_set)pk_chk_reg_p); + + property no_pk_chk_reg_p; + !fv_hw_pk_chk_we + |=> + ecc_dsa_ctrl.pk_chk_reg == $past(ecc_dsa_ctrl.pk_chk_reg); + endproperty + no_pk_chk_reg_a: assert property(disable iff(!reset_n || fv_zeroize)no_pk_chk_reg_p); + +endmodule + + +bind ecc_dsa_ctrl fv_ecc_dsa_ctrl_m fv_ecc_dsa_ctrl ( + .clk(clk), + .reset_n(reset_n), + .cptra_pwrgood(cptra_pwrgood), + + .hwif_out(hwif_out), + .hwif_in(hwif_in), + + .kv_read(kv_read), + .kv_rd_resp(kv_rd_resp), + .kv_write(kv_write), + .kv_wr_resp(kv_wr_resp), + .pcr_signing_data(pcr_signing_data), + + .error_intr(error_intr), + .notif_intr(notif_intr), + .debugUnlock_or_scan_mode_switch(debugUnlock_or_scan_mode_switch) + ); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_ecc_dsa_sequencer.sv b/src/ecc/formal/properties/fv_ecc_dsa_sequencer.sv new file mode 100644 index 000000000..895625f5d --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_dsa_sequencer.sv @@ -0,0 +1,355 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_dsa_sequencer + import ecc_pm_uop_pkg::*; + import ecc_dsa_uop_pkg::*; + #( + parameter ADDR_WIDTH = 8, + parameter DATA_WIDTH = 32 + ) + ( + input wire clk, + input wire rst_n, + input wire ena, + input wire [ADDR_WIDTH-1 : 0] addra, + input logic [DATA_WIDTH-1 : 0] douta + ); + + /////////////////////////////////////////////// + // Helper logic for driving the addra, these assertions + // are used only at block level + /////////////////////////////////////////////// + + logic [ADDR_WIDTH-1 : 0] fv_cntr_const,fv_cntr_kgn,fv_cntr_sgn,fv_cntr_ver; + logic fv_const_set, fv_kgn_set,fv_sgn_set,fv_ver_set; + + always_ff @(posedge clk or negedge rst_n) begin + if(!rst_n) begin + fv_cntr_const <= '0; + fv_cntr_kgn <= '0; + fv_cntr_sgn <= '0; + fv_cntr_ver <= '0; + fv_const_set <= 0; + fv_kgn_set <= 0; + fv_sgn_set <= 0; + fv_ver_set <= 0; + end + else begin + if(addra ==0) begin + fv_ver_set <= 0; + fv_const_set <=1; + fv_cntr_const <= addra+1; + end + else if(fv_const_set) begin + fv_cntr_const <= fv_cntr_const+1; + end + if(addra ==DSA_KG_S) begin + fv_const_set <=0; + fv_kgn_set <= 1; + fv_cntr_kgn <= addra+1; + end + else if(fv_kgn_set) begin + fv_cntr_kgn <= fv_cntr_kgn+1; + end + if(addra == DSA_SGN_S) begin + fv_kgn_set <=0; + fv_sgn_set <= 1; + fv_cntr_sgn <= addra +1; + end + else if(fv_sgn_set) begin + fv_cntr_sgn <= fv_cntr_sgn+1; + end + if(addra == DSA_VER_S) begin + fv_sgn_set <=0; + fv_ver_set <= 1; + fv_cntr_ver <= addra +1; + end + else if(fv_ver_set) begin + fv_cntr_ver <= fv_cntr_ver+1; + end + + + end + end + + cntr_assume: assume property(disable iff(!rst_n) fv_const_set |-> addra == fv_cntr_const); + cntr_assume_kgn: assume property(disable iff(!rst_n) fv_kgn_set |-> addra == fv_cntr_kgn); + cntr_assume_sgn: assume property(disable iff(!rst_n) fv_sgn_set |-> addra == fv_cntr_sgn); + cntr_assume_ver: assume property(disable iff(!rst_n) fv_ver_set |-> addra == fv_cntr_ver); + always_enable: assume property(disable iff(!rst_n) ena == 1'b1); + + default clocking default_clk @(posedge clk); endclocking + + + sequence reset_sequence; + !rst_n ##1 rst_n; + endsequence + + + //////////////////////////////////////////// + // reset property, when reset out a and b // + // are zero // + //////////////////////////////////////////// + + property reset_p; + $past(!rst_n) + |-> + douta == '0; + endproperty + + reset_a : assert property(reset_p); + + + //If the addra input has illegal addresses then the output douta should be zero + property illegal_addr_p; + ((addra > DSA_NOP) && (addra < DSA_KG_S)) || + ((addra > DSA_KG_E) && (addra < DSA_SGN_S)) || + ((addra > DSA_SGN_E) && (addra < DSA_VER_S)) || + (addra > DSA_VER_E) + |=> + douta == '0; + endproperty + illegal_addr_a : assert property(disable iff(!rst_n) illegal_addr_p); + + + + //Checks the sequence where some constant values are written into the memory + property const_p; + addra == 0 + |-> + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} //no operation + ##1 douta == {DSA_UOP_WR_CORE, CONST_ZERO_ID, UOP_OPR_CONST_ZERO} // write to the memory addr zero with value zero + ##1 douta == {DSA_UOP_WR_CORE, CONST_ONE_ID, UOP_OPR_CONST_ONE} // write to the memory addr one with value one + ##1 douta == {DSA_UOP_WR_CORE, CONST_E_a_MONT_ID, UOP_OPR_CONST_E_a} // write to the memory addr two with value mont_a + ##1 douta == {DSA_UOP_WR_CORE, CONST_E_3b_MONT_ID, UOP_OPR_CONST_E_3b} // write to the memory addr three with value mont_3b + ##1 douta == {DSA_UOP_WR_CORE, CONST_ONE_p_MONT_ID, UOP_OPR_CONST_ONE_MONT} // write to the memory addr four with value const_one in mont for mod p + ##1 douta == {DSA_UOP_WR_CORE, CONST_R2_p_MONT_ID, UOP_OPR_CONST_R2_p} // write to the memory addr five with value R2 in mont domain mod p, used for converting normal domain to mont domain + ##1 douta == {DSA_UOP_WR_CORE, CONST_G_X_MONT_ID, UOP_OPR_CONST_GX_MONT} // write to the memory addr six with value Gx in mont domain + ##1 douta == {DSA_UOP_WR_CORE, CONST_G_Y_MONT_ID, UOP_OPR_CONST_GY_MONT} // write to the memory addr seven with value Gy in mont domain + ##1 douta == {DSA_UOP_WR_CORE, CONST_R2_q_MONT_ID, UOP_OPR_CONST_R2_q} // write to the memory addr 29 with value R2 in mont domain mod q, used for converting normal domain to mont domain + ##1 douta == {DSA_UOP_WR_CORE, CONST_ONE_q_MONT_ID, UOP_OPR_CONST_ONE_q_MONT} //// write to the memory addr 28 with value const_one in mont for mod p + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE}; + endproperty + + + const_a: assert property (disable iff(!rst_n) const_p); + + + // Checks the sequence of operations for the keygen operation + property keygen_p; + addra == DSA_KG_S + |-> + ##1 douta <= {DSA_UOP_HMAC_DRBG, NOP_ID, UOP_OPR_DONTCARE} // Input seed for lamda, scalar, privkey genration + ##1 douta <= {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta <= {DSA_UOP_WR_CORE, SCALAR_G_ID, UOP_OPR_SCALAR_G} // Writing scalar here it is privkey to the memory + ##1 douta <= {DSA_UOP_RD_CORE, PRIVKEY_ID, UOP_OPR_SCALAR_G} // Read the generated privkey, used for out + ##1 douta <= {DSA_UOP_SCALAR_SCA, SCALAR_G_ID, UOP_OPR_DONTCARE} // passing the generated scalar to scalar blinding as input + ##1 douta <= {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta <= {DSA_UOP_WR_SCALAR, SCALAR_ID, UOP_OPR_DONTCARE} // the scalar blinded privkey is used as a secret key + ##1 douta <= {DSA_UOP_WR_CORE, LAMBDA_ID, UOP_OPR_LAMBDA} // lamda generated by hmac_drbg is stored into memory + ##1 douta <= {DSA_UOP_KEYGEN, NOP_ID, UOP_OPR_DONTCARE} // keygen cmd triggered in pm_ctrl to generate pub key + ##1 douta <= {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta <= {DSA_UOP_RD_CORE, PUBKEYX_ID, UOP_OPR_Qx_AFFN} // reading the generated pubkey x and y from memory + ##1 douta <= {DSA_UOP_RD_CORE, PUBKEYY_ID, UOP_OPR_Qy_AFFN} + ##1 douta <= {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE}; + endproperty + + keygen_a: assert property (disable iff(!rst_n) keygen_p); + + + // Checks the sequence of operations for the signing operation + property sign_p; + addra == DSA_SGN_S + |-> + ##1 douta == {DSA_UOP_WR_CORE, MSG_ID, UOP_OPR_HASH_MSG} //Input hash msg + ##1 douta == {DSA_UOP_WR_CORE, PRIVKEY_ID, UOP_OPR_PRIVKEY} //Input priv key + ##1 douta == {DSA_UOP_HMAC_DRBG, NOP_ID, UOP_OPR_DONTCARE} // Feed in h and pk for k genration + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta == {DSA_UOP_WR_CORE, SCALAR_G_ID, UOP_OPR_SCALAR_G} // write to memory with the generated k + ##1 douta == {DSA_UOP_SCALAR_SCA, SCALAR_G_ID, UOP_OPR_DONTCARE} // enable the scalar blinding with k as input + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta == {DSA_UOP_WR_SCALAR, SCALAR_ID, UOP_OPR_DONTCARE} // the randmoised k is written to the secret key in pm ctrl + ##1 douta == {DSA_UOP_WR_CORE, LAMBDA_ID, UOP_OPR_LAMBDA} // lamda generated by hmac_drbg is stored into memory + ##1 douta == {DSA_UOP_WR_CORE, MASKING_ID, UOP_OPR_MASKING} // mask value generated by hmac_drbg is stored into the memory + ##1 douta == {DSA_UOP_SIGN, NOP_ID, UOP_OPR_DONTCARE} // signing cmd is passed to the pm_ctrl + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta == {DSA_UOP_RD_CORE, R_ID, UOP_OPR_SIGN_R} // read the generated r from the memory + ##1 douta == {DSA_UOP_RD_CORE, S_ID, UOP_OPR_SIGN_S} // read the generated s from the memory + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE}; + endproperty + + sign_a: assert property(disable iff(!rst_n) sign_p); + + + + // Checks the sequence of operations for the verifying operation + property verify_p; + addra == DSA_VER_S + |-> + ##1 douta == {DSA_UOP_WR_CORE, CONST_E_b_MONT_ID, UOP_OPR_CONST_E_b} // writing to the memory const b, which is in mont domain + ##1 douta == {DSA_UOP_WR_CORE, PUBKEYX_ID, UOP_OPR_Qx_AFFN} // writing to the memory input pubkey + ##1 douta == {DSA_UOP_WR_CORE, PUBKEYY_ID, UOP_OPR_Qy_AFFN} + ##1 douta == {DSA_UOP_PK_CHK, NOP_ID, UOP_OPR_DONTCARE} // Cmd to pm ctrl to check if the pubkey is on the curve + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta == {DSA_UOP_RD_CORE, PK_VALID_ID, UOP_OPR_PK_VALID} // Reading the result from memory if the pubkey is valid point on the curve + ##1 douta == {DSA_UOP_WR_CORE, MSG_ID, UOP_OPR_HASH_MSG} // writing to the memory input hash msg + ##1 douta == {DSA_UOP_WR_CORE, R_ID, UOP_OPR_SIGN_R} // writing to the memory input r + ##1 douta == {DSA_UOP_WR_CORE, S_ID, UOP_OPR_SIGN_S} // writing to the memory input s + ##1 douta == {DSA_UOP_WR_CORE, CONST_ONE_ID, UOP_OPR_LAMBDA} // writing to the memory for lamda as value 1 + ##1 douta == {DSA_UOP_VERIFY0, NOP_ID, UOP_OPR_DONTCARE} // verify0_cmd triggered in pm ctrl + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta == {DSA_UOP_RD_CORE, SCALAR_G_ID, UOP_OPR_SCALAR_G} // reading from memory (h*s_inv) value in normal domain + ##1 douta == {DSA_UOP_RD_CORE, SCALAR_PK_ID, UOP_OPR_SCALAR_PK} // reading from memory (r*s_inv) value in normal domain + ##1 douta == {DSA_UOP_WR_SCALAR, SCALAR_G_ID, UOP_OPR_DONTCARE} // (h*s_inv) value shifted by RND_SIZE and provided to pm as secret key + ##1 douta == {DSA_UOP_VERIFY1, NOP_ID, UOP_OPR_DONTCARE} // verify1_cmd passed to pm_ctrl, result in R0_x,y,z + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta == {DSA_UOP_WR_CORE, PUBKEYX_ID, UOP_OPR_Qx_AFFN} // writing into memory the pubkey again + ##1 douta == {DSA_UOP_WR_CORE, PUBKEYY_ID, UOP_OPR_Qy_AFFN} + ##1 douta == {DSA_UOP_WR_SCALAR, SCALAR_PK_ID, UOP_OPR_DONTCARE} // (r*s_inv) value shifted by RND_SIZE and provided to pm as secret key + ##1 douta == {DSA_UOP_VERIFY2, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE} + ##1 douta == {DSA_UOP_RD_CORE, VERIFY_R_ID, UOP_OPR_Qx_AFFN} //Computed r' in normal domain read back from memory + ##1 douta == {DSA_UOP_NOP, NOP_ID, UOP_OPR_DONTCARE}; + endproperty + + verify_a: assert property(disable iff(!rst_n) verify_p); + + + +//If the first field is DSA_UOP_NOP, the next fields should be NOP_ID and UOP_OPR_DONTCARE, respectively. + + property when_nop_both_id_addr_0_p; + douta[19:12] == DSA_UOP_NOP + |-> + douta[11:0]== {NOP_ID,UOP_OPR_DONTCARE}; + endproperty + +when_nop_both_id_addr_0_a: assert property(disable iff(!rst_n) when_nop_both_id_addr_0_p); + + +//If the first field is DSA_UOP_WR_CORE, the next fields should include a valid ID and ADDRESS, respectively. + + property when_wr_both_id_addr_not_0_p; + douta[19:12] == DSA_UOP_WR_CORE + |-> + douta[11:0] == {CONST_ZERO_ID, UOP_OPR_CONST_ZERO} || + douta[11:0] == {CONST_ONE_ID, UOP_OPR_CONST_ONE} || + douta[11:0] == {CONST_E_a_MONT_ID, UOP_OPR_CONST_E_a} || + douta[11:0] == {CONST_E_3b_MONT_ID, UOP_OPR_CONST_E_3b} || + douta[11:0] == {CONST_ONE_p_MONT_ID, UOP_OPR_CONST_ONE_MONT} || + douta[11:0] == {CONST_R2_p_MONT_ID, UOP_OPR_CONST_R2_p} || + douta[11:0] == {CONST_G_X_MONT_ID, UOP_OPR_CONST_GX_MONT} || + douta[11:0] == {CONST_G_Y_MONT_ID, UOP_OPR_CONST_GY_MONT} || + douta[11:0] == {CONST_R2_q_MONT_ID, UOP_OPR_CONST_R2_q} || + douta[11:0] == {CONST_ONE_q_MONT_ID, UOP_OPR_CONST_ONE_q_MONT} || + douta[11:0] == {SCALAR_G_ID, UOP_OPR_SCALAR_G} || + douta[11:0] == {LAMBDA_ID, UOP_OPR_LAMBDA} || + douta[11:0] == {MSG_ID, UOP_OPR_HASH_MSG} || + douta[11:0] == {PRIVKEY_ID, UOP_OPR_PRIVKEY} || + douta[11:0] == {MASKING_ID, UOP_OPR_MASKING} || + douta[11:0] == {CONST_E_b_MONT_ID, UOP_OPR_CONST_E_b} || + douta[11:0] == {R_ID, UOP_OPR_SIGN_R} || + douta[11:0] == {S_ID, UOP_OPR_SIGN_S} || + douta[11:0] == {CONST_ONE_ID, UOP_OPR_LAMBDA} || + douta[11:0] == {PUBKEYX_ID, UOP_OPR_Qx_AFFN} || + douta[11:0] == {PUBKEYY_ID, UOP_OPR_Qy_AFFN}; + endproperty + +when_wr_both_id_addr_not_0_a: assert property(disable iff(!rst_n) when_wr_both_id_addr_not_0_p); + + +//If the first field is DSA_UOP_HMAC_DRBG, the next fields should be NOP_ID and UOP_OPR_DONTCARE, respectively. + property when_drbg_both_id_addr_0_p; + douta[19:12] == DSA_UOP_HMAC_DRBG + |-> + douta[11:0] == {NOP_ID,UOP_OPR_DONTCARE}; + endproperty + +when_drbg_both_id_addr_0_a: assert property(disable iff(!rst_n) when_drbg_both_id_addr_0_p); + +//If the first field is DSA_UOP_SCALAR_SCA, the next fields should be SCALAR_G_ID and UOP_OPR_DONTCARE, respectively. + property when_scalar_both_id_addr_p; + douta[19:12] == DSA_UOP_SCALAR_SCA + |-> + douta[11:0] == {SCALAR_G_ID,UOP_OPR_DONTCARE}; + endproperty + +when_scalar_both_id_addr_a: assert property(disable iff(!rst_n) when_scalar_both_id_addr_p); + +//If the first field is DSA_UOP_WR_SCALAR, the next fields should be SCALAR_ID/ SCALAR_G_ID/ SCALAR_G_ID and UOP_OPR_DONTCARE, respectively. + property when_wr_scalar_both_id_addr_p; + douta[19:12] == DSA_UOP_WR_SCALAR + |-> + (douta[11:6] == SCALAR_G_ID || + douta[11:6] == SCALAR_ID || + douta[11:6] == SCALAR_PK_ID ) && + douta[5:0] == UOP_OPR_DONTCARE; + endproperty + +when_wr_scalar_both_id_addr_a: assert property(disable iff(!rst_n) when_wr_scalar_both_id_addr_p); + + + +//If the first field is DSA_UOP_KEYGEN/ DSA_UOP_KEYGEN/ DSA_UOP_VERIFY0-2, the next fields should be NOP_ID and UOP_OPR_DONTCARE, respectively. + + property when_commands_both_id_addr_0_p; + douta[19:12] == DSA_UOP_KEYGEN || + douta[19:12] == DSA_UOP_SIGN || + douta[19:12] == DSA_UOP_VERIFY0 || + douta[19:12] == DSA_UOP_VERIFY1 || + douta[19:12] == DSA_UOP_VERIFY2 + |-> + douta[11:0] == {NOP_ID,UOP_OPR_DONTCARE}; + endproperty + +when_commands_both_id_addr_0_a: assert property(disable iff(!rst_n) when_commands_both_id_addr_0_p); + +//o If the first field is DSA_UOP_RD_CORE, the next fields should include a valid ID and ADDRESS, respectively. + + property when_rd_both_id_addr_not_0_p; + douta[19:12] == DSA_UOP_RD_CORE + |-> + douta[11:0] == {PRIVKEY_ID, UOP_OPR_SCALAR_G} || + douta[11:0] == {PUBKEYX_ID, UOP_OPR_Qx_AFFN} || + douta[11:0] == {PUBKEYY_ID, UOP_OPR_Qy_AFFN} || + douta[11:0] == {R_ID, UOP_OPR_SIGN_R} || + douta[11:0] == {S_ID, UOP_OPR_SIGN_S} || + douta[11:0] == {PK_VALID_ID, UOP_OPR_PK_VALID} || + douta[11:0] == {SCALAR_G_ID, UOP_OPR_SCALAR_G} || + douta[11:0] == {SCALAR_PK_ID, UOP_OPR_SCALAR_PK} || + douta[11:0] == {VERIFY_R_ID, UOP_OPR_Qx_AFFN}; + endproperty + +when_rd_both_id_addr_not_0_a: assert property(disable iff(!rst_n) when_rd_both_id_addr_not_0_p); + + +endmodule + + +bind ecc_dsa_sequencer fv_ecc_dsa_sequencer + #(.ADDR_WIDTH(ADDR_WIDTH), + .DATA_WIDTH(DATA_WIDTH) + ) + fv_ecc_dsa_sequencer_inst( + .clk(clka), + .rst_n(reset_n && !zeroize), + .ena(ena), + .addra(addra), + .douta(douta) + ); diff --git a/src/ecc/formal/properties/fv_ecc_fau.sv b/src/ecc/formal/properties/fv_ecc_fau.sv new file mode 100644 index 000000000..b1f85eb10 --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_fau.sv @@ -0,0 +1,167 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_fau_m #( + parameter REG_SIZE = 384, + parameter RADIX = 32 + ) + ( + // Clock and reset. + input wire clk, + input wire rst_n, + // DATA PORT + input wire add_en_i, + input wire sub_i, + input wire mult_en_i, + input wire [REG_SIZE-1:0] prime_i, + input wire [RADIX-1 : 0] mult_mu_i, + input wire [REG_SIZE-1:0] opa_i, + input wire [REG_SIZE-1:0] opb_i, + input wire [REG_SIZE-1:0] add_res_o, + input wire [REG_SIZE-1:0] mult_res_o + ); + + + default clocking default_clk @(posedge clk); endclocking + + sequence reset_sequence; + (!rst_n) ##1 rst_n; + endsequence + + + /////////////////////////////////////////// + // reset property, when reset all the o/p // + // are zero // + //////////////////////////////////////////// + + property reset_p; + $past(!rst_n) + |-> + `ifdef TOP + add_res_o == '0 && //need to be defined on top as at block level open inputs and could take any value being comb + `endif + mult_res_o == '0 && + ecc_fau.mult_start_edge == '0 && + ecc_fau.sub == '0 && + ecc_fau.add_start_edge == '0 ; + endproperty + + reset_a : assert property(reset_p); + + //When ever mult_en_i is triggered, it would just generate one pulse + + property mult_pulse_p; + $rose(mult_en_i) + |=> + ecc_fau.mult_start_edge + ##1 + !ecc_fau.mult_start_edge; + endproperty + + mult_pulse_a: assert property(disable iff(!rst_n) mult_pulse_p); + + + //Once edge triggered from next cycle on it stays out until there is an another mult cmd + property no_mult_edge_p; + ecc_fau.mult_start_edge + |=> + !ecc_fau.mult_start_edge s_until_with mult_en_i; + endproperty + no_mult_edge_a: assert property(disable iff(!rst_n)no_mult_edge_p); + + + //When ever add_en_i is triggered, it would just generate one pulse + property add_pulse_p; + $rose(add_en_i) + |=> + ecc_fau.add_start_edge + ##1 + !ecc_fau.add_start_edge; + endproperty + + add_pulse_a: assert property(disable iff(!rst_n) add_pulse_p); + + + //Once edge triggered from next cycle on it stays out until there is an another add cmd + property no_add_edge_p; + ecc_fau.add_start_edge + |=> + !ecc_fau.add_start_edge s_until_with add_en_i; + endproperty + no_add_edge_a: assert property(disable iff(!rst_n)no_add_edge_p); + + + //Primary outputs connected to primary outputs of submodules + property outputs_p; + mult_res_o == ecc_fau.mult_res_s && + add_res_o == ecc_fau.add_res_s; + endproperty + + outputs_a: assert property(disable iff(!rst_n) outputs_p); + + + //Primary inputs connected to primary inputs of submodules + property inputs_p; + ecc_fau.mult_opa == opa_i && + ecc_fau.mult_opb == opb_i; + endproperty + + inputs_a: assert property(disable iff(!rst_n) inputs_p); + + + //When add and mult ready + property garbage_ready_p; + ecc_fau.ready_garbage_bit == (ecc_fau.add_ready_o & ecc_fau.mult_ready_o); + endproperty + garbage_ready_a: assert property(disable iff(!rst_n) garbage_ready_p); + + + // Always the results should be less than the prime + `ifdef TOP + property data_out_prime_p(ready,result); + (ready) + |-> + ((result < prime_i)) + ;endproperty + data_out_add_sub_res_prime_a: assert property(disable iff(!rst_n) data_out_prime_p(ecc_fau.add_ready_o,add_res_o)); + data_out_mult_res_prime_a: assert property(disable iff(!rst_n) data_out_prime_p(ecc_fau.mult_ready_o,mult_res_o)); + `endif + +endmodule + bind ecc_fau fv_ecc_fau_m #( + .REG_SIZE(REG_SIZE), + .RADIX(RADIX) + ) + ecc_fau_i + ( + // Clock and reset. + .clk(clk), + .rst_n(reset_n && !zeroize), + + // DATA PORT + .add_en_i(add_en_i), + .sub_i(sub_i), + .mult_en_i(mult_en_i), + .prime_i(prime_i), + .mult_mu_i(mult_mu_i), + .opa_i(opa_i), + .opb_i(opb_i), + .add_res_o(add_res_o), + .mult_res_o(mult_res_o) + ); + diff --git a/src/ecc/formal/properties/fv_ecc_hmac_drbg_interface.sv b/src/ecc/formal/properties/fv_ecc_hmac_drbg_interface.sv new file mode 100644 index 000000000..3a4c45390 --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_hmac_drbg_interface.sv @@ -0,0 +1,547 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +`define hiearchy ecc_hmac_drbg_interface + +module fv_ecc_hmac_drbg_interface_m#( + parameter REG_SIZE = 384, + parameter [REG_SIZE-1 : 0] GROUP_ORDER = 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973, + parameter [147 : 0] LFSR_INIT_SEED = 148'h6_04E7_A407_54F1_4487_A021_11AC_D0DF_8C55_57A0 // a random value + ) + ( + // Clock and reset. + input wire clk, + input wire rst_n, + input wire keygen_sign, + input wire en, + input wire ready, + + //Inputs + input wire [REG_SIZE-1 : 0] keygen_seed, + input wire [REG_SIZE-1 : 0] keygen_nonce, + input wire [REG_SIZE-1 : 0] privKey, + input wire [REG_SIZE-1 : 0] hashed_msg, + input wire [REG_SIZE-1 : 0] IV, + + //Outputs + input wire [REG_SIZE-1 : 0] lambda, + input wire [REG_SIZE-1 : 0] scalar_rnd, + input wire [REG_SIZE-1 : 0] masking_rnd, + input wire [REG_SIZE-1 : 0] drbg + ); + + localparam [3 : 0] IDLE_ST = 4'd0; + localparam [3 : 0] LFSR_ST = 4'd1; + localparam [3 : 0] LAMBDA_ST = 4'd2; + localparam [3 : 0] SCALAR_RND_ST = 4'd3; + localparam [3 : 0] RND_DONE_ST = 4'd4; + localparam [3 : 0] MASKING_RND_ST = 4'd5; + localparam [3 : 0] KEYGEN_ST = 4'd6; + localparam [3 : 0] SIGN_ST = 4'd7; + localparam [3 : 0] DONE_ST = 4'd8; + + default clocking default_clk @(posedge clk); endclocking + + sequence reset_sequence; + (!rst_n) ##1 rst_n; + endsequence + + /////////////////////////////////////////// + // constraint on hashed msg + /////////////////////////////////////////// + hash_msg_less_than_grp_order: assume property(disable iff(!rst_n) hashed_msg < GROUP_ORDER); + + + /////////////////////////////////////////// + // Helper logic for lfsr_seed + /////////////////////////////////////////// + + logic [147 : 0] fv_lfsr_seed_reg; + logic [383:0] fv_hmac_drbg_result_reg; + logic fv_hmac_drbg_valid_reg; + always_ff @(posedge clk, negedge rst_n) begin + if(!rst_n) + fv_lfsr_seed_reg <= LFSR_INIT_SEED; + else begin + fv_hmac_drbg_valid_reg <= `hiearchy.hmac_drbg_valid; + fv_hmac_drbg_result_reg <= `hiearchy.hmac_drbg_result; + if(`hiearchy.state_reg == LFSR_ST && `hiearchy.hmac_drbg_valid && !fv_hmac_drbg_valid_reg) begin + fv_lfsr_seed_reg <= `hiearchy.hmac_drbg_result[147 : 0]; + end + end + end + + + /////////////////////////////////////////// + // reset property, when reset all the o/p // + // are zero // + //////////////////////////////////////////// + + property reset_p; + $past(!rst_n) + |-> + `hiearchy.state_reg == IDLE_ST && + lambda == '0 && + scalar_rnd == '0 && + masking_rnd == '0 && + drbg == '0 && + ready == 1; + endproperty + + reset_a : assert property(reset_p); + + + //State transitioning from idle to lfsr if en and hmac_drbg_ready + property idle_to_lfsr_p; + `hiearchy.state_reg == IDLE_ST && + (en & `hiearchy.hmac_drbg_ready) + |=> + `hiearchy.state_reg == LFSR_ST && + `hiearchy.hmac_drbg_init == 1 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == IV && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + `hiearchy.hmac_drbg_nonce == $past(`hiearchy.counter_nonce) && + ready == 0 && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg) + ; + + endproperty + + idle_to_lfsr_a: assert property(disable iff(!rst_n) idle_to_lfsr_p); + + + // If en and hmac_drbg isn't ready then stays back in idle state + property idle_wait_p; + `hiearchy.state_reg == IDLE_ST && + !(en & `hiearchy.hmac_drbg_ready) + |=> + `hiearchy.state_reg == IDLE_ST && + ready == 1 && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == '0 && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + `hiearchy.hmac_drbg_nonce == (`hiearchy.counter_nonce_reg) && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + + idle_wait_a: assert property(disable iff(!rst_n) idle_wait_p); + + + // State transition from lfsr to lambda when hmac_drbg_valid is set + property lfsr_to_lambda_p; + `hiearchy.state_reg== LFSR_ST && + $rose(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == LAMBDA_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 1 && + `hiearchy.hmac_drbg_entropy == IV && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == $past(`hiearchy.hmac_drbg_result[147 : 0]) ^ `hiearchy.counter_nonce[147 : 0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + + lfsr_to_lambda_a: assert property(disable iff(!rst_n) lfsr_to_lambda_p); + + + // If hmac_drbg_valid isn't set then stays back in same state + property lfsr_wait_p; + `hiearchy.state_reg == LFSR_ST && + !(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == LFSR_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == IV && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg) + ; + endproperty + lfsr_wait_a: assert property(disable iff(!rst_n) lfsr_wait_p); + + + //State transition from lamda to scalar_rnd when hmac_drbg_valid is set + property lambda_to_scalar_rnd_p; + `hiearchy.state_reg == LAMBDA_ST && + $rose(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == SCALAR_RND_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 1 && + `hiearchy.hmac_drbg_entropy == IV && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == fv_lfsr_seed_reg ^ `hiearchy.counter_nonce[147 : 0] && + lambda == $past(`hiearchy.hmac_drbg_result) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + + lambda_to_scalar_rnd_a: assert property(disable iff(!rst_n) lambda_to_scalar_rnd_p); + + + //If hmac_drbg_valid isn't set then stays back in same state + property lambda_wait_p; + `hiearchy.state_reg == LAMBDA_ST && + !(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == LAMBDA_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == IV && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + lambda_wait_a: assert property(disable iff(!rst_n) lambda_wait_p); + + + //State transition from scalar_rnd to rnd_done when hmac_drbg_valid is set + property scalar_rnd_to_rnd_done_p; + `hiearchy.state_reg == SCALAR_RND_ST && + $rose(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == RND_DONE_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == '0 && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(`hiearchy.hmac_drbg_result) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + scalar_rnd_to_rnd_done_a: assert property(disable iff(!rst_n) scalar_rnd_to_rnd_done_p); + + + //If hmac_drbg_valid isn't set then stays back in same state + property scalar_rnd_wait_p; + `hiearchy.state_reg == SCALAR_RND_ST && + !(`hiearchy.hmac_drbg_valid) + + |=> + `hiearchy.state_reg == SCALAR_RND_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == IV && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + scalar_rnd_wait_a: assert property(disable iff(!rst_n) scalar_rnd_wait_p); + + + // if in rnd_done state then if keygen_sign is set then state changes to masking_rnd + property rnd_done_to_masking_rnd_p; + `hiearchy.state_reg == RND_DONE_ST && + keygen_sign + |=> + `hiearchy.state_reg == MASKING_RND_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 1 && + `hiearchy.hmac_drbg_entropy == IV && + ready == 0 && + `hiearchy.hmac_lfsr_seed == fv_lfsr_seed_reg ^ `hiearchy.counter_nonce[147 : 0] && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + rnd_done_to_masking_rnd_a: assert property(disable iff(!rst_n) rnd_done_to_masking_rnd_p); + + + // if in rnd_done state then if keygen_sign isn't set then state changes to keygen + property rnd_done_to_keygen_p; + `hiearchy.state_reg == RND_DONE_ST && + !keygen_sign + |=> + `hiearchy.state_reg == KEYGEN_ST && + `hiearchy.hmac_drbg_init == 1 && + `hiearchy.hmac_drbg_next == 0 && + ready == 0 && + `hiearchy.hmac_drbg_entropy == keygen_seed && + `hiearchy.hmac_lfsr_seed == fv_lfsr_seed_reg ^ `hiearchy.counter_nonce[147 : 0] && + `hiearchy.hmac_drbg_nonce == keygen_nonce && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + rnd_done_to_keygen_a: assert property(disable iff(!rst_n) rnd_done_to_keygen_p); + + + //State transition from masking_rnd to sign when hmac_drbg_valid is set + property masking_rnd_to_sign_p; + `hiearchy.state_reg == MASKING_RND_ST && + $rose(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == SIGN_ST && + `hiearchy.hmac_drbg_init == 1 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == privKey && + ready == 0 && + `hiearchy.hmac_drbg_nonce == hashed_msg && + `hiearchy.hmac_lfsr_seed == fv_lfsr_seed_reg ^ `hiearchy.counter_nonce[147 : 0] && + masking_rnd == $past(`hiearchy.hmac_drbg_result) && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + + drbg == $past(drbg); + endproperty + masking_rnd_to_sign_a: assert property(disable iff(!rst_n) masking_rnd_to_sign_p); + + //If hmac_drbg_valid isn't set then stays back in same state + property masking_rnd_wait_p; + `hiearchy.state_reg == MASKING_RND_ST && + !(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == MASKING_RND_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == IV && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + masking_rnd_wait_a: assert property(disable iff(!rst_n) masking_rnd_wait_p); + + + //State transition from keygen to done when hmac_drbg_valid is set + property keygen_to_done_p; + `hiearchy.state_reg == KEYGEN_ST && + $rose(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == DONE_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == '0 && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(`hiearchy.hmac_drbg_result); + endproperty + keygen_to_done_a: assert property(disable iff(!rst_n) keygen_to_done_p); + + //If hmac_drbg_valid isn't set then stays back in same state + property keygen_wait_p; + `hiearchy.state_reg == KEYGEN_ST && + !(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == KEYGEN_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == keygen_seed && + ready == 0 && + `hiearchy.hmac_drbg_nonce == keygen_nonce && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + keygen_wait_a: assert property(disable iff(!rst_n) keygen_wait_p); + + + + + //State transition from sign to done when hmac_drbg_valid is set + property sign_to_done_p; + `hiearchy.state_reg == SIGN_ST && + $rose(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == DONE_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == '0 && + ready == 0 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(`hiearchy.hmac_drbg_result); + endproperty + sign_to_done_a: assert property(disable iff(!rst_n) sign_to_done_p); + + + //If hmac_drbg_valid isn't set then stays back in same state + property sign_wait_p; + `hiearchy.state_reg == SIGN_ST && + !(`hiearchy.hmac_drbg_valid) + |=> + `hiearchy.state_reg == SIGN_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == privKey && + ready == 0 && + `hiearchy.hmac_drbg_nonce == hashed_msg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + sign_wait_a: assert property(disable iff(!rst_n) sign_wait_p); + + + + property done_to_idle_p; + `hiearchy.state_reg == DONE_ST + |=> + `hiearchy.state_reg == IDLE_ST && + `hiearchy.hmac_drbg_init == 0 && + `hiearchy.hmac_drbg_next == 0 && + `hiearchy.hmac_drbg_entropy == '0 && + ready == 1 && + `hiearchy.hmac_drbg_nonce == `hiearchy.counter_nonce_reg && + `hiearchy.hmac_lfsr_seed == (fv_lfsr_seed_reg) ^ `hiearchy.counter_nonce[147:0] && + lambda == $past(lambda) && + scalar_rnd == $past(scalar_rnd) && + masking_rnd == $past(masking_rnd) && + drbg == $past(drbg); + endproperty + done_to_idle_a: assert property(disable iff(!rst_n) done_to_idle_p); + + + + + //counter_reg is checked if it adds 1 after everycycle + + // Helper logic for reset reg to use in disable iff + logic fv_rst_n_reg; + always_ff @(posedge clk) begin + fv_rst_n_reg <= rst_n; + end + + property counter_reg_p; + `hiearchy.counter_reg == $past(`hiearchy.counter_reg)+1; + endproperty + counter_reg_a: assert property(disable iff(!rst_n || !fv_rst_n_reg) counter_reg_p); + + + + //counter_nonce_reg has counter_nonce onece en is triggered. + property counter_nonce_reg_p; + en + |=> + `hiearchy.counter_nonce_reg == $past(`hiearchy.counter_nonce); + endproperty + counter_nonce_reg_a: assert property(disable iff(!rst_n) counter_nonce_reg_p); + + // counter_nonce_reg stable if no en + property counter_nonce_reg_stable_p; + !en + |=> + `hiearchy.counter_nonce_reg == $past(`hiearchy.counter_nonce_reg); + endproperty + counter_nonce_reg_stable_a: assert property(disable iff(!rst_n) counter_nonce_reg_stable_p); + + + + + + //done_edge is a pulse from the hmac_drbg_valid + property done_pulse_p; + $rose(`hiearchy.hmac_drbg_valid) + |-> + `hiearchy.hmac_done_edge + ##1 + !`hiearchy.hmac_done_edge; + endproperty + + done_pulse_a: assert property(disable iff(!rst_n) done_pulse_p); + + + // eventually ready==1, once the fsm triggered + property ready_liveliness_p; + `hiearchy.state_reg == IDLE_ST && + (en & `hiearchy.hmac_drbg_ready) + |-> + s_eventually(ready); + endproperty + ready_liveliness_a: assert property(disable iff(!rst_n) ready_liveliness_p); + +endmodule + +bind ecc_hmac_drbg_interface fv_ecc_hmac_drbg_interface_m#( + .REG_SIZE(REG_SIZE), + .GROUP_ORDER(GROUP_ORDER) + ) + fv_ecc_hmac_drbg_interface ( + .clk(clk), + .rst_n(reset_n && !zeroize), + .keygen_sign(keygen_sign), + .en(en), + .ready(ready), + .keygen_seed(keygen_seed), + .keygen_nonce(keygen_nonce), + .privKey(privKey), + .hashed_msg(hashed_msg), + .IV(IV), + .lambda(lambda), + .scalar_rnd(scalar_rnd), + .masking_rnd(masking_rnd), + .drbg(drbg) + ); + + + + + + + + + \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_ecc_hmac_drbg_interface_constraints.sv b/src/ecc/formal/properties/fv_ecc_hmac_drbg_interface_constraints.sv new file mode 100644 index 000000000..6e8f9a07c --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_hmac_drbg_interface_constraints.sv @@ -0,0 +1,113 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_hmac_drbg_interface_constraints_m #( + parameter time_window = 3)( + input logic clk, + input logic rst_n, + input logic hmac_drbg_ready, + input logic hmac_drbg_init, + input logic hmac_drbg_next, + input logic hmac_drbg_valid, + input logic [383:0] counter_nonce +); + +default clocking default_clk @(posedge clk); endclocking + + + +property hmac_drbg_ready_after_reset(hmac_drbg_ready); + (!rst_n) + |=> + hmac_drbg_ready; + endproperty +assume_hmac_drbg_ready_after_reset : assume property(@(posedge clk) hmac_drbg_ready_after_reset(hmac_drbg_ready)); + + sequence idletonext(hmac_drbg_ready, hmac_drbg_init, hmac_drbg_next); + hmac_drbg_ready && + (hmac_drbg_init || hmac_drbg_next); + endsequence + + property hmac_drbg_not_ready(hmac_drbg_ready, hmac_drbg_init, hmac_drbg_next,time_window); + idletonext(hmac_drbg_ready, hmac_drbg_init, hmac_drbg_next) + |=> + !hmac_drbg_ready[*time_window] + ##1 + hmac_drbg_ready; + endproperty + assume_hmac_drbg_not_ready : assume property(@(posedge clk)disable iff(!rst_n ) hmac_drbg_not_ready(hmac_drbg_ready, hmac_drbg_init, hmac_drbg_next,time_window)); + + + property hmac_drbg_result_then_ready(hmac_drbg_valid, hmac_drbg_ready); + hmac_drbg_valid + |-> + hmac_drbg_ready; + endproperty + assume_hmac_drbg_result_then_ready : assume property(@(posedge clk) hmac_drbg_result_then_ready(hmac_drbg_valid, hmac_drbg_ready)); + + + property for_init(hmac_drbg_init, hmac_drbg_next, hmac_drbg_valid, time_window); + hmac_drbg_init || hmac_drbg_next + |-> + ##(time_window+1) + hmac_drbg_valid; + endproperty + assume_hmac_drbg_valid_after_init_next : assume property(@(posedge clk)disable iff(!rst_n ) for_init(hmac_drbg_init, hmac_drbg_next, hmac_drbg_valid, time_window)); + + + property for_valid(hmac_drbg_valid, hmac_drbg_init, hmac_drbg_next); + hmac_drbg_valid && + !(hmac_drbg_init || hmac_drbg_next) + |=> + hmac_drbg_valid; + endproperty + assume_hmac_drbg_valid_continous : assume property(@(posedge clk)disable iff(!rst_n ) for_valid(hmac_drbg_valid, hmac_drbg_init, hmac_drbg_next)); + + property hmac_drbg_ready_until_init_next(hmac_drbg_ready, hmac_drbg_init, hmac_drbg_next); + hmac_drbg_ready && + (hmac_drbg_init || hmac_drbg_next) + |=> + !hmac_drbg_ready +;endproperty + assume_hmac_drbg_ready_until_init_next : assume property ( @(posedge clk) disable iff(!rst_n ) hmac_drbg_ready_until_init_next(hmac_drbg_ready, hmac_drbg_init, hmac_drbg_next)); + + + property hmac_drbg_valid_zero_in_all_state(hmac_drbg_valid, hmac_drbg_init, hmac_drbg_next,time_window); + !hmac_drbg_valid && + (hmac_drbg_init || hmac_drbg_next) + |=> + !hmac_drbg_valid[*time_window] + ##1 + hmac_drbg_valid; + endproperty + assume_hmac_drbg_valid_zero_in_all_states : assume property (@(posedge clk) disable iff(!rst_n ) hmac_drbg_valid_zero_in_all_state(hmac_drbg_valid, hmac_drbg_init, hmac_drbg_init, time_window)); + + + assume_cntr_nonce_only_64bit: assume property(@(posedge clk) disable iff(!rst_n ) counter_nonce <= 64'hffffffffffffffff); + +endmodule + +bind ecc_hmac_drbg_interface fv_ecc_hmac_drbg_interface_constraints_m fv_ecc_hmac_drbg_interface_constraints ( + .clk(clk), + .rst_n(reset_n && !zeroize), + .hmac_drbg_init(ecc_hmac_drbg_interface.hmac_drbg_init), + .hmac_drbg_next(ecc_hmac_drbg_interface.hmac_drbg_next), + .hmac_drbg_ready(ecc_hmac_drbg_interface.hmac_drbg_ready), + .hmac_drbg_valid(ecc_hmac_drbg_interface.hmac_drbg_valid), + .counter_nonce(ecc_hmac_drbg_interface.counter_nonce) +); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_ecc_pm_ctrl_abstract.sv b/src/ecc/formal/properties/fv_ecc_pm_ctrl_abstract.sv new file mode 100644 index 000000000..48dfb1b7f --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_pm_ctrl_abstract.sv @@ -0,0 +1,1101 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_pm_ctrl_abstract + import ecc_pm_uop_pkg::*; + #( + parameter REG_SIZE = 384, + parameter RND_SIZE = 192, + parameter INSTR_SIZE = 24, + parameter MULT_DLY = 38, + parameter ADD_DLY = 1, + parameter Secp384_MONT_COUNT = 384, + parameter Secp384_SCA_MONT_COUNT = 576 + ) + ( + // Clock and reset. + input wire clk, + input wire rst_n, + + + // from arith_unit + input wire [2 : 0] ecc_cmd_i, + input wire sca_en_i, + input wire digit_i, + input pm_instr_struct_t instr_o, + input logic req_digit_o, + input wire busy_o +); + + /////////////////////////////////////////////////////////////////// + // All the sequences latency from start to end + // The function dly, has the arguments as no. of mult, no. of add+sub + // no. of store operations, rest operations in the sequence + /////////////////////////////////////////////////////////////////// + + localparam CHK_DLY = dly(6,6,3,3,4); + localparam PM_INT_G_DLY = dly(3,3,0,0,0); + localparam PM_INT_DLY = dly(0,0,3,3,4); + localparam PA_DLY = dly(17,17,23,23,0); + localparam PD_DLY = dly(17,17,23,23,4); + localparam CONV_VER0_P1_DLY = dly(4,4,0,0,4); + localparam INV_DLY = dly(519,519,1,1,0); + localparam SIGN0_DLY = dly(7,7,5,5,4); + localparam INVQ_DLY = dly(519,519,1,1,4); + localparam SIGN1_DLY = dly(3,3,1,1,4); + localparam VER0_P0_DLY = dly(3,3,0,0,4); + localparam VER_ST_DLY = dly(0,0,3,3,0); + localparam PM_INT_PK_DLY = dly(2,2,1,1,0); + localparam VER_PA_DLY = dly(17,17,24,24,0); + + localparam PIP_DLY = 3; // The pipeline delay from having the data in instr_o from prog_instr + + + + + + ////////////////////////////////////////// + //Delay computation // + ////////////////////////////////////////// + + function logic [24:0] dly(input logic[11:0] num_mul,input logic[11:0] st_mul,input logic[11:0] num_add_sub,input logic[11:0] st_add_sub,input logic[11:0] rest); + logic [24:0] fv_total_mult_dly; + logic [24:0] fv_total_add_sub_dly; + fv_total_mult_dly = (num_mul*(MULT_DLY+2))+(st_mul); + fv_total_add_sub_dly = (num_add_sub*(ADD_DLY+2))+(st_add_sub); + return(fv_total_mult_dly+fv_total_add_sub_dly+rest-1); + endfunction + + + + + default clocking default_clk @(posedge clk); endclocking + + sequence reset_sequence; + !rst_n ##1 rst_n; + endsequence + + + //////////////////////////////////////////// + // reset property, when reset out and reg // + // are zero // + //////////////////////////////////////////// + + property reset_p; + $past(!rst_n) + |-> + ecc_pm_ctrl.prog_cntr == NOP && + ecc_pm_ctrl.mont_cntr <= '0 && + ecc_pm_ctrl.stall_cntr <= '0 && + ecc_pm_ctrl.stalled <= '0 && + ecc_pm_ctrl.mont_ladder <= '0 && + ecc_pm_ctrl.ecc_cmd_reg <= '0 && + instr_o == '0 && + req_digit_o == '0 && + busy_o == 0; + endproperty + + reset_a : assert property(reset_p); + + + //--------------------------------// + // Unabstracted counter properties// + //-------------------------------// + + // Validates once the check public key cmd is set then the sequence is triggered and finally ends in NOP + property check_point_p(delay); + ecc_cmd_i == CHK_PK_CMD && + ecc_pm_ctrl.prog_cntr == NOP + |=> + ecc_pm_ctrl.prog_cntr == CHK_PK_S + ##delay ecc_pm_ctrl.prog_cntr == CHK_PK_E + ##1 ecc_pm_ctrl.prog_cntr == NOP; + endproperty + check_point_a: assert property(disable iff(!rst_n) check_point_p(CHK_DLY)); + + + // validates once the cmd is set initally it would traverse through PM_INIT_G_S and PM_INIT_S + property pm_init_g_s_to_pm_init_s_p(cmd,delay); + ecc_cmd_i == cmd && + ecc_pm_ctrl.prog_cntr == NOP + |=> + ecc_pm_ctrl.prog_cntr == PM_INIT_G_S && // Initialise R1 with G + ecc_pm_ctrl.mont_cntr == $past((sca_en_i)? ecc_pm_ctrl.Secp384_SCA_MONT_COUNT : ecc_pm_ctrl.Secp384_MONT_COUNT) + ##delay ecc_pm_ctrl.prog_cntr == PM_INIT_G_E + ##1 ecc_pm_ctrl.prog_cntr == PM_INIT_S; // Initialise R0 with (0:1:0) + endproperty + keygen_stage0_a: assert property(disable iff(!rst_n) pm_init_g_s_to_pm_init_s_p(KEYGEN_CMD,PM_INT_G_DLY)); + signing_stage0_a: assert property(disable iff(!rst_n) pm_init_g_s_to_pm_init_s_p(SIGN_CMD,PM_INT_G_DLY)); + + // validates if cmd sequence is ongoing then it would traverse from PM_INIT_S till PA_S + property pm_init_s_to_pa_s_p(cmd,delay); + ecc_pm_ctrl.ecc_cmd_reg == cmd && + ecc_pm_ctrl.prog_cntr == PM_INIT_S + |-> + ##delay ecc_pm_ctrl.prog_cntr == PM_INIT_E + ##1 ecc_pm_ctrl.prog_cntr == PA_S && + ecc_pm_ctrl.mont_cntr == $past(ecc_pm_ctrl.mont_cntr)-1; // Point add + endproperty + keygen_stage1_a: assert property(disable iff(!rst_n) pm_init_s_to_pa_s_p(KEYGEN_CMD,PM_INT_DLY)); + signing_stage1_a: assert property(disable iff(!rst_n) pm_init_s_to_pa_s_p(SIGN_CMD,PM_INT_DLY)); + verify_part1_stage1_a: assert property(disable iff(!rst_n) pm_init_s_to_pa_s_p(VER_PART1_CMD,PM_INT_DLY)); + verify_part2_stage1_a: assert property(disable iff(!rst_n) pm_init_s_to_pa_s_p(VER_PART2_CMD,PM_INT_DLY)); + + + + //validates if cmd sequence is ongoing then it would traverse from PA_S to PD_S + property pa_s_to_pd_s_p(cmd,delay); + ecc_pm_ctrl.ecc_cmd_reg == cmd && + ecc_pm_ctrl.prog_cntr == PA_S + |-> + ##delay ecc_pm_ctrl.prog_cntr == PA_E + ##1 ecc_pm_ctrl.prog_cntr == PD_S; + endproperty + keygen_stage1_1_a: assert property(disable iff(!rst_n) pa_s_to_pd_s_p(KEYGEN_CMD,PA_DLY)); + signing_stage1_1_a: assert property(disable iff(!rst_n) pa_s_to_pd_s_p(SIGN_CMD,PA_DLY)); + verify_part1_stage1_1_a: assert property(disable iff(!rst_n) pa_s_to_pd_s_p(VER_PART1_CMD,PA_DLY)); + verify_part2_stage1_1_a: assert property(disable iff(!rst_n) pa_s_to_pd_s_p(VER_PART2_CMD,PA_DLY)); + + + + //validates if cmd sequence is ongoing then it would traverse from PD_S to PD_E + property pd_s_to_pd_e_p(cmd,delay); + ecc_pm_ctrl.ecc_cmd_reg == cmd && + ecc_pm_ctrl.prog_cntr == PD_S + |-> + ##delay ecc_pm_ctrl.prog_cntr == PD_E; + endproperty + keygen_stage2_1_a: assert property(disable iff(!rst_n) pd_s_to_pd_e_p(KEYGEN_CMD,PD_DLY)); + signing_stage2_1_a: assert property(disable iff(!rst_n) pd_s_to_pd_e_p(SIGN_CMD,PD_DLY)); + verify_part1_stage2_1_a: assert property(disable iff(!rst_n) pd_s_to_pd_e_p(VER_PART1_CMD,PD_DLY)); + verify_part2_stage2_1_a: assert property(disable iff(!rst_n) pd_s_to_pd_e_p(VER_PART2_CMD,PD_DLY)); + + + //validates if cmd sequence is ongoing then it would traverse from PD_E to INV_S when the mont_cntr is zero + property pd_e_to_invs_p(cmd); + ecc_pm_ctrl.ecc_cmd_reg == cmd && + ecc_pm_ctrl.prog_cntr == PD_E && + ecc_pm_ctrl.mont_cntr == 0 + |-> + ##1 ecc_pm_ctrl.prog_cntr == INV_S; + endproperty + keygen_stage2_a: assert property(disable iff(!rst_n) pd_e_to_invs_p(KEYGEN_CMD)); + signing_stage2_a: assert property(disable iff(!rst_n) pd_e_to_invs_p(SIGN_CMD)); + + // validates if cmd sequence is ongoing then it would traverse from PD_E to PA_S when the mont_cntr is not zero + property pd_e_to_pa_s_p(cmd); + ecc_pm_ctrl.ecc_cmd_reg == cmd && + ecc_pm_ctrl.prog_cntr == PD_E && + ecc_pm_ctrl.mont_cntr != 0 + |-> + ##1 ecc_pm_ctrl.prog_cntr == PA_S && + ecc_pm_ctrl.mont_cntr == $past(ecc_pm_ctrl.mont_cntr)-1; + endproperty + keygen_stage2_loop_a: assert property(disable iff(!rst_n) pd_e_to_pa_s_p(KEYGEN_CMD)); + signing_stage2_loop_a: assert property(disable iff(!rst_n) pd_e_to_pa_s_p(SIGN_CMD)); + verify_part1_stage2_loop_a: assert property(disable iff(!rst_n) pd_e_to_pa_s_p(VER_PART1_CMD)); + verify_part2_stage2_loop_a: assert property(disable iff(!rst_n) pd_e_to_pa_s_p(VER_PART2_CMD)); + + //validates if cmd sequence is ongoing then it would traverse from INV_E to CONV_S + property inve_to_convs_p(cmd); + ecc_pm_ctrl.ecc_cmd_reg == cmd && + ecc_pm_ctrl.prog_cntr == INV_E[*(MULT_DLY+2)] //[*3] for mult delay 1 + |-> + ##1 ecc_pm_ctrl.prog_cntr == CONV_S; + endproperty + keygen_stage3_a: assert property(disable iff(!rst_n) inve_to_convs_p(KEYGEN_CMD)); + signing_stage3_a: assert property(disable iff(!rst_n) inve_to_convs_p(SIGN_CMD)); + verify_part2_stage3_2_a: assert property(disable iff(!rst_n) inve_to_convs_p(VER_PART2_CMD)); + + //validates if cmd sequence is ongoing then it would traverse from INV_S to INV_E + property invs_to_inve_p(cmd,delay); + ecc_pm_ctrl.ecc_cmd_reg == cmd && + ecc_pm_ctrl.prog_cntr == INV_S //[*3] for mult delay 1 + |-> + ##delay ecc_pm_ctrl.prog_cntr == INV_E; + endproperty + keygen_stage3_1_a: assert property(disable iff(!rst_n) invs_to_inve_p(KEYGEN_CMD,INV_DLY)); + signing_stage3_1_a: assert property(disable iff(!rst_n) invs_to_inve_p(SIGN_CMD,INV_DLY)); + verify_part2_stage3_1_a: assert property(disable iff(!rst_n) invs_to_inve_p(VER_PART2_CMD,INV_DLY)); + + + //validates if cmd sequence is ongoing then it would traverse from CONV_S to NOP + property convs_to_nop(cmd,delay); + ecc_pm_ctrl.ecc_cmd_reg == cmd && + ecc_pm_ctrl.prog_cntr == CONV_S + |-> + ##delay ecc_pm_ctrl.prog_cntr == CONV_E //##19 mult delay 1 + ##1 ecc_pm_ctrl.prog_cntr == NOP; + endproperty + keygen_stage4_a: assert property(disable iff(!rst_n) convs_to_nop(KEYGEN_CMD,CONV_VER0_P1_DLY)); + verify_part2_stage4_a: assert property(disable iff(!rst_n) convs_to_nop(VER_PART2_CMD,CONV_VER0_P1_DLY)); + + + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [PROG_ADDR_W-1 : 0] counter_keygen_a; + logic [PROG_ADDR_W-1 : 0] counter_keygen_b; + logic trigger_counter_keygen_a_reg; + logic trigger_counter_keygen_b_reg; + logic triggered_counter_keygen_a; + logic triggered_counter_keygen_b; + + counter_nonreachable_values: assume property (disable iff(!rst_n)counter_nonreachable_values_p); + property counter_nonreachable_values_p; + counter_keygen_a != PM_INIT_G_E+1 && counter_keygen_b != PM_INIT_G_E+1 && + counter_keygen_a != PM_INIT_E+1 && counter_keygen_b != PM_INIT_E+1 && + counter_keygen_a != INV_E+1 && counter_keygen_b != INV_E+1 && + counter_keygen_a != PA_E+1 && counter_keygen_b != PA_E+1 && + counter_keygen_a != PD_E+1 && counter_keygen_b != PD_E+1 && + counter_keygen_a != INV_E+1 && counter_keygen_b != INV_E+1; + endproperty + + counter_keygen_a_assume: assume property(disable iff(!rst_n) (counter_keygen_a >=PM_INIT_G_S) && (counter_keygen_a <=CONV_E) && $stable(counter_keygen_a)); + counter_keygen_b_assume: assume property(disable iff(!rst_n) (counter_keygen_b <=CONV_E) && (counter_keygen_b > counter_keygen_a) && $stable(counter_keygen_b)); + + assign trigger_counter_keygen_a_reg = (ecc_pm_ctrl.prog_cntr==counter_keygen_a); + assign trigger_counter_keygen_b_reg = (ecc_pm_ctrl.prog_cntr==counter_keygen_b); + always_ff @(posedge clk, negedge rst_n) begin + if(!rst_n) begin + triggered_counter_keygen_a <= '0; + triggered_counter_keygen_b <= '0; + end + else begin + if(ecc_pm_ctrl.ecc_cmd_reg==KEYGEN_CMD) begin + if(trigger_counter_keygen_a_reg) begin + triggered_counter_keygen_a <= 1; + end + if(trigger_counter_keygen_b_reg) begin + triggered_counter_keygen_b <= 1; + end + end + end + end + + property liveness_p(cmd,trigered); + ecc_cmd_i == cmd && + ecc_pm_ctrl.prog_cntr == NOP + |-> + s_eventually(trigered); + endproperty + counter_keygen_a_liveness_a: assert property(disable iff(!rst_n) liveness_p(KEYGEN_CMD,triggered_counter_keygen_a)); + counter_keygen_b_liveness_a: assert property(disable iff(!rst_n) liveness_p(KEYGEN_CMD,triggered_counter_keygen_b)); + + //property to order_check + property order_check_p(triggered_a,triggered_b); + triggered_b + |=> + $past(triggered_a); + endproperty + keygen_order_check_a: assert property(disable iff(!rst_n) order_check_p(triggered_counter_keygen_a,triggered_counter_keygen_b)); + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + //------------------------------------// + // Signing staging + //------------------------------------// + + + //validates if signing sequence is ongoing then it would traverse from CONV_S till INVq_S + property signing_stage3_2_p(delay1,delay2); + ecc_pm_ctrl.ecc_cmd_reg == SIGN_CMD && + ecc_pm_ctrl.prog_cntr == CONV_S + |-> + ##delay1 ecc_pm_ctrl.prog_cntr == CONV_E // conversion to affine r compute done + ##1 ecc_pm_ctrl.prog_cntr == SIGN0_S // (d + r (privKey-d)),((h-d) + r.d) + ##delay2 ecc_pm_ctrl.prog_cntr == SIGN0_E + ##1 ecc_pm_ctrl.prog_cntr == INVq_S; // k inverse ##52 mult delay 1 + endproperty + signing_stage3_2_a: assert property(disable iff(!rst_n) signing_stage3_2_p(CONV_VER0_P1_DLY,SIGN0_DLY)); + + + //validates if signing sequence is ongoing then it would traverse from INVq_S till INVq_E + property signing_stage4_1_p(delay); + ecc_pm_ctrl.ecc_cmd_reg == SIGN_CMD && + ecc_pm_ctrl.prog_cntr == INVq_S + |-> + ##delay ecc_pm_ctrl.prog_cntr == INVq_E; + endproperty + signing_stage4_1_a: assert property(disable iff(!rst_n) signing_stage4_1_p(INVQ_DLY)); + + + //validates if signing sequence is ongoing then it would traverse from INVq_E till NOP + property signing_stage4_p(delay); + ecc_pm_ctrl.ecc_cmd_reg == SIGN_CMD && + ecc_pm_ctrl.prog_cntr == INVq_E + |-> + ##1 ecc_pm_ctrl.prog_cntr == SIGN1_S // final value s [k^-1((h-d) + r (privKey-d))] + [k^-1(d + r.d)] mod q + ##delay ecc_pm_ctrl.prog_cntr == SIGN1_E + ##1 ecc_pm_ctrl.prog_cntr == NOP ; // ##20 mult delay 1 + endproperty + signing_stage4_a: assert property(disable iff(!rst_n) signing_stage4_p(SIGN1_DLY)); + + + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [PROG_ADDR_W-1 : 0] counter_sign_a; + logic [PROG_ADDR_W-1 : 0] counter_sign_b; + logic trigger_counter_sign_a_reg; + logic trigger_counter_sign_b_reg; + logic triggered_counter_sign_a; + logic triggered_counter_sign_b; + + counter_nonreachable_values_in_sign: assume property (disable iff(!rst_n)counter_nonreachable_values_in_sign_p); + property counter_nonreachable_values_in_sign_p; + counter_sign_a != PM_INIT_G_E+1 && counter_sign_b != PM_INIT_G_E+1 && + counter_sign_a != PM_INIT_E+1 && counter_sign_b != PM_INIT_E+1 && + counter_sign_a != INV_E+1 && counter_sign_b != INV_E+1 && + counter_sign_a != PA_E+1 && counter_sign_b != PA_E+1 && + counter_sign_a != PD_E+1 && counter_sign_b != PD_E+1 && + counter_sign_a != INV_E+1 && counter_sign_b != INV_E+1 && + counter_sign_a != CONV_E+1 && counter_sign_b != CONV_E+1 && + counter_sign_a != SIGN0_E+1 && counter_sign_b != SIGN0_E+1 && + counter_sign_a != INVq_E+1 && counter_sign_b != INVq_E+1 + ; + endproperty + + counter_sign_a_assume: assume property(disable iff(!rst_n) (counter_sign_a >=PM_INIT_G_S) && (counter_sign_a <=SIGN1_E) && $stable(counter_sign_a)); + counter_sign_b_assume: assume property(disable iff(!rst_n) (counter_sign_b <=SIGN1_E) && (counter_sign_b > counter_sign_a) && $stable(counter_sign_b)); + + assign trigger_counter_sign_a_reg = (ecc_pm_ctrl.prog_cntr==counter_sign_a); + assign trigger_counter_sign_b_reg = (ecc_pm_ctrl.prog_cntr==counter_sign_b); + always_ff @(posedge clk, negedge rst_n) begin + if(!rst_n) begin + triggered_counter_sign_a <= '0; + triggered_counter_sign_b <= '0; + end + else begin + if(ecc_pm_ctrl.ecc_cmd_reg==SIGN_CMD) begin + if(trigger_counter_sign_a_reg) begin + triggered_counter_sign_a <= 1; + end + if(trigger_counter_sign_b_reg) begin + triggered_counter_sign_b <= 1; + end + end + end + end + + counter_sign_a_liveness_a: assert property(disable iff(!rst_n) liveness_p(SIGN_CMD,triggered_counter_sign_a)); + + counter_sign_b_liveness_a: assert property(disable iff(!rst_n) liveness_p(SIGN_CMD,triggered_counter_sign_b)); + + order_check_sign_a: assert property(disable iff(!rst_n) order_check_p(triggered_counter_sign_a,triggered_counter_sign_b)); + + + + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + + //--------------------------------------// + // Verifying staging + //-------------------------------------// + + //Validates once the VER_PART0_CMD is triggered then it would traverse itll INVq_S + property verify_part0_stage0_p(delay); + ecc_cmd_i == VER_PART0_CMD && + ecc_pm_ctrl.prog_cntr == NOP + |=> + ecc_pm_ctrl.prog_cntr == VER0_P0_S //convert h,r,s inputs to mont + ##delay ecc_pm_ctrl.prog_cntr == VER0_P0_E + ##1 ecc_pm_ctrl.prog_cntr == INVq_S; // compute s inverse //##16 mult delay 1 + endproperty + verify_part0_stage0_a: assert property(disable iff(!rst_n) verify_part0_stage0_p(VER0_P0_DLY)); + + + //validates if the verify part0 is ongoing then it would traverse from INVq_s to INVq_E + property verify_part0_stage1_1_p(delay); + ecc_pm_ctrl.ecc_cmd_reg == VER_PART0_CMD && + ecc_pm_ctrl.prog_cntr == INVq_S + |-> + ##delay ecc_pm_ctrl.prog_cntr == INVq_E; + endproperty + verify_part0_stage1_1_a: assert property(disable iff(!rst_n) verify_part0_stage1_1_p(INVQ_DLY)); + + + //validates if the verify part0 is ongoing then finally it would end in NOP + property verify_part0_stage1_p(delay); + ecc_pm_ctrl.ecc_cmd_reg == VER_PART0_CMD && + ecc_pm_ctrl.prog_cntr == INVq_E + |-> + ##1 ecc_pm_ctrl.prog_cntr == VER0_P1_S // compute h*s_inv and r*s_inv + ##delay ecc_pm_ctrl.prog_cntr == VER0_P1_E + ##1 ecc_pm_ctrl.prog_cntr == NOP; // ##20 mult delay 1 + endproperty + verify_part0_stage1_a: assert property(disable iff(!rst_n) verify_part0_stage1_p(CONV_VER0_P1_DLY)); + + + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [PROG_ADDR_W-1 : 0] counter_ver_p0_a; + logic [PROG_ADDR_W-1 : 0] counter_ver_p0_b; + logic [PROG_ADDR_W-1 : 0] counter_ver_p0_c; + logic [PROG_ADDR_W-1 : 0] counter_ver_p0_a_1; + logic [PROG_ADDR_W-1 : 0] counter_ver_p0_b_1; + logic [PROG_ADDR_W-1 : 0] counter_ver_p0_c_1; + logic trigger_counter_ver_p0_a_reg; + logic trigger_counter_ver_p0_b_reg; + logic trigger_counter_ver_p0_c_reg; + logic trigger_counter_ver_p0_a_1_reg; + logic trigger_counter_ver_p0_b_1_reg; + logic trigger_counter_ver_p0_c_1_reg; + logic triggered_counter_ver_p0_a; + logic triggered_counter_ver_p0_b; + logic triggered_counter_ver_p0_c; + logic triggered_counter_ver_p0_a_1; + logic triggered_counter_ver_p0_b_1; + logic triggered_counter_ver_p0_c_1; + + + + counter_ver_p0_a_assume: assume property(disable iff(!rst_n) (counter_ver_p0_a <=VER0_P0_E) && (counter_ver_p0_a >=VER0_P0_S) && $stable(counter_ver_p0_a)); + counter_ver_p0_a_1_assume: assume property(disable iff(!rst_n) (counter_ver_p0_a_1 <=VER0_P0_E) && (counter_ver_p0_a_1 > counter_ver_p0_a) && $stable(counter_ver_p0_a_1)); + counter_ver_p0_b_assume: assume property(disable iff(!rst_n) (counter_ver_p0_b >=INVq_S) && (counter_ver_p0_b <=INVq_E) && $stable(counter_ver_p0_b)); + counter_ver_p0_b_1_assume: assume property(disable iff(!rst_n) (counter_ver_p0_b_1 >counter_ver_p0_b) && (counter_ver_p0_b_1 <=INVq_E) && $stable(counter_ver_p0_b_1)); + counter_ver_p0_c_assume: assume property(disable iff(!rst_n) (counter_ver_p0_c <=VER0_P1_E) && ((counter_ver_p0_c >=VER0_P1_S)) && $stable(counter_ver_p0_c)); + counter_ver_p0_c_1_assume: assume property(disable iff(!rst_n) (counter_ver_p0_c_1 <=VER0_P1_E) && ((counter_ver_p0_c_1 > counter_ver_p0_c)) && $stable(counter_ver_p0_c_1)); + + assign trigger_counter_ver_p0_a_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p0_a); + assign trigger_counter_ver_p0_b_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p0_b); + assign trigger_counter_ver_p0_c_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p0_c); + assign trigger_counter_ver_p0_a_1_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p0_a_1); + assign trigger_counter_ver_p0_b_1_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p0_b_1); + assign trigger_counter_ver_p0_c_1_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p0_c_1); + + always_ff @(posedge clk, negedge rst_n) begin + if(!rst_n) begin + triggered_counter_ver_p0_a <= '0; + triggered_counter_ver_p0_b <= '0; + triggered_counter_ver_p0_c <= '0; + triggered_counter_ver_p0_a_1 <= '0; + triggered_counter_ver_p0_b_1 <= '0; + triggered_counter_ver_p0_c_1 <= '0; + end + else begin + if(ecc_pm_ctrl.ecc_cmd_reg==VER_PART0_CMD) begin + if(trigger_counter_ver_p0_a_reg) begin + triggered_counter_ver_p0_a <= 1; + end + if(trigger_counter_ver_p0_b_reg) begin + triggered_counter_ver_p0_b <= 1; + end + if(trigger_counter_ver_p0_c_reg) begin + triggered_counter_ver_p0_c <= 1; + end + if(trigger_counter_ver_p0_a_1_reg) begin + triggered_counter_ver_p0_a_1 <= 1; + end + if(trigger_counter_ver_p0_b_1_reg) begin + triggered_counter_ver_p0_b_1 <= 1; + end + if(trigger_counter_ver_p0_c_1_reg) begin + triggered_counter_ver_p0_c_1 <= 1; + end + end + end + end + + + counter_ver_p0_a_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART0_CMD,triggered_counter_ver_p0_a)); + + counter_ver_p0_b_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART0_CMD,triggered_counter_ver_p0_b)); + + counter_ver_p0_c_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART0_CMD,triggered_counter_ver_p0_c)); + + counter_intrnl_ver0_p0_s_a: assert property(disable iff(!rst_n) order_check_p(triggered_counter_ver_p0_a,triggered_counter_ver_p0_a_1)); + + counter_staging0_ver_p0_a: assert property(disable iff(!rst_n) order_check_p((triggered_counter_ver_p0_a & triggered_counter_ver_p0_a_1 & triggered_counter_ver_p0_b),triggered_counter_ver_p0_b_1)); + + counter_staging1_ver_p0_a: assert property(disable iff(!rst_n) order_check_p((triggered_counter_ver_p0_a & triggered_counter_ver_p0_b & triggered_counter_ver_p0_c & triggered_counter_ver_p0_a_1 & triggered_counter_ver_p0_b_1),triggered_counter_ver_p0_c_1)); + + + + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + + + + //validates once the verify part1 is set initally it would traverse through PM_INIT_G_S and PM_INIT_S + property verify_part1_stage0_p(delay); + ecc_cmd_i == VER_PART1_CMD && + ecc_pm_ctrl.prog_cntr == NOP + |=> + ecc_pm_ctrl.prog_cntr == PM_INIT_G_S && // Initialise R1 with G + ecc_pm_ctrl.mont_cntr == ecc_pm_ctrl.Secp384_MONT_COUNT + ##delay ecc_pm_ctrl.prog_cntr == PM_INIT_G_E + ##1 ecc_pm_ctrl.prog_cntr == PM_INIT_S; // Initialise R0 with (0:1:0) + endproperty + verify_part1_stage0_a: assert property(disable iff(!rst_n) verify_part1_stage0_p(PM_INT_G_DLY)); + + + //validates if verify part1 sequence is ongoing then it would traverse from PD_E to NOP when the mont_cntr is zero + property verify_part1_stage2_p; + ecc_pm_ctrl.ecc_cmd_reg == VER_PART1_CMD && + ecc_pm_ctrl.prog_cntr == PD_E && + ecc_pm_ctrl.mont_cntr == 0 + |-> + ##1 ecc_pm_ctrl.prog_cntr == NOP; //(h*s^-1)*G + endproperty + verify_part1_stage2_a: assert property(disable iff(!rst_n) verify_part1_stage2_p); + + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [PROG_ADDR_W-1 : 0] counter_ver_p1_a; + logic [PROG_ADDR_W-1 : 0] counter_ver_p1_b; + logic trigger_counter_ver_p1_a_reg; + logic trigger_counter_ver_p1_b_reg; + logic triggered_counter_ver_p1_a; + logic triggered_counter_ver_p1_b; + + counter_nonreachable_values_in_ver_p1: assume property (disable iff(!rst_n)counter_nonreachable_values_in_ver_p1_p); + property counter_nonreachable_values_in_ver_p1_p; + counter_ver_p1_a != PM_INIT_G_E+1 && counter_ver_p1_b != PM_INIT_G_E+1 && + counter_ver_p1_a != PM_INIT_E+1 && counter_ver_p1_b != PM_INIT_E+1 && + counter_ver_p1_a != INV_E+1 && counter_ver_p1_b != INV_E+1 && + counter_ver_p1_a != PA_E+1 && counter_ver_p1_b != PA_E+1; + + endproperty + + counter_ver_p1_a_assume: assume property(disable iff(!rst_n) (counter_ver_p1_a >=PM_INIT_G_S) && (counter_ver_p1_a <=PD_E) && $stable(counter_ver_p1_a)); + counter_ver_p1_b_assume: assume property(disable iff(!rst_n) (counter_ver_p1_b <=PD_E) && (counter_ver_p1_b > counter_ver_p1_a) && $stable(counter_ver_p1_b)); + + assign trigger_counter_ver_p1_a_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p1_a); + assign trigger_counter_ver_p1_b_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p1_b); + always_ff @(posedge clk, negedge rst_n) begin + if(!rst_n) begin + triggered_counter_ver_p1_a <= '0; + triggered_counter_ver_p1_b <= '0; + end + else begin + if (ecc_pm_ctrl.ecc_cmd_reg == VER_PART1_CMD) begin + if(trigger_counter_ver_p1_a_reg) begin + triggered_counter_ver_p1_a <= 1; + end + if(trigger_counter_ver_p1_b_reg) begin + triggered_counter_ver_p1_b <= 1; + end + end + end + end + + counter_ver_p1_a_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART1_CMD,triggered_counter_ver_p1_a)); + + counter_ver_p1_b_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART1_CMD,triggered_counter_ver_p1_b)); + + counter_order_check_ver_p1_a: assert property(disable iff(!rst_n) order_check_p(triggered_counter_ver_p1_a,triggered_counter_ver_p1_b)); + + + + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + + // validates once the verify part2 is set initally it would traverse through VER1_ST_S and PM_INIT_S + property verify_part2_stage0_p(delay1,delay2); + ecc_cmd_i == VER_PART2_CMD && + ecc_pm_ctrl.prog_cntr == NOP + |=> + ecc_pm_ctrl.prog_cntr == VER1_ST_S //store (h*s^-1)*G in P1 address + ##delay1 ecc_pm_ctrl.prog_cntr == VER1_ST_E + ##1 ecc_pm_ctrl.prog_cntr == PM_INIT_PK_S // Pubkey in R1 + ##delay2 ecc_pm_ctrl.prog_cntr == PM_INIT_PK_E + ##1 ecc_pm_ctrl.prog_cntr == PM_INIT_S; // Initialise R0 with (0:1:0) ##12 mult delay 1 + endproperty + verify_part2_stage0_a: assert property(disable iff(!rst_n) verify_part2_stage0_p(VER_ST_DLY,PM_INT_PK_DLY)); + + + //validates if verify part2 sequence is ongoing then it would traverse from PD_E to VER2_PA_S when the mont_cntr is zero + property verify_part2_stage2_p; + ecc_pm_ctrl.ecc_cmd_reg == VER_PART2_CMD && + ecc_pm_ctrl.prog_cntr == PD_E && + ecc_pm_ctrl.mont_cntr == 0 + |-> + ##1 ecc_pm_ctrl.prog_cntr == VER2_PA_S ; // add (h*s_inv)*G, (r*s_inv)*PK) + endproperty + verify_part2_stage2_a: assert property(disable iff(!rst_n) verify_part2_stage2_p); + + + + //validates if verify part2 sequence is ongoing then it would traverse from VER2_PA_S till INV_S + property verify_part2_stage3_p(delay); + ecc_pm_ctrl.ecc_cmd_reg == VER_PART2_CMD && + ecc_pm_ctrl.prog_cntr == VER2_PA_S + |-> + ##delay ecc_pm_ctrl.prog_cntr == VER2_PA_E + ##1 ecc_pm_ctrl.prog_cntr == INV_S ; // Inv z coordinate + endproperty + verify_part2_stage3_a: assert property(disable iff(!rst_n) verify_part2_stage3_p(VER_PA_DLY)); + + +///////////////////////////////////////////////////////////////////////////////////// +// ---------------------------------BEGIN----------------------------------------- // +// Checking the counter integrity that the sequence is performed one after another // +///////////////////////////////////////////////////////////////////////////////////// + + logic [PROG_ADDR_W-1 : 0] counter_ver_p2_a; + logic [PROG_ADDR_W-1 : 0] counter_ver_p2_b; + logic [PROG_ADDR_W-1 : 0] counter_ver_p2_c; + logic [PROG_ADDR_W-1 : 0] counter_ver_p2_d; + logic [PROG_ADDR_W-1 : 0] counter_ver_p2_a_1; + logic [PROG_ADDR_W-1 : 0] counter_ver_p2_b_1; + logic [PROG_ADDR_W-1 : 0] counter_ver_p2_c_1; + logic [PROG_ADDR_W-1 : 0] counter_ver_p2_d_1; + logic trigger_counter_ver_p2_a_1_reg; + logic trigger_counter_ver_p2_b_1_reg; + logic trigger_counter_ver_p2_c_1_reg; + logic trigger_counter_ver_p2_d_1_reg; + logic triggered_counter_ver_p2_a_1; + logic triggered_counter_ver_p2_b_1; + logic triggered_counter_ver_p2_c_1; + logic triggered_counter_ver_p2_d_1; + logic trigger_counter_ver_p2_a_reg; + logic trigger_counter_ver_p2_b_reg; + logic trigger_counter_ver_p2_c_reg; + logic trigger_counter_ver_p2_d_reg; + logic triggered_counter_ver_p2_a; + logic triggered_counter_ver_p2_b; + logic triggered_counter_ver_p2_c; + logic triggered_counter_ver_p2_d; + + counter_nonreachable_values_in_ver_p2: assume property (disable iff(!rst_n)counter_nonreachable_values_in_ver_p2_p); + property counter_nonreachable_values_in_ver_p2_p; + + counter_ver_p2_a != VER1_ST_E+1 && counter_ver_p2_a_1 != VER1_ST_E+1 && + counter_ver_p2_b != PM_INIT_E+1 && counter_ver_p2_b_1 != PM_INIT_E+1 && + counter_ver_p2_b != PA_E+1 && counter_ver_p2_b_1 != PA_E+1 && + counter_ver_p2_d!= INV_E+1 && counter_ver_p2_d_1!= INV_E+1 + ; + endproperty + + counter_ver_p2_a_assume: assume property(disable iff(!rst_n) (counter_ver_p2_a >=VER1_ST_S) && (counter_ver_p2_a <=PM_INIT_PK_E) && $stable(counter_ver_p2_a)); + counter_ver_p2_a_1_assume: assume property(disable iff(!rst_n) (counter_ver_p2_a_1 > counter_ver_p2_a) && (counter_ver_p2_a_1 <=PM_INIT_PK_E) && $stable(counter_ver_p2_a_1)); + + counter_ver_p2_b_assume: assume property(disable iff(!rst_n) (counter_ver_p2_b <=PD_E) && (counter_ver_p2_b >= PM_INIT_S) && $stable(counter_ver_p2_b)); + counter_ver_p2_b_1_assume: assume property(disable iff(!rst_n) (counter_ver_p2_b_1 <=PD_E) && (counter_ver_p2_b_1 > counter_ver_p2_b) && $stable(counter_ver_p2_b_1)); + + counter_ver_p2_c_assume: assume property(disable iff(!rst_n) (counter_ver_p2_c >=VER2_PA_S) && (counter_ver_p2_c <=VER2_PA_E) && $stable(counter_ver_p2_c)); + counter_ver_p2_c_1_assume: assume property(disable iff(!rst_n) (counter_ver_p2_c_1 >counter_ver_p2_c) && (counter_ver_p2_c_1 <=VER2_PA_E) && $stable(counter_ver_p2_c_1)); + + counter_ver_p2_d_assume: assume property(disable iff(!rst_n) (counter_ver_p2_d <=CONV_E) && (counter_ver_p2_d >= INV_S) && $stable(counter_ver_p2_d)); + counter_ver_p2_d_1_assume: assume property(disable iff(!rst_n) (counter_ver_p2_d_1 <=CONV_E) && (counter_ver_p2_d_1 > counter_ver_p2_d) && $stable(counter_ver_p2_d_1)); + + assign trigger_counter_ver_p2_a_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p2_a); + assign trigger_counter_ver_p2_b_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p2_b); + + assign trigger_counter_ver_p2_c_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p2_c); + assign trigger_counter_ver_p2_d_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p2_d); + + assign trigger_counter_ver_p2_a_1_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p2_a_1); + assign trigger_counter_ver_p2_b_1_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p2_b_1); + + assign trigger_counter_ver_p2_c_1_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p2_c_1); + assign trigger_counter_ver_p2_d_1_reg = (ecc_pm_ctrl.prog_cntr==counter_ver_p2_d_1); + + always_ff @(posedge clk, negedge rst_n) begin + if(!rst_n) begin + triggered_counter_ver_p2_a <= '0; + triggered_counter_ver_p2_b <= '0; + triggered_counter_ver_p2_c <= '0; + triggered_counter_ver_p2_d <= '0; + triggered_counter_ver_p2_a_1 <= '0; + triggered_counter_ver_p2_b_1 <= '0; + triggered_counter_ver_p2_c_1 <= '0; + triggered_counter_ver_p2_d_1 <= '0; + end + else begin + if(ecc_pm_ctrl.ecc_cmd_reg == VER_PART2_CMD) begin + if(trigger_counter_ver_p2_a_reg) begin + triggered_counter_ver_p2_a <= 1; + end + if(trigger_counter_ver_p2_b_reg) begin + triggered_counter_ver_p2_b <= 1; + end + if(trigger_counter_ver_p2_c_reg) begin + triggered_counter_ver_p2_c <= 1; + end + if(trigger_counter_ver_p2_d_reg) begin + triggered_counter_ver_p2_d <= 1; + end + if(trigger_counter_ver_p2_a_1_reg) begin + triggered_counter_ver_p2_a_1 <= 1; + end + if(trigger_counter_ver_p2_b_1_reg) begin + triggered_counter_ver_p2_b_1 <= 1; + end + if(trigger_counter_ver_p2_c_1_reg) begin + triggered_counter_ver_p2_c_1 <= 1; + end + if(trigger_counter_ver_p2_d_1_reg) begin + triggered_counter_ver_p2_d_1 <= 1; + end + end + end + end + + + counter_ver_p2_a_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART2_CMD,triggered_counter_ver_p2_a)); + + + counter_ver_p2_b_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART2_CMD,triggered_counter_ver_p2_b)); + + counter_ver_p2_c_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART2_CMD,triggered_counter_ver_p2_c)); + + counter_ver_p2_d_liveness_a: assert property(disable iff(!rst_n) liveness_p(VER_PART2_CMD,triggered_counter_ver_p2_d)); + + counter_intrnl_ver_p2_a: assert property(disable iff(!rst_n) order_check_p(triggered_counter_ver_p2_a,triggered_counter_ver_p2_a_1)); + + counter_staging0_ver_p2_a: assert property(disable iff(!rst_n) order_check_p((triggered_counter_ver_p2_a & triggered_counter_ver_p2_a_1 & triggered_counter_ver_p2_b),triggered_counter_ver_p2_b_1)); + + counter_staging1_ver_p2_a: assert property(disable iff(!rst_n) order_check_p((triggered_counter_ver_p2_a & triggered_counter_ver_p2_b & triggered_counter_ver_p2_c & triggered_counter_ver_p2_a_1 & triggered_counter_ver_p2_b_1), triggered_counter_ver_p2_c_1)); + + counter_staging2_ver_p2_a: assert property(disable iff(!rst_n) order_check_p((triggered_counter_ver_p2_a & triggered_counter_ver_p2_b & triggered_counter_ver_p2_c & triggered_counter_ver_p2_d & triggered_counter_ver_p2_a_1 & triggered_counter_ver_p2_b_1 & triggered_counter_ver_p2_c_1),triggered_counter_ver_p2_d_1)); + + + +///////////////////////////////////////////////////////////////////////////////////// +// ------------------------------------END---------------------------------------- // +///////////////////////////////////////////////////////////////////////////////////// + + + + + //If the prog_cntr is not NOP then the pm_ctrl is busy + property busy_p; + ecc_pm_ctrl.prog_cntr != NOP + |-> + busy_o; + endproperty + busy_a: assert property(disable iff(!rst_n) busy_p); + + //If the prog_cntr is NOP then the pm_ctrl is not busy + property no_busy_p; + (ecc_pm_ctrl.prog_cntr == NOP) + |-> + !busy_o; + endproperty + no_busy_a: assert property(disable iff(!rst_n) no_busy_p); + + + //req_digit_o is set only when the mont_cntr is not zero in PD_E step or the very first rotation i.e in PM_INIT_E + property req_digit_p; + (ecc_pm_ctrl.prog_cntr == PD_E && ecc_pm_ctrl.mont_cntr!=0) || + (ecc_pm_ctrl.prog_cntr == PM_INIT_E) + |=> + req_digit_o; + endproperty + req_digit_a: assert property(disable iff(!rst_n) req_digit_p); + + + //req_digit_o is zero when the mont_cntr is zero in PD_E step or it is not the very first rotation i.e in PM_INIT_E + property no_req_digit_p; + !(ecc_pm_ctrl.prog_cntr == PD_E && ecc_pm_ctrl.mont_cntr!=0) && + !(ecc_pm_ctrl.prog_cntr == PM_INIT_E) + |=> + !req_digit_o; + endproperty + no_req_digit_a: assert property(disable iff(!rst_n) no_req_digit_p); + + + //req_digit_o trigger mont_cntr times + property mont_multiples_req_digit_o_p(cmd,count); + $rose(ecc_pm_ctrl.ecc_cmd_reg == cmd) + |-> + strong((req_digit_o && (ecc_pm_ctrl.prog_cntr==PA_S))[->count] ##1( ecc_pm_ctrl.mont_cntr==0)) ; + endproperty + keygen_mont_multiples_req_digit_o_a:assert property(disable iff(!rst_n) mont_multiples_req_digit_o_p(KEYGEN_CMD,Secp384_SCA_MONT_COUNT)); + signing_mont_multiples_req_digit_o_a:assert property(disable iff(!rst_n) mont_multiples_req_digit_o_p(SIGN_CMD,Secp384_SCA_MONT_COUNT)); + ver_p1_mont_multiples_req_digit_o_a:assert property(disable iff(!rst_n) mont_multiples_req_digit_o_p(VER_PART1_CMD,Secp384_MONT_COUNT)); + ver_p2_mont_multiples_req_digit_o_a:assert property(disable iff(!rst_n) mont_multiples_req_digit_o_p(VER_PART2_CMD,Secp384_MONT_COUNT)); + + + //when output of pm_sequencer instruction is add it would be on primary output after 3 cycles and stays stable for the delay time +2 + property opcode_add_p; + ecc_pm_ctrl.prog_instr.opcode.add_en + |-> + ##PIP_DLY + instr_o.opcode == $past(ecc_pm_ctrl.prog_instr.opcode,3) + ##1 instr_o.opcode ==$past(instr_o.opcode)[*(ADD_DLY+1)]; + endproperty + opcode_add_a: assert property(disable iff(!rst_n) opcode_add_p); + + + //when output of pm_sequencer instruction is multiplication it would be on primary output after 3 cycles and stays stable for the delay time +2 + property opcode_mul_p; + ecc_pm_ctrl.prog_instr.opcode.mult_en + |-> + ##PIP_DLY + instr_o.opcode == $past(ecc_pm_ctrl.prog_instr.opcode,3) + ##1 instr_o.opcode ==$past(instr_o.opcode)[*(MULT_DLY+1)]; + endproperty + opcode_mul_a: assert property(disable iff(!rst_n) opcode_mul_p); + + + //-----------------------------------------// + // Helper logic for stall + //-----------------------------------------// + + logic fv_stall; + logic fv_stall_dly; + logic fv_stall_pulse; + logic [6:0] fv_dly_cntr; + + always_ff @(posedge clk, negedge rst_n) begin + if(!rst_n) begin + fv_stall <= 0; + fv_dly_cntr <= 0; + fv_stall_dly <= 0; + end + else begin + if(ecc_pm_ctrl.prog_instr.opcode.add_en || + ecc_pm_ctrl.prog_instr.opcode.mult_en) begin + fv_stall <= 1; + end + if(ecc_pm_ctrl.prog_instr.opcode.add_en)begin + fv_dly_cntr <= ADD_DLY+1; + end + if(ecc_pm_ctrl.prog_instr.opcode.mult_en) begin + fv_dly_cntr <= MULT_DLY+1; + end + if(fv_dly_cntr>0) begin + fv_dly_cntr <= fv_dly_cntr - 7'h1; + end + if(fv_dly_cntr == 0 && fv_stall==1) begin + fv_stall <= 0; + end + fv_stall_dly <= fv_stall; + end + end + assign fv_stall_pulse = fv_stall & ~fv_stall_dly; + +//When the add or mult are set then the next cycle output of pm_seq instruction is stored so it not lost during +//the exceution of add ormult and the next instr_o would be stored value + property opcode_no_compute_p; + logic[5:0] next_opcode; + fv_stall_pulse + ##0 (1'b1, next_opcode = ecc_pm_ctrl.prog_instr.opcode) + ##1 !fv_stall[->1] + |-> + ##2 + instr_o.opcode == next_opcode; + endproperty + + opcode_no_compute_a: assert property (disable iff(!rst_n)opcode_no_compute_p); + + + +//Helper function for choosing address +function logic[5:0] xor_choose(input logic digit, input logic[5:0] addr); + return({addr[5:3],digit^addr[2],addr[1:0]}); +endfunction + + +//Constraint on digit_i stability,proven on the top +stable_digit_during_ladder: assume property(disable iff(!rst_n) ((ecc_pm_ctrl.prog_cntr <= PD_E) && + (ecc_pm_ctrl.prog_cntr >= PA_S)) |-> $stable(digit_i)); + + +logic[5:0] fv_compute_addra; +logic[5:0] fv_compute_addrb; +//Helper logic for storing the computed address + always_comb begin:operands_addr + if((ecc_pm_ctrl.prog_cntr <= PD_E) && (ecc_pm_ctrl.prog_cntr >= PA_S) && ecc_pm_ctrl.prog_instr.opa_addr[5:3]==3'b001) + fv_compute_addra = xor_choose(digit_i,ecc_pm_ctrl.prog_instr.opa_addr); + else + fv_compute_addra = ecc_pm_ctrl.prog_instr.opa_addr; + + if((ecc_pm_ctrl.prog_cntr <= PD_E) && (ecc_pm_ctrl.prog_cntr >= PA_S) && ecc_pm_ctrl.prog_instr.opb_addr[5:3]==3'b001) + fv_compute_addrb = xor_choose(digit_i,ecc_pm_ctrl.prog_instr.opb_addr); + else + fv_compute_addrb = ecc_pm_ctrl.prog_instr.opb_addr; + end + + + +//when output of pm_sequencer instruction is add and the addresses are not R0 then +//it would be on primary output after 3 cycles and stays stable for the delay time +2 + property addr_when_add_sub_p; + logic[5:0] addra,addrb; + ecc_pm_ctrl.prog_instr.opcode.add_en + ##0 (1'b1, addra = (fv_compute_addra)) + ##0 (1'b1, addrb = (fv_compute_addrb)) + |-> + ##PIP_DLY + (instr_o.opa_addr == addra && + instr_o.opb_addr == addrb)[*(ADD_DLY+2)] + ; + endproperty + + addr_when_add_sub_a: assert property (disable iff(!rst_n)addr_when_add_sub_p); + + +//when output of pm_sequencer instruction is multiplication and the addresses it +//would be on primary output after 3 cycles and stays stable for the delay time +2 + property addr_when_mult_p; + logic[5:0] addra,addrb; + ecc_pm_ctrl.prog_instr.opcode.mult_en + ##0 (1'b1, addra = (fv_compute_addra)) + ##0 (1'b1, addrb = (fv_compute_addrb)) + |-> + ##PIP_DLY + (instr_o.opa_addr == addra && + instr_o.opb_addr == addrb)[*(MULT_DLY+2)] + ; + endproperty + + addr_when_mult_a: assert property (disable iff(!rst_n)addr_when_mult_p); + + + +//When the add or mult are set then the next cycle output of pm_seq instruction is +//stored so it not lost during the exceution of add ormult and the next instr_o would be stored value + property addr_when_no_cmd_p; + logic[5:0] addra,addrb; + + fv_stall_pulse + ##0 (1'b1, addra = (fv_compute_addra)) + ##0 (1'b1, addrb = (fv_compute_addrb)) + ##1 !fv_stall[->1] + |-> + ##2 + (instr_o.opa_addr == addra && + instr_o.opb_addr == addrb) + ; + endproperty + + addr_when_no_cmd_a: assert property (disable iff(!rst_n)addr_when_no_cmd_p); + + + + + property instr_o_when_cmds_2cycls_p; + ecc_pm_ctrl.prog_instr.opcode.add_en || + ecc_pm_ctrl.prog_instr.opcode.mult_en + |=> + (instr_o.opa_addr == $past(instr_o.opa_addr) && + instr_o.opb_addr == $past(instr_o.opb_addr)) && + instr_o.opcode == $past(instr_o.opcode); + endproperty + instr_o_when_cmds_2cycls_a: assert property(disable iff(!rst_n) instr_o_when_cmds_2cycls_p); + + + property instr_o_when_no_cmds_2cycls_p; + !fv_stall && + ecc_pm_ctrl.prog_instr.opcode!=UOP_NOP + |=> + (instr_o.opa_addr == $past(instr_o.opa_addr) && + instr_o.opb_addr == $past(instr_o.opb_addr)) && + instr_o.opcode == $past(instr_o.opcode); + endproperty + instr_o_when_no_cmds_2cycls_a: assert property(disable iff(!rst_n) instr_o_when_no_cmds_2cycls_p); + + + + property prog_cntr_stable_p; + fv_stall && + (fv_dly_cntr > 1) + |=> + ecc_pm_ctrl.prog_cntr == $past(ecc_pm_ctrl.prog_cntr); + endproperty + + prog_cntr_stable_a: assert property(disable iff(!rst_n) prog_cntr_stable_p); + + + + property prog_cntr_change_p; + (fv_stall & (fv_dly_cntr <= 1)) + |=> + ecc_pm_ctrl.prog_cntr != $past(ecc_pm_ctrl.prog_cntr); + endproperty + + prog_cntr_change_a: assert property(disable iff(!rst_n) prog_cntr_change_p); + + + property prog_cntr_change_1_p; + !fv_stall && + ecc_pm_ctrl.prog_cntr !=NOP + |=> + fv_stall || + ecc_pm_ctrl.prog_cntr != $past(ecc_pm_ctrl.prog_cntr); + endproperty + + prog_cntr_change_1_a: assert property(disable iff(!rst_n) prog_cntr_change_1_p); + + + property no_cmd_prog_nop_p; + ecc_pm_ctrl.prog_cntr == NOP && + ecc_cmd_i != KEYGEN_CMD && + ecc_cmd_i != SIGN_CMD && + ecc_cmd_i != VER_PART0_CMD && + ecc_cmd_i != VER_PART1_CMD && + ecc_cmd_i != VER_PART2_CMD && + ecc_cmd_i != CHK_PK_CMD + |=> + ecc_pm_ctrl.prog_cntr == NOP; + endproperty + + no_cmd_prog_nop_a: assert property(disable iff(!rst_n) no_cmd_prog_nop_p); + + + +endmodule + +bind ecc_pm_ctrl fv_ecc_pm_ctrl_abstract #( + .REG_SIZE(REG_SIZE), + .RND_SIZE(RND_SIZE), + .INSTR_SIZE(INSTRUCTION_LENGTH), + .MULT_DLY(ecc_pm_ctrl.MULT_DELAY), + .ADD_DLY(ecc_pm_ctrl.ADD_DELAY), + .Secp384_MONT_COUNT(ecc_pm_ctrl.Secp384_MONT_COUNT), + .Secp384_SCA_MONT_COUNT(ecc_pm_ctrl.Secp384_SCA_MONT_COUNT) + ) + fv_ecc_pm_ctrl_abstract_inst( + .clk(clk), + .rst_n(reset_n && !zeroize), + .ecc_cmd_i(ecc_cmd_i), + .sca_en_i(sca_en_i), + .digit_i(digit_i), + .instr_o(instr_o), + .req_digit_o(req_digit_o), + .busy_o(busy_o) + ); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_ecc_pm_sequencer.sv b/src/ecc/formal/properties/fv_ecc_pm_sequencer.sv new file mode 100644 index 000000000..475393718 --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_pm_sequencer.sv @@ -0,0 +1,3065 @@ + +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_pm_sequencer + import ecc_pm_uop_pkg::*; + #( + parameter ADDR_WIDTH = 10, + parameter DATA_WIDTH = 32 + ) + ( + input wire clk, + input wire rst_n, + input wire ena, + input wire [ADDR_WIDTH-1 : 0] addra, + input logic [DATA_WIDTH-1 : 0] douta + ); + +logic [ADDR_WIDTH-1 : 0] fv_cntr_pminitg; +logic [ADDR_WIDTH-1 : 0] fv_cntr_pminit; +logic [ADDR_WIDTH-1 : 0] fv_cntr_pa; +logic [ADDR_WIDTH-1 : 0] fv_cntr_pd; +logic [ADDR_WIDTH-1 : 0] fv_cntr_inv; +logic [ADDR_WIDTH-1 : 0] fv_cntr_conv; +logic [ADDR_WIDTH-1 : 0] fv_cntr_sign0; +logic [ADDR_WIDTH-1 : 0] fv_cntr_invq; +logic [ADDR_WIDTH-1 : 0] fv_cntr_sign1; +logic [ADDR_WIDTH-1 : 0] fv_cntr_chkpk; +logic [ADDR_WIDTH-1 : 0] fv_cntr_ver0p0; +logic [ADDR_WIDTH-1 : 0] fv_cntr_ver0p1; +logic [ADDR_WIDTH-1 : 0] fv_cntr_ver1st; +logic [ADDR_WIDTH-1 : 0] fv_cntr_pminitpk; +logic [ADDR_WIDTH-1 : 0] fv_cntr_ver2pa; + +logic fv_set_pminitg; +logic fv_set_pminit; +logic fv_set_pa; +logic fv_set_pd; +logic fv_set_inv; +logic fv_set_conv; +logic fv_set_sign0; +logic fv_set_invq; +logic fv_set_sign1; +logic fv_set_chkpk; +logic fv_set_ver0p0; +logic fv_set_ver0p1; +logic fv_set_ver1st; +logic fv_set_pminitpk; +logic fv_set_ver2pa; + +always_ff @(posedge clk or negedge rst_n) begin + if(!rst_n) begin + fv_set_pminitg <= '0; + fv_set_pminit <= '0; + fv_set_pa <= '0; + fv_set_pd <= '0; + fv_set_inv <= '0; + fv_set_conv <= '0; + fv_set_sign0 <= '0; + fv_set_invq <= '0; + fv_set_sign1 <= '0; + fv_set_chkpk <= '0; + fv_set_ver0p0 <= '0; + fv_set_ver0p1 <= '0; + fv_set_ver1st <= '0; + fv_set_pminitpk <= '0; + fv_set_ver2pa <= '0; + fv_cntr_pminitg <= '0; + fv_cntr_pminit <= '0; + fv_cntr_pa <= '0; + fv_cntr_pd <= '0; + fv_cntr_inv <= '0; + fv_cntr_conv <= '0; + fv_cntr_sign0 <= '0; + fv_cntr_invq <= '0; + fv_cntr_sign1 <= '0; + fv_cntr_chkpk <= '0; + fv_cntr_ver0p0 <= '0; + fv_cntr_ver0p1 <= '0; + fv_cntr_ver1st <= '0; + fv_cntr_pminitpk <= '0; + fv_cntr_ver2pa <= '0; + end + else begin + if(addra == PM_INIT_G_S) begin + fv_set_pminitg <= 1; + fv_set_ver2pa <=0; + fv_cntr_pminitg <= addra+1; + end + else if(fv_set_pminitg) begin + fv_cntr_pminitg <= fv_cntr_pminitg+1; + end + if(addra == PM_INIT_S) begin + fv_set_pminitg <= 0; + fv_set_pminit <=1; + fv_cntr_pminit <= addra+1; + end + else if(fv_set_pminit) begin + fv_cntr_pminit <= fv_cntr_pminit+1; + end + if(addra == PA_S) begin + fv_set_pminit <= 0; + fv_set_pa <=1; + fv_cntr_pa <= addra+1; + end + else if(fv_set_pa) begin + fv_cntr_pa <= fv_cntr_pa+1; + end + if(addra == PD_S) begin + fv_set_pa <= 0; + fv_set_pd <=1; + fv_cntr_pd <= addra+1; + end + else if(fv_set_pd) begin + fv_cntr_pd <= fv_cntr_pd+1; + end + if(addra == INV_S) begin + fv_set_pd <= 0; + fv_set_inv <=1; + fv_cntr_inv <= addra+1; + end + else if(fv_set_inv) begin + fv_cntr_inv <= fv_cntr_inv+1; + end + if(addra == CONV_S) begin + fv_set_inv <= 0; + fv_set_conv <=1; + fv_cntr_conv <= addra+1; + end + else if(fv_set_conv) begin + fv_cntr_conv <= fv_cntr_conv+1; + end + if(addra == SIGN0_S) begin + fv_set_conv <= 0; + fv_set_sign0 <=1; + fv_cntr_sign0 <= addra+1; + end + else if(fv_set_sign0) begin + fv_cntr_sign0 <= fv_cntr_sign0+1; + end + if(addra == INVq_S) begin + fv_set_sign0 <= 0; + fv_set_invq <=1; + fv_cntr_invq <= addra+1; + end + else if(fv_set_invq) begin + fv_cntr_invq <= fv_cntr_invq+1; + end + if(addra == SIGN1_S) begin + fv_set_invq <= 0; + fv_set_sign1 <=1; + fv_cntr_sign1 <= addra+1; + end + else if(fv_set_sign1) begin + fv_cntr_sign1 <= fv_cntr_sign1+1; + end + if(addra == CHK_PK_S) begin + fv_set_sign1 <= 0; + fv_set_chkpk <=1; + fv_cntr_chkpk <= addra+1; + end + else if(fv_set_chkpk) begin + fv_cntr_chkpk <= fv_cntr_chkpk+1; + end + if(addra == VER0_P0_S) begin + fv_set_chkpk <= 0; + fv_set_ver0p0 <=1; + fv_cntr_ver0p0 <= addra+1; + end + else if(fv_set_ver0p0) begin + fv_cntr_ver0p0 <= fv_cntr_ver0p0+1; + end + if(addra == VER0_P1_S) begin + fv_set_ver0p0 <= 0; + fv_set_ver0p1 <=1; + fv_cntr_ver0p1 <= addra+1; + end + else if(fv_set_ver0p1) begin + fv_cntr_ver0p1 <= fv_cntr_ver0p1+1; + end + if(addra == VER1_ST_S) begin + fv_set_ver0p1 <= 0; + fv_set_ver1st <=1; + fv_cntr_ver1st <= addra+1; + end + else if(fv_set_ver1st) begin + fv_cntr_ver1st <= fv_cntr_ver1st+1; + end + if(addra == PM_INIT_PK_S) begin + fv_set_pminitpk <= 1; + fv_set_ver1st <=0; + fv_cntr_pminitpk <= addra+1; + end + else if(fv_set_pminitpk) begin + fv_cntr_pminitpk <= fv_cntr_pminitpk+1; + end + if(addra == VER2_PA_S) begin + fv_set_ver2pa <= 1; + fv_set_pminitpk <=0; + fv_cntr_ver2pa <= addra+1; + end + else if(fv_set_ver2pa) begin + fv_cntr_ver2pa <= fv_cntr_ver2pa+1; + end + end +end + +property assign_addra(set,cntr); + set + |-> + addra == cntr; +endproperty + +cntr_assume_pminitg :assume property(assign_addra(fv_set_pminitg ,fv_cntr_pminitg )); +cntr_assume_pminit :assume property(assign_addra(fv_set_pminit ,fv_cntr_pminit )); +cntr_assume_pa :assume property(assign_addra(fv_set_pa ,fv_cntr_pa )); +cntr_assume_pd :assume property(assign_addra(fv_set_pd ,fv_cntr_pd )); +cntr_assume_inv :assume property(assign_addra(fv_set_inv ,fv_cntr_inv )); +cntr_assume_conv :assume property(assign_addra(fv_set_conv ,fv_cntr_conv )); +cntr_assume_sign0 :assume property(assign_addra(fv_set_sign0 ,fv_cntr_sign0 )); +cntr_assume_invq :assume property(assign_addra(fv_set_invq ,fv_cntr_invq )); +cntr_assume_sign1 :assume property(assign_addra(fv_set_sign1 ,fv_cntr_sign1 )); +cntr_assume_chkpk :assume property(assign_addra(fv_set_chkpk ,fv_cntr_chkpk )); +cntr_assume_ver0p0 :assume property(assign_addra(fv_set_ver0p0 ,fv_cntr_ver0p0 )); +cntr_assume_ver0p1 :assume property(assign_addra(fv_set_ver0p1 ,fv_cntr_ver0p1 )); +cntr_assume_ver1st :assume property(assign_addra(fv_set_ver1st ,fv_cntr_ver1st )); +cntr_assume_pminitpk:assume property(assign_addra(fv_set_pminitpk,fv_cntr_pminitpk)); +cntr_assume_ver2pa :assume property(assign_addra(fv_set_ver2pa ,fv_cntr_ver2pa )); + +always_enable: assume property(disable iff(!rst_n) ena == 1'b1); + +default clocking default_clk @(posedge clk); endclocking + + + sequence reset_sequence; + !rst_n ##1 rst_n; + endsequence + + +//////////////////////////////////////////// +// reset property, when reset out a and b // +// are zero // +//////////////////////////////////////////// + + property reset_p; + $past(!rst_n) + |-> + + douta == '0; + endproperty + + reset_a : assert property(reset_p); + + +//////////////////////////////////////////// +// Illegal address should result in zero // +//////////////////////////////////////////// + + property illicit_addra_p; + ((addra >1) && (addra < PM_INIT_G_S))|| + ((addra >PM_INIT_G_E) && (addra < PM_INIT_S))|| + ((addra >PM_INIT_E) && (addra < PA_S))|| + ((addra >PA_E) && (addra < PD_S))|| + ((addra >PD_E) && (addra < INV_S))|| + ((addra >INV_E) && (addra < CONV_S))|| + ((addra >CONV_E) && (addra < SIGN0_S))|| + ((addra >SIGN0_E) && (addra < INVq_S))|| + ((addra >INVq_E) && (addra < SIGN1_S))|| + ((addra >SIGN1_E) && (addra < CHK_PK_S))|| + ((addra >CHK_PK_E) && (addra < VER0_P0_S))|| + ((addra >VER0_P0_E) && (addra < VER0_P1_S))|| + ((addra >VER0_P1_E) && (addra < VER1_ST_S))|| + ((addra >VER1_ST_E) && (addra < PM_INIT_PK_S))|| + ((addra >PM_INIT_PK_E) && (addra < VER2_PA_S))|| + (addra > VER2_PA_E) + |=> + douta =='0; + endproperty + + + illicit_addra_a : assert property(disable iff(!rst_n) illicit_addra_p); + + + +//////////////////////////////////////////// +// Initial two steps dout is zero // +// // +//////////////////////////////////////////// + property initial_p; + addra == NOP || + addra == 1 + |=> + + douta == '0; + endproperty + + initial_a : assert property(disable iff(!rst_n) initial_p); + +//////////////////////////////////////////// +// Base point randamization and storing // +// in R1 // +//////////////////////////////////////////// + + + property pm_init_G_p; + addra == PM_INIT_G_S + + |-> + + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_LAMBDA, UOP_OPR_CONST_R2_p} // R1_Z = mm(Lambda, R2) λ conversion to montgomery domain + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_Z} // storing λ in the projective coordinate R1_Z + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_GX_MONT, UOP_OPR_R1_Z} // R1_X = mm(GX_MONT, R0_Z) 𝑋=𝐺𝑥×λ + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_X} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_GY_MONT, UOP_OPR_R1_Z} // R1_Y = mm(GY_MONT, R0_Z) 𝑌=𝐺𝑦×λ + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_Y}; + endproperty + + pm_init_G_a: assert property (disable iff(!rst_n) pm_init_G_p); + + +//////////////////////////////////////////// +// Initialize R0 with Zero // +// // +//////////////////////////////////////////// + + + property pm_init_S_p; + addra == PM_INIT_S + + |-> + + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_CONST_ZERO, UOP_OPR_CONST_ZERO} // R0_X = 0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_CONST_ONE_MONT, UOP_OPR_CONST_ZERO} // initialised with one_mont R0_y = 384'h100000000ffffffffffffffff0000000100000000 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Y, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_CONST_ZERO, UOP_OPR_CONST_ZERO} // R0_Z = 0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE}; + endproperty + + + pm_init_S_a: assert property (disable iff(!rst_n) pm_init_S_p); + + + + + +///////////////////////////////////////////// +// t0 =A,t1 =B,t2 =C,t3 =D,t4 =E,t5 =F // +// X1 = R0_x ,X2 = R1_x, after step 15 X3 = R1_x +// Y1 = R0_y ,Y2 = R1_y, after step Y3 = R1_x +// Z1 = R0_z ,Z2 = R1_z, after step 19 Z3 = R1_z +// +//////////////////////////////////////////// + property point_add_p; + addra == PA_S + + |=> + + douta == {UOP_DO_MUL_p, UOP_OPR_R0_X, UOP_OPR_R1_X} // t0 <- X1.X2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_Y, UOP_OPR_R1_Y} // t1 <- Y1.Y2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_B} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_Z, UOP_OPR_R1_Z} // t2 <- Z1.Z2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Y} // t3 <- X1+Y1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_D, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R1_X, UOP_OPR_R1_Y} // t4 <- X2+Y2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_E} // t3 <- t3.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_D} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_B} //t4 <- t0+t1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_D, UOP_OPR_E} // t3 <- t3 - t4 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_D, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Z} // t4 <- X1+Z1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R1_X, UOP_OPR_R1_Z} // t5 <- X2 + Z2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_E, UOP_OPR_F} //t4 <- t4.t5 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_E} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_C} // t5 <- t0+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_E, UOP_OPR_F} // t4 <- t4 - t5 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Y, UOP_OPR_R0_Z} // t5 <- Y1+Z1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R1_Y, UOP_OPR_R1_Z} // X3 <- Y2 +Z2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_R1_X} // t5 <- t5.X3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_F} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_C} // X3 <- t1 +t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_F, UOP_OPR_R1_X} // t5 <- t5-X3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_E} // Z3 <- a.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_Z} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_3b, UOP_OPR_C} // X3 <-3b.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_X} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R1_X, UOP_OPR_R1_Z} // Z3 <- X3 + Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_B, UOP_OPR_R1_Z} // X3 <- t1-Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_R1_Z} // Z3 <- t1+Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R1_X, UOP_OPR_R1_Z} // Y3 <- X3.Z3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_Y} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_A} // t1 <- t0+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_A} // t1 <- t1+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_C} // t2 <- a.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_3b, UOP_OPR_E} // t4 <- 3b.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_E} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_C} // t1<-t1+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_A, UOP_OPR_C} // t2<-t0-t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_C, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_C} // t2<- a.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_E, UOP_OPR_C} // t4<-t4+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_B, UOP_OPR_E} // t0 <- t1.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R1_Y, UOP_OPR_A} // Y3 <- Y3+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_Y, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_E} // t0<-t5.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_R1_X} // X3 <- t3.X3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_X} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_R1_X, UOP_OPR_A} // X3 <- X3-t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_B} // t0 <- t3.t1 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_R1_Z} //Z3 <- t5.Z3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_Z} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R1_Z, UOP_OPR_A} // Z3 <- Z3 + t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_Z, UOP_OPR_DONTCARE} + ##1 addra == PD_S; +endproperty + +point_add_a: assert property(disable iff(!rst_n) point_add_p); + + + + + property point_dbl_p; + + addra == PD_S + + |=> + + douta == {UOP_DO_MUL_p, UOP_OPR_R0_X, UOP_OPR_R0_X} // t0 <- X1.X2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_Y, UOP_OPR_R0_Y} // t1 <- Y1.Y2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_B} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_Z, UOP_OPR_R0_Z} // t2 <- Z1.Z2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Y} // t3 <- X1+Y1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_D, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Y} // t4 <- X2+Y2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_E} // t3 <- t3.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_D} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_B} //t4 <- t0+t1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_D, UOP_OPR_E} // t3 <- t3 - t4 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_D, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Z} // t4 <- X1+Z1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Z} // t5 <- X2 + Z2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_E, UOP_OPR_F} //t4 <- t4.t5 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_E} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_C} // t5 <- t0+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_E, UOP_OPR_F} // t4 <- t4 - t5 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Y, UOP_OPR_R0_Z} // t5 <- Y1+Z1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Y, UOP_OPR_R0_Z} // X3 <- Y2 +Z2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_R0_X} // t5 <- t5.X3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_F} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_C} // X3 <- t1 +t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_F, UOP_OPR_R0_X} // t5 <- t5-X3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_E} // Z3 <- a.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_Z} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_3b, UOP_OPR_C} // X3 <-3b.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_X} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Z} // Z3 <- X3 + Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_B, UOP_OPR_R0_Z} // X3 <- t1-Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_R0_Z} // Z3 <- t1+Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_X, UOP_OPR_R0_Z} // Y3 <- X3.Z3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_Y} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_A} // t1 <- t0+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_A} // t1 <- t1+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_C} // t2 <- a.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_3b, UOP_OPR_E} // t4 <- 3b.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_E} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_C} // t1<-t1+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_A, UOP_OPR_C} // t2<-t0-t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_C, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_C} // t2<- a.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_E, UOP_OPR_C} // t4<-t4+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_B, UOP_OPR_E} // t0 <- t1.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Y, UOP_OPR_A} // Y3 <- Y3+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Y, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_E} // t0<-t5.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_R0_X} // X3 <- t3.X3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_X} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_R0_X, UOP_OPR_A} // X3 <- X3-t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_B} // t0 <- t3.t1 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_R0_Z} //Z3 <- t5.Z3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_Z} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Z, UOP_OPR_A} // Z3 <- Z3 + t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE}; +endproperty + +point_dbl_a: assert property(disable iff(!rst_n) point_dbl_p); + + + + + + +property conv_p; + addra == CONV_S + + |-> + + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_OUT, UOP_OPR_R0_Y} // y_MONT = fp_mult(Z_inv, Y_MONT, p) . Y = Y/Z (Ref: sec 2 Montgomery curves and their arithmetic The case of large characteristic fields Craig Costello · Benjamin Smith) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_Qy_MONT} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_OUT, UOP_OPR_R0_X} // x_MONT = fp_mult(Z_inv, X_MONT, p) X = X/Z + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_Qx_MONT} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_ONE, UOP_OPR_Qy_MONT} // y_affine = fp_mult(y_MONT, 1, p) conversion from mont domain to normal + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_Qy_AFFN} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_ONE, UOP_OPR_Qx_MONT} // y_affine = fp_mult(y_MONT, 1, p) conversion from mont domain to normal + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_Qx_AFFN} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE}; +endproperty + +conv_a: assert property(disable iff(!rst_n) conv_p); + +//////////////////////////////////////////////////////////////// +// s = [k^-1((h-d) + r (privKey-d))] + [k^-1(d + r.d)] mod n // +// // +//////////////////////////////////////////////////////////////// + + +property sign0_p; + addra == SIGN0_S + + |-> + + ##1 douta == {UOP_DO_ADD_q, UOP_OPR_CONST_ZERO, UOP_OPR_Qx_AFFN} // R = Qx_AFFN + ##1 douta == {UOP_ST_ADD_q, UOP_OPR_SIGN_R, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_SIGN_R, UOP_OPR_CONST_R2_q} // E = mm(R, R2) % q r conversion to montgomery domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_E} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_SCALAR_G, UOP_OPR_CONST_R2_q} // k_MONT = mm(k, R2) % q k conversion to montgomery domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_IN} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_PRIVKEY, UOP_OPR_CONST_R2_q} // A = mm(privKey, R2) % q privkey conversion to montgomery domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_HASH_MSG, UOP_OPR_CONST_R2_q} // B = mm(h, R2) % q hash msg conversion to montgomery domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_B} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_MASKING, UOP_OPR_CONST_R2_q} // D = mm(masking_d, R2) % q d conversion to montgomery domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_D} + ##1 douta == {UOP_DO_SUB_q, UOP_OPR_A, UOP_OPR_D} // A = (A - D) % q (privkey-d) + ##1 douta == {UOP_ST_ADD_q, UOP_OPR_A, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_q, UOP_OPR_B, UOP_OPR_D} // B = (B - D) % q (h-d) + ##1 douta == {UOP_ST_ADD_q, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A, UOP_OPR_E} // C = mm(A, E) % q r(privkey-d) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_D, UOP_OPR_E} // F = mm(D, E) % q r.d + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_F} + ##1 douta == {UOP_DO_ADD_q, UOP_OPR_D, UOP_OPR_C} // C = (C + D) % q (d + r (privKey-d)) + ##1 douta == {UOP_ST_ADD_q, UOP_OPR_C, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_q, UOP_OPR_B, UOP_OPR_F} // D = (B + F) % q ((h-d) + r.d) + ##1 douta == {UOP_ST_ADD_q, UOP_OPR_D, UOP_OPR_DONTCARE}; +endproperty + + + +sign0_a: assert property(disable iff(!rst_n) sign0_p); + + +property sign1_p; + addra == SIGN1_S + + |-> + + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_OUT, UOP_OPR_C} // C = fp_mult(C, k_inv, q) C = k^-1.((h-d) + r (privKey-d)) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_OUT, UOP_OPR_D} // D = fp_mult(D, k_inv, q) D = k^-1.(d + r.d) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_D} + ##1 douta == {UOP_DO_ADD_q, UOP_OPR_C, UOP_OPR_D} // B = C + D % q B = (C+D) mod n + ##1 douta == {UOP_ST_ADD_q, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_CONST_ONE, UOP_OPR_B} // B = fp_mult(B, 1, q) conversion from montgomery to normal domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_SIGN_S} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE}; +endproperty + +sign1_a: assert property(disable iff(!rst_n) sign1_p); + + +// Inputs pubKey,h(hash msg),r(respective r part in signature),s(respective s part in signature) +// s1 = s^-1 mod q +// R' = (h* s1)*G + (r*s1)*pubKey +// r' = R'x mod q +// +// Verify part0 to convert inputs to the mont domain + + + + +property verify0_p0_p; + addra == VER0_P0_S + + |-> + + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_HASH_MSG, UOP_OPR_CONST_R2_q} // A = mm(h, R2) % q conversion of hash msg to mont domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_SIGN_R, UOP_OPR_CONST_R2_q} // B = mm(R, R2) % q conversion of r to mont domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_B} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_SIGN_S, UOP_OPR_CONST_R2_q} // INV_IN = mm(S, R2) % q conversion of s to mont domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_IN} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE}; +endproperty + +verify0_p0_a: assert property(disable iff(!rst_n)verify0_p0_p); + + + +// verify part1 use the generated s^-1 for the intermediate computations and convert them +// into normal domain so in next step they could be used in the point multiplication. + + +property verify0_p1_p; + addra == VER0_P1_S + + |-> + + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_OUT, UOP_OPR_A} // A = mm(h, S_INV) % q h*s^-1 mod q + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_CONST_ONE, UOP_OPR_A} // hs1 = mm(A, 1) % q conversion from mont domain to normal domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_SCALAR_G} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_OUT, UOP_OPR_B} // B = mm(r, S_INV) % q r*s^-1 mod q + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_B} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_CONST_ONE, UOP_OPR_B} // rs1 = mm(B, 1) % q conversion from mont domain to normal domain + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_SCALAR_PK} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE}; +endproperty + +verify0_p1_a: assert property(disable iff(!rst_n)verify0_p1_p); + + +//verify1 (h*s^-1)*G + +property verify1_st_p; + addra == VER1_ST_S + + |-> + + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_CONST_ZERO} // computed results stored in R0, in the previous seq + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_P1_X_MONT, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Y, UOP_OPR_CONST_ZERO} + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_P1_Y_MONT, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Z, UOP_OPR_CONST_ZERO} + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_P1_Z_MONT, UOP_OPR_DONTCARE}; + +endproperty + +verify1_st_a: assert property(disable iff(!rst_n)verify1_st_p); + + +// verify2 Initialise with PubKey(PK) for (r*s^-1)*PK computation +// It is stored R1, but R1_z is initialised with one_mont + + + +property verify2_init_pk_p; + + addra == PM_INIT_PK_S + + |-> + + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_Qx_AFFN, UOP_OPR_CONST_R2_p} //Through DSA seq pubkey is stored to QX and QY prior to start of this seq + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_X} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_Qy_AFFN, UOP_OPR_CONST_R2_p} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R1_Y} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_CONST_ONE_MONT, UOP_OPR_CONST_ZERO} // + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R1_Z, UOP_OPR_DONTCARE}; +endproperty + +verify2_init_pk_a: assert property (disable iff(!rst_n) verify2_init_pk_p); + + + + //VER2 point addtion of PA((h*s_inv)*G, (r*s_inv)*PK) + // t0 =A,t1 =B,t2 =C,t3 =D,t4 =E,t5 =F // + // X1 = R0_x ,X2 = P1_x, after step 15 X3 = R0_x + // Y1 = R0_y ,Y2 = P1_y, after step Y3 = R0_x + // Z1 = R0_z ,Z2 = P1_z, after step 19 Z3 = R0_z + + property verify2_pointadd_p; + + addra == VER2_PA_S + |-> + + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_X, UOP_OPR_P1_X_MONT} // A = fp_mult(P0.X, P1.X, p) t0 <- X1.X2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_Y, UOP_OPR_P1_Y_MONT} // B = fp_mult(P0.Y, P1.Y, p) t1 <- Y1.Y2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_B} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_Z, UOP_OPR_P1_Z_MONT} // C = fp_mult(P0.Z, P1.Z, p) t2 <- Z1.Z2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Y} // D = (P0.X + P0.Y) % p t3 <- X1+Y1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_D, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_P1_X_MONT, UOP_OPR_P1_Y_MONT} // E = (P1.X + P1.Y) % p t4 <- X2+Y2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_E} // D = fp_mult(D, E, p) t3 <- t3.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_D} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_B} // E = (A + B) % p t4 <- t0+t1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_D, UOP_OPR_E} // D = (D - E) % p t3 <- t3 - t4 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_D, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Z} // E = (P0.X + P0.Z) % p t4 <- X1+Z1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_P1_X_MONT, UOP_OPR_P1_Z_MONT} // F = (P1.X + P1.Z) % p t5 <- X2 + Z2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_E, UOP_OPR_F} // E = fp_mult(E, F, p) t4 <- t4.t5 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_E} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_C} // F = (A + C) % p t5 <- t0+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_E, UOP_OPR_F} // E = (E - F) % p t4 <- t4 - t5 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Y, UOP_OPR_R0_Z} // F = (P0.Y + P0.Z) % p t5 <- Y1+Z1 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_P1_Y_MONT, UOP_OPR_P1_Z_MONT} // X3 = (P1.Y + P1.Z) % p X3 <- Y2 +Z2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_R0_X} // F = fp_mult(F, X3, p) t5 <- t5.X3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_F} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_C} // X3 = (B + C) % p X3 <- t1 +t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_F, UOP_OPR_R0_X} // F = (F - X3) % p t5 <- t5-X3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_F, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_E} // Z3 = fp_mult(ECC.a, E, p) Z3 <- a.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_Z} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_3b, UOP_OPR_C} // X3 = fp_mult(ECC.3b, C, p) X3 <-3b.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_X} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_X, UOP_OPR_R0_Z} // Z3 = (X3 + Z3) % p Z3 <- X3 + Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_B, UOP_OPR_R0_Z} // X3 = (B - Z3) % p X3 <- t1-Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_R0_Z} // Z3 = (B + Z3) % p Z3 <- t1+Z3 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_R0_X, UOP_OPR_R0_Z} // Y3 = fp_mult(X3, Z3, p) Y3 <- X3.Z3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_Y} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_A, UOP_OPR_A} // B = (A + A) % p t1 <- t0+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_A} // B = (B + A) % p t1 <- t1+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_C} // C = fp_mult(ECC.a, C, p) t2 <- a.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_3b, UOP_OPR_E} // E = fp_mult(ECC.3b, E, p) t4 <- 3b.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_E} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_B, UOP_OPR_C} // B = (B + C) % p t1<-t1+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_B, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_A, UOP_OPR_C} // C = (A - C) % p t2<-t0-t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_C, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_C} // C = fp_mult(ECC.a, C, p) t2<- a.t2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_E, UOP_OPR_C} // E = (E + C) % p t4<-t4+t2 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_E, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_B, UOP_OPR_E} // A = fp_mult(B, E, p) t0 <- t1.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Y, UOP_OPR_A} // Y3 = (Y3 + A) % p Y3 <- Y3+t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Y, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_E} // A = fp_mult(F, E, p) t0<-t5.t4 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_R0_X} // X3 = fp_mult(D, X3, p) X3 <- t3.X3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_X} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_R0_X, UOP_OPR_A} // X3 = (X3 - A) % p X3 <- X3-t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_X, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_D, UOP_OPR_B} // A = fp_mult(D, B, p) t0 <- t3.t1 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_F, UOP_OPR_R0_Z} // Z3 = fp_mult(F, Z3, p) Z3 <- t5.Z3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_R0_Z} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Z, UOP_OPR_A} // Z3 = (Z3 + A) % p Z3 <- Z3 + t0 + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_R0_Z, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_R0_Z, UOP_OPR_CONST_ZERO} // Zinv_IN = P1_Z + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_INV_IN, UOP_OPR_DONTCARE}; +endproperty + +verify2_pointadd_a: assert property (disable iff(!rst_n) verify2_pointadd_p); + + + + + +property inv_modp_p; + addra == INV_S + + |-> + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_CONST_ZERO, UOP_OPR_CONST_ONE_MONT} // precompute[0] = UOP_OPR_CONST_ONE_MONT % p + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_INV_PRE0, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_IN, UOP_OPR_INV_PRE0} // precompute[1] = fp_mult(Z, precompute[0], p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_IN, UOP_OPR_INV_PRE1} // precompute[2] = fp_mult(Z, precompute[1], p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_IN, UOP_OPR_INV_PRE2} // precompute[3] = fp_mult(Z, precompute[2], p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_IN, UOP_OPR_INV_PRE3} // precompute[4] = fp_mult(Z, precompute[3], p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE4} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_IN, UOP_OPR_INV_PRE4} // precompute[5] = fp_mult(Z, precompute[4], p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_IN, UOP_OPR_INV_PRE5} // precompute[6] = fp_mult(Z, precompute[5], p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_IN, UOP_OPR_INV_PRE6} // precompute[7] = fp_mult(Z, precompute[6], p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_INV_PRE0, UOP_OPR_INV_PRE0} // a_inv = fp_mult(precompute[0], precompute[0], p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} // a_inv = fp_mult(a_inv, a_inv, p) //why these two additional steps ? + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} // a_inv = fp_mult(a_inv, a_inv, p) + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_INV_OUT}; +endproperty + + +inv_modp_a: assert property (disable iff(!rst_n) inv_modp_p); + + + + +property inv_modq_p; + addra == INVq_S + + |-> + + ##1 douta == {UOP_DO_ADD_q, UOP_OPR_CONST_ZERO, UOP_OPR_CONST_ONE_q_MONT} // precompute[0] = UOP_OPR_CONST_ONE_q_MONT % q + ##1 douta == {UOP_ST_ADD_q, UOP_OPR_INV_PRE0, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_IN, UOP_OPR_INV_PRE0} // precompute[1] = fp_mult(Z, precompute[0], q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_IN, UOP_OPR_INV_PRE1} // precompute[2] = fp_mult(Z, precompute[1], q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_IN, UOP_OPR_INV_PRE2} // precompute[3] = fp_mult(Z, precompute[2], q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_IN, UOP_OPR_INV_PRE3} // precompute[4] = fp_mult(Z, precompute[3], q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE4} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_IN, UOP_OPR_INV_PRE4} // precompute[5] = fp_mult(Z, precompute[4], q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_IN, UOP_OPR_INV_PRE5} // precompute[6] = fp_mult(Z, precompute[5], q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_IN, UOP_OPR_INV_PRE6} // precompute[7] = fp_mult(Z, precompute[6], q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_INV_PRE0, UOP_OPR_INV_PRE0} // a_inv = fp_mult(precompute[0], precompute[0], q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} // a_inv = fp_mult(a_inv, a_inv, q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} // a_inv = fp_mult(a_inv, a_inv, q) + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE4} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE4} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE4} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE7} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE4} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE0} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE3} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE4} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE2} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE4} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE5} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE6} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_A_INV} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_A_INV} + ##1 douta == {UOP_DO_MUL_q, UOP_OPR_A_INV, UOP_OPR_INV_PRE1} + ##1 douta == {UOP_ST_MUL_q, UOP_OPR_DONTCARE, UOP_OPR_INV_OUT}; +endproperty + +inv_modq_a: assert property(disable iff(!rst_n) inv_modq_p); + + + +//seq to check the provided pubKey is on the curve or not. +property chk_pk_p; + addra == CHK_PK_S + + |-> + + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_Qy_AFFN, UOP_OPR_CONST_R2_p} // A = mm(Qy, R2) % p conversion of pubkey y to mont domain + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_A, UOP_OPR_A} // A = A*A % p y^2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_A} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_Qx_AFFN, UOP_OPR_CONST_R2_p} // B = mm(Qx, R2) % p conversion of pubkey x to mont domain + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_B} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_B, UOP_OPR_B} // C = B*B % p x^2 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_C, UOP_OPR_B} // C = C*B % p x^3 + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_C} + ##1 douta == {UOP_DO_MUL_p, UOP_OPR_CONST_E_a, UOP_OPR_B} // D = ECC.a*B % p a.x + ##1 douta == {UOP_ST_MUL_p, UOP_OPR_DONTCARE, UOP_OPR_D} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_C, UOP_OPR_D} // C = C + D % p x^3 + a.x + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_C, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_ADD_p, UOP_OPR_C, UOP_OPR_CONST_E_b} // C = C + ECC.b % p x^3 + a.x + b + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_C, UOP_OPR_DONTCARE} + ##1 douta == {UOP_DO_SUB_p, UOP_OPR_A, UOP_OPR_C} // PK_valid = A - C % p y^2 - (x^3 + a.x + b) should be equal to zero if the key is on the curve + ##1 douta == {UOP_ST_ADD_p, UOP_OPR_PK_VALID, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE} + ##1 douta == {UOP_NOP, UOP_OPR_DONTCARE, UOP_OPR_DONTCARE}; +endproperty + +chk_pk_a: assert property(disable iff(!rst_n) chk_pk_p); + + + +// When storing both the address should not be the same +property store_not_same_addr_p; + douta[17] || + douta[16] + |-> + douta[11:6]!= douta[5:0]; +endproperty + +store_not_same_addr_a: assert property(disable iff(!rst_n) store_not_same_addr_p); + +// If it starts with UOP_NOP, the next both fields should be UOP_OPR_DONTCARE +property when_nop_both_addr_0_p; + douta[17:12] == UOP_NOP + |-> + douta[11:0]== {UOP_OPR_DONTCARE,UOP_OPR_DONTCARE}; +endproperty + +when_nop_both_addr_0_a: assert property(disable iff(!rst_n) when_nop_both_addr_0_p); + +//If it starts with UOP_ST_ADD_p/UOP_ST_ADD_q, the last field should be UOP_OPR_DONTCARE. + +property when_add_addrb_0_p; + (douta[17:12] == UOP_ST_ADD_p) || + (douta[17:12] == UOP_ST_ADD_q) + |-> + douta[5:0]== UOP_OPR_DONTCARE; +endproperty + +when_add_addrb_0_a: assert property(disable iff(!rst_n) when_add_addrb_0_p); + + +//o If it starts with UOP_ST_MUL_p/UOP_ST_MUL_q the middle field should be UOP_OPR_DONTCARE + +property when_mult_addra_0_p; + (douta[17:12] == UOP_ST_MUL_p) || + (douta[17:12] == UOP_ST_MUL_q) + |-> + douta[11:6]== UOP_OPR_DONTCARE; +endproperty + +when_mult_addra_0_a: assert property(disable iff(!rst_n) when_mult_addra_0_p); + +//If it starts with UOP_DO_MUL_p/UOP_DO_MUL_q/ UOP_DO_ADD_p/ UOP_DO_ADD_q/ UOP_DO_SUB_p/UOP_DO_SUB_q, +//the next both fields shouldn’t be UOP_OPR_DONTCARE. + + +property when_do_add_mul_sub_addr_not_zero_p; + ((douta[17:12] == UOP_DO_MUL_p) || + (douta[17:12] == UOP_DO_MUL_q) || + (douta[17:12] == UOP_DO_ADD_q) || + (douta[17:12] == UOP_DO_ADD_p) || + (douta[17:12] == UOP_DO_SUB_p) || + (douta[17:12] == UOP_DO_SUB_q)) && + $past(addra) != PM_INIT_S && + $past(addra) != PM_INIT_S+ 4 //Next field after opcode is const_zero i.e both the fields are zero so excluded + |-> + douta[11:0] != {UOP_OPR_DONTCARE,UOP_OPR_DONTCARE}; +endproperty + +when_do_add_mul_sub_addr_not_zero_a: assert property(disable iff(!rst_n) when_do_add_mul_sub_addr_not_zero_p); + + +endmodule + + + +bind ecc_pm_sequencer fv_ecc_pm_sequencer + #(.ADDR_WIDTH(ADDR_WIDTH), + .DATA_WIDTH(DATA_WIDTH) + ) + fv_ecc_pm_sequencer_inst( + .clk(clka), + .rst_n(reset_n && !zeroize), + .ena(ena), + .addra(addra), + .douta(douta) + ); diff --git a/src/ecc/formal/properties/fv_ecc_ram_tdp_file.sv b/src/ecc/formal/properties/fv_ecc_ram_tdp_file.sv new file mode 100644 index 000000000..7cad1927b --- /dev/null +++ b/src/ecc/formal/properties/fv_ecc_ram_tdp_file.sv @@ -0,0 +1,210 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_ecc_ram_tdp_file #( + parameter ADDR_WIDTH = 10, + parameter DATA_WIDTH = 32 + ) + ( + input wire clk, + input wire rst_n, + + + input wire ena, + input wire wea, + input wire [ADDR_WIDTH-1 : 0] addra, + input wire [DATA_WIDTH-1 : 0] dina, + input logic [DATA_WIDTH-1 : 0] douta, + + input wire enb, + input wire web, + input wire [ADDR_WIDTH-1 : 0] addrb, + input wire [DATA_WIDTH-1 : 0] dinb, + input logic [DATA_WIDTH-1 : 0] doutb + ); + + // Declare the RAM variable + localparam ADDR_LENGTH = 2**ADDR_WIDTH; + default clocking default_clk @(posedge clk); endclocking + + + sequence reset_sequence; + !rst_n ##1 rst_n; + endsequence + +addr_not_same_write : assume property (disable iff(!rst_n) (ena && wea && enb && web) |-> addra != addrb); + + +//////////////////////////////////////////// +// reset property, when reset out a and b // +// are zero // +//////////////////////////////////////////// + + property reset_p; + $past(!rst_n) + |-> + douta == '0 && + doutb == '0; + endproperty + + reset_a : assert property(reset_p); + + + + + +/////////////////////////////////////////////// +//Symbolic checking // +/////////////////////////////////////////////// + logic [ADDR_WIDTH-1:0] sym_addr; + + property sym_reset_mem_p; + $past(!rst_n) + |-> + ecc_ram_tdp_file.mem[sym_addr] == '0; + endproperty + sym_reset_mem_a: assert property(sym_reset_mem_p); + + + /////////////////////////////////////////////// + // write to the memory with din in the // + // address provided considering the addresses// + // a and b will not be same while writing // + /////////////////////////////////////////////// + + logic [8:0] idx_sym_data_wr_a; + logic [8:0] idx_sym_data_wr_b; + + idx_sym_wr_a_less_than_384: assume property(disable iff(!rst_n) (idx_sym_data_wr_a<9'd384) && $stable(idx_sym_data_wr_a)); + idx_sym_wr_b_less_than_384: assume property(disable iff(!rst_n) (idx_sym_data_wr_b<9'd384) && $stable(idx_sym_data_wr_b)); + + + property write_p(en,we,addr,dout,din,idx); + logic [ADDR_WIDTH-1 : 0] store_addr; + logic [DATA_WIDTH-1: 0] store_data; + en && + we + ##0 (1'b1, store_addr = addr) + ##0 (1'b1, store_data = ecc_ram_tdp_file.mem[addr]) + |=> + dout[idx] == store_data[idx] && + (ecc_ram_tdp_file.mem[store_addr][idx]) == $past(din[idx]) + ; + endproperty + write_a_a: assert property(disable iff(!rst_n)write_p(ena,wea,addra,douta,dina,idx_sym_data_wr_a)); + write_b_a: assert property(disable iff(!rst_n)write_p(enb,web,addrb,doutb,dinb,idx_sym_data_wr_b)); + + + + + /////////////////////////////////////////////// + // read to the memory with whatever the // + // address provided considering the addresses// + // a and b can be same // + /////////////////////////////////////////////// + logic [8:0] idx_sym_data_rd_a; + logic [8:0] idx_sym_data_rd_b; + + idx_sym_rd_a_less_than_384: assume property(disable iff(!rst_n) (idx_sym_data_rd_a<9'd384) && $stable(idx_sym_data_rd_a)); + idx_sym_rd_b_less_than_384:assume property(disable iff(!rst_n) (idx_sym_data_rd_b<9'd384) && $stable(idx_sym_data_rd_b)); + + + property read_p(en,we,addr,dout,idx); + logic [DATA_WIDTH-1:0] store_data; + logic [ADDR_WIDTH-1:0] store_addr; + en && + !we + ##0 (1'b1, store_data = ecc_ram_tdp_file.mem[addr] ) + |=> + dout[idx] == store_data[idx] + ; + endproperty + read_a_a: assert property(disable iff(!rst_n)read_p(ena,wea,addra,douta,idx_sym_data_rd_a)); + read_b_a: assert property(disable iff(!rst_n)read_p(enb,web,addrb,doutb,idx_sym_data_rd_b)); + + + + +/////////////////////////////////////////////// +// No enable, no read and write // +/////////////////////////////////////////////// + logic [8:0] idx_sym_nen_a; + logic [8:0] idx_sym_nen_b; + logic [8:0] idx_sym_nen_ab; + + idx_sym_nen_a_less_than_384: assume property(disable iff(!rst_n) (idx_sym_nen_a<9'd384) && $stable(idx_sym_nen_a)); + idx_sym_nen_b_less_than_384: assume property(disable iff(!rst_n) (idx_sym_nen_b<9'd384) && $stable(idx_sym_nen_b)); + idx_sym_nen_ab_less_than_384: assume property(disable iff(!rst_n) (idx_sym_nen_ab<9'd384) && $stable(idx_sym_nen_ab)); + + + property no_enable_p(en,dout,addr,idx); + logic [DATA_WIDTH-1:0] store_data; + logic [ADDR_WIDTH-1 : 0] store_addr; + !en && + addra != addrb + ##0 (1'b1, store_data = ecc_ram_tdp_file.mem[addr] ) + ##0 (1'b1, store_addr = addr) + |=> + dout[idx] == $past(dout[idx]) && + (ecc_ram_tdp_file.mem[store_addr][idx]) == store_data[idx]; + endproperty + + no_enable_a_a: assert property(disable iff(!rst_n) no_enable_p(ena,douta,addra,idx_sym_nen_a)); + no_enable_b_a: assert property(disable iff(!rst_n) no_enable_p(enb,doutb,addrb,idx_sym_nen_b)); + + + property no_enable_ab_p; + logic [DATA_WIDTH-1:0] store_datab,store_dataa; + logic [ADDR_WIDTH-1 : 0] store_addrb,store_addra; + !ena && + !enb + ##0 (1'b1, store_dataa = ecc_ram_tdp_file.mem[addra] ) + ##0 (1'b1, store_addra = addra) + ##0 (1'b1, store_datab = ecc_ram_tdp_file.mem[addrb] ) + ##0 (1'b1, store_addrb = addrb) + |=> + douta[idx_sym_nen_ab] == $past(douta[idx_sym_nen_ab]) && + (ecc_ram_tdp_file.mem[store_addra][idx_sym_nen_ab]) == store_dataa[idx_sym_nen_ab] && + doutb[idx_sym_nen_ab] == $past(doutb[idx_sym_nen_ab]) && + (ecc_ram_tdp_file.mem[store_addrb][idx_sym_nen_ab]) == store_datab[idx_sym_nen_ab]; + endproperty + + no_enable_ab_a: assert property(disable iff(!rst_n) no_enable_ab_p); + +endmodule + + + +bind ecc_ram_tdp_file fv_ecc_ram_tdp_file #( + .ADDR_WIDTH(ADDR_WIDTH), + .DATA_WIDTH(DATA_WIDTH) + ) + fv_ecc_ram_tdp_file_inst( + .clk(clk), + .rst_n(reset_n && !zeroize), + .ena(ena), + .wea(wea), + .addra(addra), + .dina(dina), + .douta(douta), + .enb(enb), + .web(web), + .addrb(addrb), + .dinb(dinb), + .doutb(doutb) + ); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_montmultiplier.sv b/src/ecc/formal/properties/fv_montmultiplier.sv new file mode 100644 index 000000000..42011dd95 --- /dev/null +++ b/src/ecc/formal/properties/fv_montmultiplier.sv @@ -0,0 +1,269 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_montmultiplier #( + parameter REG_SIZE = 384, + parameter RADIX = 32 +) +( + // Clock and reset. + input logic clk, + input logic rst_n, + + // DATA PORT + input logic start_i, + input logic [REG_SIZE-1:0] opa_i, + input logic [REG_SIZE-1:0] opb_i, + input logic [REG_SIZE-1:0] n_i, + input logic [RADIX-1:0] n_prime_i, // only need the last few bits + input logic [REG_SIZE-1:0] p_o, + input logic ready_o +); + +default clocking default_clk @(posedge clk); endclocking + + +//-------------------------------------------------------// +//R = 2^((ceil(bits(n_i)/RADIX)+1)*RADIX) +//R^(-1) = R invmod n_i; +//localparam R = 417'h100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; +//localparam R_inv = 355'h0600000014000000140000000C00000002FFFFFFFCFFFFFFFAFFFFFFFBFFFFFFF7FFFFFFE5FFFFFFD8FFFFFFE7; +//-------------------------------------------------------// + + +localparam MULT_DLY = 40; // Defines after start how many cycles ready would stay deasserted. + + +localparam int unsigned S_NUM = ((REG_SIZE + RADIX - 1) / RADIX) + 1; +localparam int unsigned FULL_REG_SIZE = S_NUM * RADIX; + +localparam PE_UNITS = ((S_NUM - 1) / 2) - 1; + + +function logic[ REG_SIZE-1:0] montmult (logic[ REG_SIZE-1:0] a, logic[ REG_SIZE-1:0] b, logic[ REG_SIZE-1:0] c, logic[ REG_SIZE-1:0] d); + return ((1152'(768'(a*b)*c)%d)); +endfunction + + + +sequence reset_sequence; + !rst_n ##1 rst_n; +endsequence + +property reset_p; + $past(!rst_n) + |-> + p_o == 0 && + ready_o == 1; +endproperty + +reset_a: assert property(reset_p); + + +//////////////////////////////////////////// +// start_i triggers only after multi done // +/////////////////////////////////////////// +start_mult_as: assume property(disable iff(!rst_n)start_mult_as_p); + +property start_mult_as_p; + start_i + |=> + !start_i until (ready_o); +endproperty + +mult_operands_less_than_prime: assume property(disable iff(!rst_n) mult_operands_less_than_prime_p); + +property mult_operands_less_than_prime_p; + start_i + |-> + opa_i < n_i && + opb_i < n_i ; +endproperty + + + +`ifndef FOR48 + + +///////////////////////////////////////////////// +// Property for 16 bit to prove the computation// +//////////////////////////////////////////////// + +/********For inp value less than 4 bits ******/ +property multi_0_p(prime_i, mu_i,r_inv); + logic [REG_SIZE-1:0] temp; + n_i == prime_i && + n_prime_i == mu_i && + opa_i <= 4'hf && + opb_i <= 4'hf && + start_i + ##0 (1'b1, temp = (48'(32'(opa_i*opb_i)*r_inv)%n_i)) + |-> + ##16 + (p_o == temp) && + ready_o; + endproperty + + +/********For inp value less than 8 bits ******/ +property multi_1_p(prime_i, mu_i,r_inv); + logic [REG_SIZE-1:0] temp; + n_i == prime_i && + n_prime_i == mu_i && + opa_i <= 8'hff && + opb_i <= 8'hff && + opa_i > 4'hf && + opb_i > 4'hf && + start_i + ##0 (1'b1, temp = (48'(32'(opa_i*opb_i)*r_inv)%n_i)) + + |-> + ##16 + (p_o == temp) && + ready_o; + endproperty + + +/********For inp value less than 12 bits ******/ +property multi_2_p(prime_i, mu_i,r_inv); + logic [REG_SIZE-1:0] temp; + n_i == prime_i && + n_prime_i == mu_i && + opa_i <= 12'hfff && + opb_i <= 12'hfff && + opa_i > 8'hff && + opb_i > 8'hff && + start_i + ##0 (1'b1, temp = (48'(32'(opa_i*opb_i)*r_inv)%n_i)) + |-> + ##16 //for 16 bit just gave a slack + (p_o[0] == temp[0]) && + ready_o; + endproperty + +/********For inp value all bits ******/ +property multi_p(prime_i, mu_i,r_inv); + logic [REG_SIZE-1:0] temp; + n_i == prime_i && + n_prime_i == mu_i && + start_i + ##0 (1'b1, temp = (48'(32'(opa_i*opb_i)*r_inv)%n_i)) + |-> + ##16 //for 16 bit just gave a slack + p_o == temp && + ready_o; + endproperty + +logic [4:0][REG_SIZE-1:0] prime; +logic [4:0][RADIX-1:0] mu_word; +logic [4:0][REG_SIZE-1:0] rinv; +assign prime ={16'hfceb,16'hfcfb,16'hfd0d,16'hfd0f,16'hfd19}; +assign mu_word = {4'hd,4'hd,4'hb,4'h1,4'h7}; +assign rinv ={16'hc0ea,16'he269,16'hcc03,16'h1a92,16'h4e28}; + +genvar i; +for(i=0;i<5;i++) begin + multi_a: assert property(disable iff (!rst_n) multi_p(prime[i], mu_word[i],rinv[i])); + multi_2_a: assert property(disable iff (!rst_n) multi_2_p(prime[i], mu_word[i],rinv[i])); + multi_1_a: assert property(disable iff (!rst_n) multi_1_p(prime[i], mu_word[i],rinv[i])); + multi_0_a: assert property(disable iff (!rst_n) multi_0_p(prime[i], mu_word[i],rinv[i])); +end + + +///////////////////////////////////////////////// +// Property for ready deassert // +//////////////////////////////////////////////// + +property no_ready_p; + start_i + |=> + !ready_o[*15]; +endproperty + +no_ready_a: assert property(disable iff(!rst_n)no_ready_p); + + +//-------------------------------------------------------------------------------------------------// +// For 48 bit operands // +//-------------------------------------------------------------------------------------------------// + + +`else + + +/********For inp value all bits ******/ +property multi_p(prime_i, mu_i,r_inv); + logic [REG_SIZE-1:0] temp; + n_i == prime_i && + n_prime_i == mu_i && + start_i + ##0 (1'b1, temp = (144'(96'(opa_i*opb_i)*r_inv)%n_i)) + //##0 (1'b1, temp = ((1152'(768'(opa_i*opb_i)*r_inv)%n_i))) + ##1 ready_o[->1] + |-> + + p_o == temp; +endproperty + + +logic [4:0][REG_SIZE-1:0] prime; +logic [4:0][RADIX-1:0] mu_word; +logic [4:0][REG_SIZE-1:0] rinv; +assign prime ={48'hffffffffff9f,48'hffffffffffb3,48'hffffffffffbf,48'hffffffffffc9,48'hffffffffffd5}; +assign mu_word = {4'h1,4'h5,4'h1,4'h7,4'h3}; +assign rinv ={48'h1fd5c5f02a2e,48'h3ce213f2b376,48'h1fc0fc0fc0f4,48'h686fb586fb42,48'h30be82fa0be0}; + + +genvar i; +for(i=0;i<5;i++) begin + multi_a: assert property(disable iff (!rst_n) multi_p(prime[i], mu_word[i],rinv[i])); + end + +///////////////////////////////////////////////// +// Property for ready deassert // +//////////////////////////////////////////////// + +property no_ready_p; + start_i + |=> + !ready_o[*(MULT_DLY-1)]; +endproperty + +no_ready_a: assert property(disable iff(!rst_n)no_ready_p); + +`endif +endmodule + +bind ecc_montgomerymultiplier fv_montmultiplier #( + .REG_SIZE(REG_SIZE), + .RADIX(RADIX) + ) + fv_montmultiplier_inst ( + // Clock and reset. + .clk(clk), + .rst_n(reset_n && !zeroize), + + // DATA PORT + .start_i(start_i), + .opa_i(opa_i), + .opb_i(opb_i), + .n_i(n_i), + .n_prime_i(n_prime_i), // only need the last few bits + .p_o(p_o), + .ready_o(ready_o) + ); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_montmultiplier_glue.sv b/src/ecc/formal/properties/fv_montmultiplier_glue.sv new file mode 100644 index 000000000..ad8573f5c --- /dev/null +++ b/src/ecc/formal/properties/fv_montmultiplier_glue.sv @@ -0,0 +1,252 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_montmultiplier_glue #( + parameter REG_SIZE = 384, + parameter RADIX = 32 +) +( + // Clock and reset. + input wire clk, + input wire rst_n, + + + // DATA PORT + input wire start_i, + input wire [REG_SIZE-1:0] opa_i, + input wire [REG_SIZE-1:0] opb_i, + input wire [REG_SIZE-1:0] n_i, + input wire [RADIX-1:0] n_prime_i, // only need the last few bits + input logic [REG_SIZE-1:0] p_o, + input logic ready_o +); + +localparam int unsigned S_NUM = ((REG_SIZE + RADIX - 1) / RADIX) + 1; +localparam int unsigned FULL_REG_SIZE = S_NUM * RADIX; + +localparam PE_UNITS = ((S_NUM - 1) / 2) - 1; + +localparam [(FULL_REG_SIZE-REG_SIZE)-1 : 0] fv_zero_pad = '0; + +localparam prime_p = 384'hfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff; +localparam prime_q = 384'hffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973; +localparam p_mu = 32'h00000001; +localparam q_mu = 32'he88fdc45; +localparam MULT_DLY = 40; +localparam DLY_CONCAT = MULT_DLY - (2*(PE_UNITS+1))-1; //27 + + +///////////////////////////////////////////////// +// Function for selecting o/p // +///////////////////////////////////////////////// +function logic[REG_SIZE-1:0] reduction_prime(input logic [FULL_REG_SIZE-1:0] a, input logic [REG_SIZE-1:0] b); + if(a>=b) + return(a-b); + else + return(a); +endfunction + + +default clocking default_clk @(posedge clk); endclocking + +// constraint that the multiplication is enable and doesn't trigger until the current computation done +property start_mult_as_p; + start_i + |=> + !start_i until (ready_o); +endproperty +start_mult_as: assume property(disable iff(!rst_n)start_mult_as_p); + + +// Reset property +sequence reset_sequence; + !rst_n ##1 rst_n; +endsequence + +property reset_a; + reset_sequence + |-> + p_o == 0 && + ready_o == 1; +endproperty + +reset_p: assert property(reset_a); + + + +// Bit symbolics used for proof convergence, these define the bit to be checked in proof +logic [8:0] fv_bit_idx_p; +logic [8:0] fv_bit_idx_q; +idx_384_p_assump: assume property(disable iff(!rst_n) fv_bit_idx_p < 384); +idx_384_q_assump: assume property(disable iff(!rst_n) fv_bit_idx_q < 384); + + + +////////////////////////////////////////////////// +// Once the start triggers then after a delay of 28 cycles i.e DLY_CONCAT because to push the whole +// operand a sequentially would require 26 cycles and 2 extra cycles for valid computation to receive on first box +// from next cycle on as each block of PE works parallely on 2 RADIX elements, next computed value is again on first_box +// later the sequence continues until the last block i.e the carry bits are stored and then reduced by prime +// + +property compare_p(prime,idx); +logic [REG_SIZE-1:0] fv_result; +logic [FULL_REG_SIZE-1:0] fv_reg; + ##0 n_i == prime + ##0 start_i + ##DLY_CONCAT + ##0 (1'b1, fv_reg[RADIX-1:0] = (ecc_montgomerymultiplier.gen_PE[0].box_i.s_out)) + ##1 (1'b1, fv_reg[2*RADIX-1:RADIX] = (ecc_montgomerymultiplier.gen_PE[0].box_i.s_out)) + ##1 (1'b1, fv_reg[3*RADIX-1:2*RADIX] = (ecc_montgomerymultiplier.gen_PE[1].box_i.s_out)) + ##1 (1'b1, fv_reg[4*RADIX-1:3*RADIX] = (ecc_montgomerymultiplier.gen_PE[1].box_i.s_out)) + ##1 (1'b1, fv_reg[5*RADIX-1:4*RADIX] = (ecc_montgomerymultiplier.gen_PE[2].box_i.s_out)) + ##1 (1'b1, fv_reg[6*RADIX-1:5*RADIX] = (ecc_montgomerymultiplier.gen_PE[2].box_i.s_out)) + ##1 (1'b1, fv_reg[7*RADIX-1:6*RADIX] = (ecc_montgomerymultiplier.gen_PE[3].box_i.s_out)) + ##1 (1'b1, fv_reg[8*RADIX-1:7*RADIX] = (ecc_montgomerymultiplier.gen_PE[3].box_i.s_out)) + ##1 (1'b1, fv_reg[9*RADIX-1:8*RADIX] = (ecc_montgomerymultiplier.gen_PE[4].box_i.s_out)) + ##1 (1'b1, fv_reg[10*RADIX-1:9*RADIX] = (ecc_montgomerymultiplier.gen_PE[4].box_i.s_out)) + ##1 (1'b1, fv_reg[11*RADIX-1:10*RADIX] = (ecc_montgomerymultiplier.final_box.s_out)) + ##1 (1'b1, fv_reg[12*RADIX-1:11*RADIX] = (ecc_montgomerymultiplier.final_box.s_out)) + ##0 (1'b1, fv_reg[13*RADIX-1:12*RADIX] = (ecc_montgomerymultiplier.final_box.c_out[RADIX-1:0])) + ##0 (1'b1, fv_result = reduction_prime(fv_reg, prime)) + |=> + ##1 + ready_o && + p_o[idx] == fv_result[idx]; +endproperty +compare_concat_prime_p_a : assert property ( disable iff(!rst_n) compare_p(prime_p,fv_bit_idx_p)); +compare_concat_prime_q_a : assert property ( disable iff(!rst_n) compare_p(prime_q,fv_bit_idx_q)); + + + +//a_reg shifts by RADIX, when odd and no start + +property when_odd_a_array_shifts_p; + ecc_montgomerymultiplier.odd && + !start_i + |=> + ecc_montgomerymultiplier.a_array[0] == RADIX'($past(ecc_montgomerymultiplier.a_reg)>>RADIX) && + ecc_montgomerymultiplier.a_reg == ($past(ecc_montgomerymultiplier.a_reg)>>RADIX); +endproperty +when_odd_a_array_shifts_a : assert property ( disable iff(!rst_n) when_odd_a_array_shifts_p); + +// a_reg stable if no odd +property when_even_a_array_stable_p; + !ecc_montgomerymultiplier.odd && + !start_i + |=> + ecc_montgomerymultiplier.a_array[0] == $past(ecc_montgomerymultiplier.a_array[0]) && + ecc_montgomerymultiplier.a_reg == $past(ecc_montgomerymultiplier.a_reg); +endproperty +when_even_a_array_stable_a : assert property ( disable iff(!rst_n) when_even_a_array_stable_p); + + + +// reg's set once start is triggered + + property reg_set_start_p; + start_i + |=> + ecc_montgomerymultiplier.a_reg == {fv_zero_pad, $past(opa_i)} && + ecc_montgomerymultiplier.b_reg == {fv_zero_pad, $past(opb_i)} && + ecc_montgomerymultiplier.p_reg == {fv_zero_pad, $past(n_i)} && + ecc_montgomerymultiplier.n_prime_reg == $past(n_prime_i); + endproperty + reg_set_start_a : assert property ( disable iff(!rst_n) reg_set_start_p); + +// reg's stay stable if no start cmd + property reg_no_start_p; + !start_i + |=> + ecc_montgomerymultiplier.b_reg == $past(ecc_montgomerymultiplier.b_reg) && + ecc_montgomerymultiplier.p_reg == $past(ecc_montgomerymultiplier.p_reg) && + ecc_montgomerymultiplier.n_prime_reg == $past(ecc_montgomerymultiplier.n_prime_reg); + endproperty + reg_no_start_a : assert property ( disable iff(!rst_n) reg_no_start_p); + + +//b_array and p_array in 64bit takes MSB 32 if odd if not LSB 32 + + property when_odd_b_p_array_p(idx); + ecc_montgomerymultiplier.odd + |-> + ecc_montgomerymultiplier.b_array[idx] == ecc_montgomerymultiplier.b_reg[(((2*idx)+1)*RADIX)-1 : (2*idx)*RADIX] && + ecc_montgomerymultiplier.p_array[idx] == ecc_montgomerymultiplier.p_reg[(((2*idx)+1)*RADIX)-1 : (2*idx)*RADIX]; + endproperty + + //b_array and p_array are 64bits takes LSB 32 if even from b_reg and p_reg + property when_even_b_p_array_p(idx); + !ecc_montgomerymultiplier.odd + |-> + ecc_montgomerymultiplier.b_array[idx] == ecc_montgomerymultiplier.b_reg[((2*idx)*RADIX)-1 : ((2*idx)-1)*RADIX] && + ecc_montgomerymultiplier.p_array[idx] == ecc_montgomerymultiplier.p_reg[((2*idx)*RADIX)-1 : ((2*idx)-1)*RADIX]; + endproperty + + for (genvar i=1; i < (PE_UNITS+2); i++) begin + when_odd_b_p_array_a : assert property ( disable iff(!rst_n) when_odd_b_p_array_p(i)); + when_even_b_p_array_a : assert property ( disable iff(!rst_n) when_even_b_p_array_p(i)); + end + + + // connections for the s_in's of the pe blocks + property s_in_routing_p; + ecc_montgomerymultiplier.gen_PE[0].box_i.s_in == ecc_montgomerymultiplier.gen_PE[1].box_i.s_out; + endproperty + //for (genvar i=0; i < (PE_UNITS); i++) begin + s_in_routing_a: assert property (disable iff(!rst_n) s_in_routing_p); + //end + + + // connections for the a_in's of the pe blocks + property a_in_routing_p; + ecc_montgomerymultiplier.gen_PE[0].box_i.a_in == ecc_montgomerymultiplier.first_box.a_out; + endproperty + + a_in_routing_a: assert property (disable iff(!rst_n) a_in_routing_p); + + + // connections for the m_in's,c_in's of the pe blocks + property m_c_in_routing_p; + ecc_montgomerymultiplier.gen_PE[0].box_i.m_in == ecc_montgomerymultiplier.first_box.m_out && + ecc_montgomerymultiplier.gen_PE[0].box_i.c_in == ecc_montgomerymultiplier.first_box.c_out; + + endproperty + m_c_in_routing_a: assert property (disable iff(!rst_n) m_c_in_routing_p); + + +endmodule + +bind ecc_montgomerymultiplier fv_montmultiplier_glue #( + .REG_SIZE(REG_SIZE), + .RADIX(RADIX) + ) + fv_montmultiplier_glue_inst ( + // Clock and reset. + .clk(clk), + .rst_n(reset_n && !zeroize), + + // DATA PORT + .start_i(start_i), + .opa_i(opa_i), + .opb_i(opb_i), + .n_i(n_i), + .n_prime_i(n_prime_i), // only need the last few bits + .p_o(p_o), + .ready_o(ready_o) + ); + diff --git a/src/ecc/formal/properties/fv_pe.sv b/src/ecc/formal/properties/fv_pe.sv new file mode 100644 index 000000000..9b9acbe78 --- /dev/null +++ b/src/ecc/formal/properties/fv_pe.sv @@ -0,0 +1,218 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_pe #( + parameter RADIX = 32 +) +( + // Clock and reset. + input logic clk, + input logic rst_n, + + input logic start_in, + input logic [RADIX-1:0] a_in, + input logic [RADIX-1:0] b_in, + input logic [RADIX-1:0] p_in, + input logic [RADIX-1:0] m_in, + input logic [RADIX-1:0] s_in, + input logic [RADIX :0] c_in, + input logic odd, + + input logic [RADIX-1:0] a_out, + input logic [RADIX-1:0] m_out, + input logic [RADIX-1:0] s_out, + input logic [RADIX :0] c_out +); + + + +function logic [2*RADIX :0] add_func( input logic [RADIX-1:0] a_in, + input logic [RADIX-1:0] b_in, + input logic [RADIX-1:0] p_in, + input logic [RADIX-1:0] m_in, + input logic [RADIX :0] c_in, + input logic [RADIX-1:0] s_in + ); + + return((a_in*b_in)+(p_in*m_in)+c_in+s_in); +endfunction + + + +default clocking default_clk @(posedge clk); endclocking + +//////////////////////////////////////////////////// +// reset or start_in // +//////////////////////////////////////////////////// + +sequence reset_sequence; + !rst_n || start_in ##1 rst_n; +endsequence + + +property reset_p; +$past(!rst_n || start_in) +|-> +m_out == 0 && +a_out == 0 && +s_out == 0 && +c_out == 0; +endproperty + +reset_a : assert property(reset_p); + + +//////////////////////////////////////////////////// +// aout when odd takes the previous value of ain // +//////////////////////////////////////////////////// + +property aout_p; + odd && + !start_in + |=> + a_out == $past(a_in); +endproperty + +aout_a : assert property(disable iff(!rst_n)aout_p); + + +//////////////////////////////////////////////////// +// mout when odd takes the previous value of min // +//////////////////////////////////////////////////// + +property mout_p; + odd && + !start_in + |=> + m_out == $past(m_in); +endproperty + +mout_a : assert property(disable iff(!rst_n) mout_p); + + + +//////////////////////////////////////////////////////// +// aout when even takes the previous value of itself // +//////////////////////////////////////////////////////// +property aout_even_p; + !odd && + !start_in + |=> + a_out == $past(a_out); +endproperty + +aout_even_a : assert property(disable iff(!rst_n)aout_even_p); + + + +//////////////////////////////////////////////////////// +// mout when even takes the previous value of itself // +//////////////////////////////////////////////////////// +property mout_even_p; + !odd && + !start_in + |=> + m_out == $past(m_out); +endproperty + +mout_even_a : assert property(disable iff(!rst_n) mout_even_p); + + + +//////////////////////////////////////////////////////////// +// sout when odd LSB (a_in*b_in)+(p_in*m_in)+c_out+s_in // +//////////////////////////////////////////////////////////// +property sout_odd_p; +logic [2*RADIX :0] temp; + odd && + !start_in + ##0 (1'b1, temp = add_func(a_in,b_in,p_in,m_in,c_out,s_in)) + |=> + s_out == temp[RADIX-1:0]; +endproperty + +sout_odd_a : assert property(disable iff(!rst_n) sout_odd_p); + + + +/////////////////////////////////////////////////////////// +// sout when even LSB a_in*b_in)+(p_in*m_in)+c_in+s_out // +/////////////////////////////////////////////////////////// +property sout_even_p; +logic [2*RADIX :0] temp; + !odd && + !start_in + ##0 (1'b1, temp = add_func(a_in,b_in,p_in,m_in,c_in,s_out)) + |=> + s_out == temp[RADIX-1:0]; +endproperty + +sout_even_a : assert property(disable iff(!rst_n) sout_even_p); + + +//////////////////////////////////////////////////////////// +// cout when odd MSB (a_in*b_in)+(p_in*m_in)+c_out+s_in // +//////////////////////////////////////////////////////////// +property cout_odd_p; +logic [2*RADIX :0] temp; + odd && + !start_in + ##0 (1'b1, temp = add_func(a_in,b_in,p_in,m_in,c_out,s_in)) + |=> + c_out == temp[2*RADIX:RADIX]; +endproperty + +cout_odd_a : assert property(disable iff(!rst_n) cout_odd_p); + + + +/////////////////////////////////////////////////////////// +// cout when even MSB a_in*b_in)+(p_in*m_in)+c_in+s_out // +/////////////////////////////////////////////////////////// +property cout_even_p; +logic [2*RADIX :0] temp; + !odd && + !start_in + ##0 (1'b1, temp = add_func(a_in,b_in,p_in,m_in,c_in,s_out)) + |=> + c_out == temp[2*RADIX:RADIX]; +endproperty + +cout_even_a : assert property(disable iff(!rst_n) cout_even_p); + + + +endmodule + +bind ecc_pe fv_pe #(.RADIX(RADIX))fv_pe_inst( + .clk(clk), + .rst_n(reset_n && !zeroize), + + .start_in(start_in), + .a_in(a_in), + .b_in(b_in), + .p_in(p_in), + .m_in(m_in), + .s_in(s_in), + .c_in(c_in), + .odd(odd), + .a_out(a_out), + .m_out(m_out), + .s_out(s_out), + .c_out(c_out) + ); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_pe_final.sv b/src/ecc/formal/properties/fv_pe_final.sv new file mode 100644 index 000000000..7e739e310 --- /dev/null +++ b/src/ecc/formal/properties/fv_pe_final.sv @@ -0,0 +1,126 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_pe_final #( + parameter RADIX = 32 +) ( + input logic clk, + input logic rst_n, + + input logic start_in, + // DATA PORT + input logic [RADIX-1:0] a_in, + input logic [RADIX-1:0] b_in, + input logic [RADIX-1:0] p_in, + input logic [RADIX-1:0] m_in, + input logic [RADIX-1:0] s_in, + input logic [RADIX :0] c_in, + input logic odd, + + input logic [RADIX-1:0] s_out, + input logic [RADIX :0] c_out +); + +default clocking default_clk @(posedge clk); endclocking + + +sequence reset_sequence; + !rst_n || start_in ##1 rst_n; +endsequence + +property reset_p; +$past(!rst_n || start_in) +|-> +s_out == 0 && +c_out == 0; +endproperty + +reset_a : assert property (reset_p); + + + +property s_out_odd_p; + odd && + !start_in + |=> + s_out == $past(32'(64'(a_in * b_in) + 64'(p_in * m_in)+ c_out + s_in)); +endproperty + +s_out_odd_a : assert property (disable iff(!rst_n) s_out_odd_p); + + + + +property s_out_noodd_p; + + !odd && + !start_in + |=> + s_out == $past(32'(64'(a_in * b_in) + 64'(p_in * m_in)+ c_in + s_out)); +endproperty + +s_out_noodd_a : assert property (disable iff(!rst_n) s_out_noodd_p); + + + + +property c_out_odd_p; +logic [2*RADIX : 0] temp; + odd && + !start_in + ##0 (1'b1, temp = (64'(a_in * b_in) + 64'(p_in * m_in)+ c_out + s_in)) + |=> + //c_out == $past(33'((64'(a_in * b_in) + 64'(p_in * m_in)+ c_out + s_in)>>32)); + c_out == temp[2*RADIX:RADIX]; +endproperty + +c_out_odd_a : assert property (disable iff(!rst_n) c_out_odd_p); + + + + +property c_out_noodd_p; +logic [2*RADIX : 0] temp; + !odd && + !start_in + ##0 (1'b1, temp = (64'(a_in * b_in) + 64'(p_in * m_in)+ c_in + s_out)) + |=> + //c_out == $past(33'((64'(a_in * b_in) + 64'(p_in * m_in)+ c_in + s_out)>>32)); + c_out == temp[2*RADIX:RADIX]; +endproperty + +c_out_noodd_a : assert property (disable iff(!rst_n) c_out_noodd_p); + +endmodule + +bind ecc_pe_final fv_pe_final #(.RADIX(RADIX)) fv_pe_final_inst( + .clk(clk), + .rst_n(reset_n && !zeroize), + + .start_in(start_in), + .a_in(a_in), + .b_in(b_in), + .p_in(p_in), + .m_in(m_in), + .s_in(s_in), + .c_in(c_in), + .odd(odd), + + .s_out(s_out), + .c_out(c_out) + ); diff --git a/src/ecc/formal/properties/fv_pe_first.sv b/src/ecc/formal/properties/fv_pe_first.sv new file mode 100644 index 000000000..7fd0b5c1a --- /dev/null +++ b/src/ecc/formal/properties/fv_pe_first.sv @@ -0,0 +1,275 @@ +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_pe_first #( + parameter RADIX = 32 +) +( + // Clock and reset. + input logic clk, + input logic rst_n, + + input logic start_in, + input logic [RADIX-1:0] a_in, + input logic [RADIX-1:0] b_in, + input logic [RADIX-1:0] p_in, + input logic [RADIX-1:0] s_in, + input wire [RADIX-1:0] n_prime_in, + input logic odd, + + input logic [RADIX-1:0] a_out, + input logic [RADIX-1:0] m_out, + input logic [RADIX :0] c_out +); + + + +default clocking default_clk @(posedge clk); endclocking + + +////////////////////////////////////////// +// m_out_func where it depends on // +// (s_in+(a_in*b_in)_lsw)*n_prme_in // +////////////////////////////////////////// + +function logic[RADIX-1:0] m_out_func (input logic [RADIX-1:0] a,input logic [RADIX-1:0] b, +input logic [RADIX-1:0] c,input logic [RADIX-1:0] d); + logic [RADIX-1:0] mult_lsw; + mult_lsw = b*c; + mult_lsw = (a+mult_lsw)*d; + return (mult_lsw); +endfunction + + +///////////////////////////////////////////// +// c_out_func where it depends on // +// previous sum(s0), carry(c0) multiplied // +// with p_in and added(res=m_temp*pin_lsw // +// carry = msw + res[maxbit] + previous(c0)// +///////////////////////////////////////////// + +function logic[RADIX:0] c_out_func (input logic [RADIX-1:0] a,input logic [RADIX-1:0] b, +input logic [RADIX:0] c, input logic [RADIX-1:0] d); + + logic[(2*RADIX)-1:0] mult; + logic [RADIX:0] res; + logic [RADIX:0] c1; + mult = a * b; + res = d + mult[RADIX-1:0]; + c1 = mult[(2*RADIX)-1:RADIX] + res[RADIX]; + +return(c1+c); + +endfunction + +/////////////////////////////////////////////// +// c_0 func used for calculating the previous// +// carry used in c_out computation // +/////////////////////////////////////////////// + +function logic[RADIX:0] c_0 (input logic [RADIX-1:0] a,input logic [RADIX-1:0] b, +input logic [RADIX-1:0] c); + logic[(2*RADIX)-1:0] mult_0; + logic [RADIX:0] res_0; + mult_0 = b*c; + res_0 = a + mult_0[RADIX-1:0]; + return (mult_0[(2*RADIX)-1:RADIX]+res_0[RADIX]); +endfunction + + +/////////////////////////////////////////////// +// m_temp_reg func used for calculating the // +// previous m_out in c_out computation // +/////////////////////////////////////////////// + +function logic[RADIX-1:0] m_temp_reg (input logic [RADIX-1:0] a,input logic [RADIX-1:0] b, +input logic [RADIX-1:0] c,input logic [RADIX-1:0] d); + logic [RADIX:0] res_0; + + res_0 = s_0(a,b,c); + return ((res_0[RADIX-1:0])*d); +endfunction + + + +/////////////////////////////////////////////// +// s_0 func used for calculating the previous// +// sum used in c_out computation // +/////////////////////////////////////////////// +function logic[RADIX-1:0] s_0 (input logic [RADIX-1:0] a,input logic [RADIX-1:0] b, +input logic [RADIX-1:0] c ); + logic[(2*RADIX)-1:0] mult_0; + logic [RADIX:0] res_0; + mult_0 = b*c; + res_0 = a + mult_0[RADIX-1:0]; + return ((res_0[RADIX-1:0])); +endfunction + + + +sequence reset_sequence; + !rst_n || start_in ##1 rst_n; +endsequence + +////////////////////////////////////////// +// When in reset carry and the sum, // +// array a are zero // +////////////////////////////////////////// + +property reset_p; +$past(!rst_n || start_in) +|-> +m_out == 0 && +a_out == 0 && +c_out == 0; +endproperty + +reset_a : assert property(reset_p); + + + +////////////////////////////////////////// +// When its odd and no start then // +// a out takes the previous a_in value // +////////////////////////////////////////// +property aout_p; + odd && + !start_in + |=> + a_out == $past(a_in); +endproperty + +aout_a : assert property(disable iff(!rst_n)aout_p); + + +////////////////////////////////////////// +// When its odd and no start then // +// m out takes the computed value // +////////////////////////////////////////// + +property mout_p; + odd && + !start_in + |=> + m_out == $past(m_out_func(s_in,a_in,b_in,n_prime_in)); +endproperty + +mout_a : assert property(disable iff(!rst_n) mout_p); + + +//////////////////////////////////////////////// +// When its even and no start then // +// a out takes the 2cyc previous a_in value // +//////////////////////////////////////////////// +property aout_even_p; + !start_in +##1 + !odd && + !start_in + |=> + a_out == $past(a_in,2); +endproperty + +aout_even_a : assert property(disable iff(!rst_n)aout_even_p); + + +////////////////////////////////////////// +// When its even and no start then // +// mout takes the previous mout value // +////////////////////////////////////////// +property mout_even_p; + !start_in + ##1 + !odd && + !start_in + |=> + m_out == $past(m_out_func($past(s_in),$past(a_in),b_in,n_prime_in),1); +endproperty + +mout_even_a : assert property(disable iff(!rst_n) mout_even_p); + + + +////////////////////////////////////////// +// When its odd and no start then // +// cout takes the computed value // +// from previous carry sum and computed m // +////////////////////////////////////////// +property cout_odd_p; +logic [RADIX :0] c0; +logic [RADIX-1:0] m_temp; +logic [RADIX-1:0] s0; + + odd && + !start_in + ##0 (1'b1, c0 = c_0(s_in,a_in,b_in)) + ##0 (1'b1, s0 = s_0(s_in,a_in,b_in)) + ##0 (1'b1, m_temp = m_temp_reg(s_in,a_in,b_in,n_prime_in)) + |=> + c_out == c_out_func(m_temp,p_in,c0,s0); +endproperty + +cout_odd_a : assert property(disable iff(!rst_n) cout_odd_p); + + + + +///////////////////////////////////////////// +// When its even and no start then // +// cout takes the computed value // +// from previous carry sum and computed m // +///////////////////////////////////////////// +property cout_even_p; +logic [RADIX :0] c0; +logic [RADIX-1:0] m_temp; +logic [RADIX-1:0] s0; + !start_in + ##1 + !odd && + !start_in + ##0 (1'b1, c0 = c_0($past(s_in),$past(a_in),b_in)) + ##0 (1'b1, s0 = s_0($past(s_in),$past(a_in),b_in)) + ##0 (1'b1, m_temp = m_temp_reg($past(s_in),$past(a_in),b_in,n_prime_in)) + |=> + c_out == c_out_func(m_temp,p_in,c0,s0); + +endproperty + +cout_even_a : assert property(disable iff(!rst_n) cout_even_p); + + + +endmodule + +bind ecc_pe_first fv_pe_first #(.RADIX(RADIX)) fv_pe_inst( + .clk(clk), + .rst_n(reset_n && !zeroize), + + .start_in(start_in), + .a_in(a_in), + .b_in(b_in), + .p_in(p_in), + .s_in(s_in), + .n_prime_in(n_prime_in), + + .odd(odd), + .a_out(a_out), + .m_out(m_out), + + .c_out(c_out) + ); \ No newline at end of file diff --git a/src/ecc/formal/properties/fv_scalar_blinding.sv b/src/ecc/formal/properties/fv_scalar_blinding.sv new file mode 100644 index 000000000..389f41d14 --- /dev/null +++ b/src/ecc/formal/properties/fv_scalar_blinding.sv @@ -0,0 +1,140 @@ + +// ------------------------------------------------- +// Contact: contact@lubis-eda.com +// Author: Tobias Ludwig, Michael Schwarz +// ------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +module fv_scalar_blind_m #( + parameter REG_SIZE = 384, + parameter RND_SIZE = 192, + parameter RADIX = 32 +)( + input bit rst_n, + input bit clk, + input bit unsigned [(RND_SIZE-1):0] rnd_i, + input bit unsigned [(REG_SIZE+RND_SIZE-1):0] data_o, + input bit unsigned [(REG_SIZE-1):0] data_i, + input logic [REG_SIZE-1:0] group_order, + input bit en_i, + input bit busy_o, + input bit input_read +); + +localparam SCA_DLY = 110; // The delay for computing the result + + + + +//Helper function for computation +function bit unsigned [(REG_SIZE+RND_SIZE-1):0] randomize(bit unsigned [(REG_SIZE-1):0] scalar, bit unsigned [(RND_SIZE-1):0] random, bit unsigned [REG_SIZE-1:0] grp_order); + return (REG_SIZE+RND_SIZE)'((scalar + (REG_SIZE+RND_SIZE)'(random * grp_order))); +endfunction + +default clocking default_clk @(posedge clk); endclocking + +sequence reset_sequence; + !rst_n ##1 rst_n; +endsequence + +//no enable until the busy stays deasserted +assume_enb: assume property (disable iff(!rst_n) + en_i + |=> + !en_i until_with (!busy_o) //check: no strong as it deasserts busy_o + ); + +//Input data is always less than group order +assume_scalr_less_group_order: assume property (disable iff(!rst_n) + data_i < group_order +); + + + + +//when reset busy_o and data_o is zero +reset_a: assert property (reset_p); +property reset_p; + $past(!rst_n) |-> + input_read && + data_o == '0 && + busy_o == 0 +;endproperty + + +//If not busy and en is set then the computation is carried out +input_read_to_input_read_a: assert property (disable iff(!rst_n) input_read_to_input_read_p); +property input_read_to_input_read_p; + logic [(REG_SIZE-1):0] scalar_store; + logic [(RND_SIZE-1):0] random_store; + logic [(REG_SIZE+RND_SIZE-1):0] temp; + + input_read && + en_i + ##0 (1'b1, scalar_store = data_i) + ##0 (1'b1, random_store = rnd_i) + ##0 (1'b1, temp = randomize(data_i,rnd_i,group_order)) +|-> + ##1 busy_o[*SCA_DLY] + ##1 (input_read && + data_o == temp && + busy_o == 0) +;endproperty + + + +// If not busy and not enabled then it stays in not busy +input_read_wait_a: assert property (disable iff(!rst_n) input_read_wait_p); +property input_read_wait_p; + input_read && + !en_i +|-> + ##1 + input_read && + busy_o == 0 +;endproperty + + +//If not busy and enabled then busy is set +input_read_next_a: assert property (disable iff(!rst_n) input_read_next_p); +property input_read_next_p; + input_read && + en_i +|-> + ##1 + !input_read && + busy_o == 1 +;endproperty + +endmodule + + + +bind ecc_scalar_blinding fv_scalar_blind_m #( + .REG_SIZE(REG_SIZE), + .RND_SIZE(RND_SIZE), + .RADIX(RADIX) + )fv_scalar_blind( + .rst_n(ecc_scalar_blinding.reset_n && !ecc_scalar_blinding.zeroize), + .clk(ecc_scalar_blinding.clk), + .rnd_i(ecc_scalar_blinding.rnd_i), + .data_o(ecc_scalar_blinding.data_o), + .data_i(ecc_scalar_blinding.data_i), + .en_i(ecc_scalar_blinding.en_i), + .busy_o(ecc_scalar_blinding.busy_o), + .input_read(!ecc_scalar_blinding.busy_o), + .group_order(ecc_scalar_blinding.GROUP_ORDER) + +); diff --git a/src/ecc/formal/readme.md b/src/ecc/formal/readme.md new file mode 100644 index 000000000..cdba90718 --- /dev/null +++ b/src/ecc/formal/readme.md @@ -0,0 +1,80 @@ +# Reproduce results + +**MACROS :** +TOP + +- Used for the submodules fv_ecc_fau.sv and fv_scalar_blinding.sv and in fv_ecc_dsa_ctrl_constraints.sv. + +- Use this macro or define this macro only when loading the design the with ecc_dsa_ctrl as top module. + +FOR48 + +- This macro is used for fv_montmultiplier.sv as the montgomery multiplier shorter version end-to-end checkers. Due to the restriction of the formal tool overmultiplication this file is used for only reduced version of the design. Further details are in the ECC_block_overview. + +## Proving the submodules + +- Load submodule as top in the formal tool. + +- Load the checker files along with the constraints and respective packages in the formal tool. + +- Run the properties. + +## Proving the top + +- Load all design files in the formal tool and set ecc_dsa_ctrl as top module, disable the proofs as mentioned in the sheet which are not for the top. + +- Load all the checker files with respective macro defined along with the constraints and respective packages in the formal tool. + +- Copy all the submodule assertions and assumptions and enable if they were disabled into seperate task and cut the signals from the top that affect the submodule verification. + + If the following modules are chossen as a task then the respective signals need to be cut. + + + # ecc_add_sub_mod_alter + + - cut the signals add_en_i, sub_i + + # ecc_pm_sequencer + + - cut the signal addra + + # ecc_dsa_sequencer + + - cut the signal addra + + # ecc_pm_sequencer + + - cut the signal addra + + # ecc_ram_tdp_file + + - cut the signals wea,web,ena,enb + + # ecc_pm_ctrl + + - cut the signal ecc_cmd_i + + # ecc_hmac_drbg_interface + + - cut the signal counter_nonce, keygen_sign, hmac_drbg_i.drbg, hmac_drbg_i.ready,hmac_drbg_i.valid, internal signal counter_nonce. Constraints do the work by reducing the timing. + + # hmac_drbg + + - cut the signals init_cmd,next_cmd,nonce, entropy,u_sha512_core_h1.digest, + u_sha512_core_h2.digest,HMAC_K.tag,hmac_drbg_lfsr.rnd + + # sha512_masked + + - cut the signals init_cmd,next_cmd,mode,block_msg,sha_masked_lfsr.rnd + + # reduced versions + - For montgomerymultiplier, scalar_blinding and ecc_pe_first modules, a reduced + version instantiations are created inside the module ecc_reduced_instatiations, these proofs could be created in a separate task as they are not part of the actual top design and these proofs should be disabled on the top. + +- On the main task, disable all submodule assumptions(convert to assertions) and just keep the assumptions on the ecc_dsa_ctrl module. + +- Run the properties on the main task . + +- Switch the tasks to one of the submodules which consists of the assumptions and assertions of that particular submodule. + +- Run the properties.