From ba30646a15f6308e2add218cb1413d558c0f0cc6 Mon Sep 17 00:00:00 2001 From: Rohith Babu Batthineni Date: Fri, 24 Nov 2023 11:00:38 +0100 Subject: [PATCH] Added formal folder with readme and pdf --- src/ecc/formal/fv_ecc_block_overview.pdf | Bin 0 -> 225361 bytes .../fv_add_sub_alter_coverpoints.sv | 45 + .../coverpoints/fv_arith_unit_coverpoints.sv | 86 + .../fv_ecc_dsa_ctrl_coverpoints.sv | 130 + ...fv_ecc_montgomerymultiplier_coverpoints.sv | 49 + .../fv_ecc_pm_ctrl_coverpoints_m.sv | 145 + .../properties/ecc_reduced_instantiations.sv | 117 + src/ecc/formal/properties/fv_add_sub_alter.sv | 138 + .../properties/fv_add_sub_constraints.sv | 70 + .../properties/fv_dsa_ctrl_constraints.sv | 204 ++ .../formal/properties/fv_ecc_arith_unit.sv | 263 ++ src/ecc/formal/properties/fv_ecc_dsa_ctrl.sv | 1428 ++++++++ .../formal/properties/fv_ecc_dsa_sequencer.sv | 355 ++ src/ecc/formal/properties/fv_ecc_fau.sv | 167 + .../properties/fv_ecc_hmac_drbg_interface.sv | 547 +++ .../fv_ecc_hmac_drbg_interface_constraints.sv | 113 + .../properties/fv_ecc_pm_ctrl_abstract.sv | 1101 ++++++ .../formal/properties/fv_ecc_pm_sequencer.sv | 3065 +++++++++++++++++ .../formal/properties/fv_ecc_ram_tdp_file.sv | 210 ++ .../formal/properties/fv_montmultiplier.sv | 269 ++ .../properties/fv_montmultiplier_glue.sv | 252 ++ src/ecc/formal/properties/fv_pe.sv | 218 ++ src/ecc/formal/properties/fv_pe_final.sv | 126 + src/ecc/formal/properties/fv_pe_first.sv | 275 ++ .../formal/properties/fv_scalar_blinding.sv | 140 + src/ecc/formal/readme.md | 80 + 26 files changed, 9593 insertions(+) create mode 100644 src/ecc/formal/fv_ecc_block_overview.pdf create mode 100644 src/ecc/formal/properties/coverpoints/fv_add_sub_alter_coverpoints.sv create mode 100644 src/ecc/formal/properties/coverpoints/fv_arith_unit_coverpoints.sv create mode 100644 src/ecc/formal/properties/coverpoints/fv_ecc_dsa_ctrl_coverpoints.sv create mode 100644 src/ecc/formal/properties/coverpoints/fv_ecc_montgomerymultiplier_coverpoints.sv create mode 100644 src/ecc/formal/properties/coverpoints/fv_ecc_pm_ctrl_coverpoints_m.sv create mode 100644 src/ecc/formal/properties/ecc_reduced_instantiations.sv create mode 100644 src/ecc/formal/properties/fv_add_sub_alter.sv create mode 100644 src/ecc/formal/properties/fv_add_sub_constraints.sv create mode 100644 src/ecc/formal/properties/fv_dsa_ctrl_constraints.sv create mode 100644 src/ecc/formal/properties/fv_ecc_arith_unit.sv create mode 100644 src/ecc/formal/properties/fv_ecc_dsa_ctrl.sv create mode 100644 src/ecc/formal/properties/fv_ecc_dsa_sequencer.sv create mode 100644 src/ecc/formal/properties/fv_ecc_fau.sv create mode 100644 src/ecc/formal/properties/fv_ecc_hmac_drbg_interface.sv create mode 100644 src/ecc/formal/properties/fv_ecc_hmac_drbg_interface_constraints.sv create mode 100644 src/ecc/formal/properties/fv_ecc_pm_ctrl_abstract.sv create mode 100644 src/ecc/formal/properties/fv_ecc_pm_sequencer.sv create mode 100644 src/ecc/formal/properties/fv_ecc_ram_tdp_file.sv create mode 100644 src/ecc/formal/properties/fv_montmultiplier.sv create mode 100644 src/ecc/formal/properties/fv_montmultiplier_glue.sv create mode 100644 src/ecc/formal/properties/fv_pe.sv create mode 100644 src/ecc/formal/properties/fv_pe_final.sv create mode 100644 src/ecc/formal/properties/fv_pe_first.sv create mode 100644 src/ecc/formal/properties/fv_scalar_blinding.sv create mode 100644 src/ecc/formal/readme.md 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 0000000000000000000000000000000000000000..5454274fde7c0ec3dcbda6c1f3fd9581a0670b70 GIT binary patch literal 225361 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 literal 0 HcmV?d00001 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.