| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| // The sequence accesses secret info regions after randomize lc_ctrl inputs. |
| // lc_ctrl_inputs: |
| // .lc_creator_seed_sw_rw_en_i |
| // .lc_owner_seed_sw_rw_en_i |
| // .lc_iso_part_sw_rd_en_i |
| // .lc_iso_part_sw_wr_en_i |
| class flash_ctrl_info_part_access_vseq extends flash_ctrl_hw_sec_otp_vseq; |
| `uvm_object_utils(flash_ctrl_info_part_access_vseq) |
| `uvm_object_new |
| |
| typedef enum { |
| AccessTest, |
| ReadOnlyTest, |
| WriteOnlyTest |
| } test_type_e; |
| int round = 0; |
| |
| task hw_info_cfg_update(); |
| // Randomize hw_info_cfg_override |
| cfg.ovrd_scr_dis = get_rand_mubi4_val(.t_weight(2), .f_weight(1), .other_weight(1)); |
| cfg.ovrd_ecc_dis = get_rand_mubi4_val(.t_weight(2), .f_weight(1), .other_weight(1)); |
| ral.hw_info_cfg_override.scramble_dis.set(cfg.ovrd_scr_dis); |
| ral.hw_info_cfg_override.ecc_dis.set(cfg.ovrd_ecc_dis); |
| csr_update(ral.hw_info_cfg_override); |
| endtask // hw_info_cfg_update |
| |
| virtual task body(); |
| // INITIALIZE FLASH REGIONS |
| // All on to configure secret info_page_cfg |
| all_sw_rw_en(); |
| init_sec_info_part(); |
| $assertoff(0, "prim_lc_sync"); |
| cfg.seq_cfg.check_mem_post_tran = 1; |
| |
| repeat (10) begin |
| `uvm_info(`gfn, $sformatf("iter:%0d", round++), UVM_LOW) |
| |
| check_lc_ctrl(cfg.flash_ctrl_vif.lc_creator_seed_sw_rw_en, FlashCreatorPart); |
| check_lc_ctrl(cfg.flash_ctrl_vif.lc_owner_seed_sw_rw_en, FlashOwnerPart); |
| |
| randcase |
| 1: check_lc_ctrl(cfg.flash_ctrl_vif.lc_iso_part_sw_wr_en, FlashIsolPart, WriteOnlyTest); |
| 1: check_lc_ctrl(cfg.flash_ctrl_vif.lc_iso_part_sw_rd_en, FlashIsolPart, ReadOnlyTest); |
| endcase // randcase |
| |
| // Drain between iteration |
| #1us; |
| end // repeat (10) |
| endtask // body |
| |
| task check_lc_ctrl(ref lc_ctrl_pkg::lc_tx_t sig, input flash_sec_part_e part, |
| test_type_e test = AccessTest); |
| flash_op_e flash_op; |
| bit is_valid; |
| `uvm_info(`gfn, $sformatf("iter%0d:info:%s test:%s begin", |
| round, part.name, test.name), UVM_HIGH) |
| if (test == AccessTest) begin |
| `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(flash_op, |
| flash_op != FlashOpInvalid;) |
| end else if (test == ReadOnlyTest) begin |
| `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(flash_op, |
| flash_op == FlashOpRead;) |
| end else begin |
| `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(flash_op, |
| flash_op inside {FlashOpProgram, FlashOpErase};) |
| end |
| |
| sig = get_rand_lc_tx_val(.t_weight(1), .f_weight(1), .other_weight(8)); |
| is_valid = is_lc_ctrl_valid(sig); |
| cfg.clk_rst_vif.wait_clks(4); |
| `uvm_info(`gfn, $sformatf("Check sig:0x%x(is_valid:%0d) part:%s op:%s testtype:%s", |
| sig, is_valid, part.name, flash_op.name, test.name), UVM_LOW) |
| |
| do_flash_op_info_part(part, flash_op, is_valid); |
| endtask // check_lc_ctrl |
| |
| // Task to access secret info partition. |
| // lc control should be set from the exernal task. |
| task do_flash_op_info_part(flash_sec_part_e part, flash_op_e op, bit is_valid); |
| data_q_t flash_op_data; |
| flash_op_t flash_op; |
| bit scr_en; |
| |
| flash_op.op = op; |
| flash_op.erase_type = FlashErasePage; |
| |
| case (part) |
| FlashCreatorPart: begin |
| flash_op.addr = FlashCreatorPartStartAddr; // Fixed Val |
| flash_op.num_words = FullPageNumWords; // Fixed Val |
| flash_op.partition = FlashPartInfo; |
| end |
| FlashOwnerPart: begin |
| flash_op.addr = FlashOwnerPartStartAddr; // Fixed Val |
| flash_op.num_words = FullPageNumWords; // Fixed Val |
| flash_op.partition = FlashPartInfo; |
| end |
| FlashIsolPart: begin |
| flash_op.addr = FlashIsolPartStartAddr; // Fixed Val |
| flash_op.num_words = FullPageNumWords; // Fixed Val |
| flash_op.partition = FlashPartInfo; |
| end |
| default: `uvm_error(`gfn, $sformatf("%s partition is not supported in this task", |
| part.name)) |
| endcase |
| |
| flash_op_data = '{}; |
| `uvm_info(`gfn, $sformatf("iter%0d:info:%s is_valid:%0b op:%p", |
| round, part.name, is_valid, flash_op), UVM_MEDIUM) |
| if (part == FlashIsolPart) begin |
| scr_en = 1; |
| end else begin |
| scr_en = ((flash_ctrl_pkg::CfgAllowRead.scramble_en == MuBi4True) && |
| (mubi4_t'(~cfg.ovrd_scr_dis) == MuBi4True)); |
| end |
| case (op) |
| FlashOpErase: begin |
| if (!is_valid) set_otf_exp_alert("recov_err"); |
| cfg.flash_mem_bkdr_init(flash_op.partition, FlashMemInitRandomize); |
| flash_ctrl_start_op(flash_op); |
| wait_flash_op_done(.timeout_ns(cfg.seq_cfg.erase_timeout_ns)); |
| cfg.flash_mem_bkdr_erase_check(.flash_op(flash_op), .check_match(is_valid)); |
| end |
| FlashOpProgram: begin |
| for (int i = 0; i < flash_op.num_words; i++) begin |
| flash_op_data[i] = $urandom_range(0, 2 ** (TL_DW) - 1); |
| end |
| if (!is_valid) begin |
| repeat(32) set_otf_exp_alert("recov_err"); |
| end |
| // This task issues flash_ctrl.control write 32 times |
| cfg.flash_mem_bkdr_init(flash_op.partition, FlashMemInitSet); |
| flash_ctrl_write_extra(flash_op, flash_op_data, is_valid, scr_en); |
| end |
| FlashOpRead: begin |
| if (!is_valid) set_otf_exp_alert("recov_err"); |
| |
| if (scr_en) begin |
| // scramble secret partition |
| update_secret_partition(); |
| end else begin |
| cfg.flash_mem_bkdr_write(.flash_op(flash_op), .scheme(FlashMemInitRandomize)); |
| end |
| flash_ctrl_start_op(flash_op); |
| flash_ctrl_read(flash_op.num_words, flash_op_data, 1); |
| wait_flash_op_done(); |
| cfg.flash_mem_bkdr_read_check(flash_op, flash_op_data, is_valid, scr_en); |
| end |
| default: `uvm_error(`gfn, $sformatf("%s op is not supported in this task", |
| op.name)) |
| endcase |
| endtask |
| |
| task init_sec_info_part(); |
| flash_bank_mp_info_page_cfg_t info_regions = '{default: MuBi4True}; |
| for (int i = 1; i < 4; i++) begin |
| if (i < 3) begin |
| info_regions.scramble_en = prim_mubi_pkg::mubi4_and_hi( |
| flash_ctrl_pkg::CfgAllowRead.scramble_en, |
| mubi4_t'(~cfg.ovrd_scr_dis)); |
| info_regions.ecc_en = prim_mubi_pkg::mubi4_and_hi( |
| flash_ctrl_pkg::CfgAllowRead.ecc_en, |
| mubi4_t'(~cfg.ovrd_ecc_dis)); |
| end else begin |
| info_regions.scramble_en = flash_ctrl_pkg::CfgAllowRead.scramble_en; |
| info_regions.ecc_en = flash_ctrl_pkg::CfgAllowRead.ecc_en; |
| end |
| flash_ctrl_mp_info_page_cfg(0, 0, i, info_regions); |
| end |
| endtask // init_info_part |
| endclass // flash_ctrl_info_part_access_vseq |