From aa1ad6e1b2b514395ed6ed0ccca0cc62c815c262 Mon Sep 17 00:00:00 2001 From: Mahmud Hassan Date: Tue, 25 Jul 2023 00:48:06 +0000 Subject: [PATCH] Merged PR 117045: AHB 32->64 bit modification in soc_ifc_tb environment, and cptra_noncore_rst_b related fixes 1. Updated dut in soc_ifc_tb to 64-bit AHB and changed test routines accordingly. 2. Failures in registers related to cptra_noncore_rst_b timing and fields (eg CPTRA_FLOW_STATUS) Related work items: #515252, #518074 --- src/soc_ifc/tb/fuse_reg_pauser_test.svh | 49 +++++- src/soc_ifc/tb/rvtime_reg_test.svh | 6 +- src/soc_ifc/tb/sha_acc_intrblk_test.svh | 4 +- src/soc_ifc/tb/single_soc_reg_test.svh | 3 +- src/soc_ifc/tb/soc_ifc_tb.sv | 210 ++++++++++++++---------- src/soc_ifc/tb/soc_ifc_tb_pkg.sv | 45 +++-- src/soc_ifc/tb/soc_reg_intrblk_test.svh | 4 +- src/soc_ifc/tb/soc_reg_invalid_test.svh | 18 +- src/soc_ifc/tb/soc_reg_reset_test.svh | 197 +++++++++++++--------- src/soc_ifc/tb/soc_reg_test.svh | 2 +- 10 files changed, 329 insertions(+), 209 deletions(-) diff --git a/src/soc_ifc/tb/fuse_reg_pauser_test.svh b/src/soc_ifc/tb/fuse_reg_pauser_test.svh index 216017d99..093fb401f 100644 --- a/src/soc_ifc/tb/fuse_reg_pauser_test.svh +++ b/src/soc_ifc/tb/fuse_reg_pauser_test.svh @@ -16,7 +16,6 @@ `define FORLOOP_COMB(x) always_comb for (int j = 0; j < x; j++) -`define REG_HIER_PFX dut.i_soc_ifc_reg.field_storage `define STR_RMPFX(astr, bstr) astr.substr(bstr.len(), astr.len() - 1).atoi() @@ -88,14 +87,18 @@ task fuse_reg_pauser_test; print_banner("1a. Default pauser and unlocked. APB write to registers, check values"); tphase = "1a"; - write_regs(SET_APB, fuse_regnames, tid, 3); // effect changes & expec same values on read + write_regs(SET_APB, fuse_regnames, tid, 3); // effect changes & repeat (5) @(posedge clk_tb); - read_regs(GET_APB, fuse_regnames, tid, 3); + read_regs(GET_APB, fuse_regnames, tid, 3); // expect same values on read //------------------------------------------------------------------------------------------- print_banner("1b. With unlocked non-default pauser, repeat 1a"); tphase = "1b"; + // NOTE. simulate_caliptra_boot() is necessary for noncore_rst_b to be deasserted + simulate_caliptra_boot(); + wait (cptra_noncore_rst_b_tb == 1'b1); + // Set pauser valid to non-default wrtrans.update_byname("CPTRA_FUSE_VALID_PAUSER", 0, tid); wrtrans.randomize(); @@ -110,9 +113,9 @@ task fuse_reg_pauser_test; error_ctr += 1; end - write_regs(SET_APB, fuse_regnames, tid, 3); // effect changes + write_regs(SET_APB, fuse_regnames, tid, 3); // effect changes & repeat (5) @(posedge clk_tb); - read_regs(GET_APB, fuse_regnames, tid, 3); + read_regs(GET_APB, fuse_regnames, tid, 3); // expect same values on read //------------------------------------------------------------------------------------------- print_banner("1c. Lock pauser with non-default value. repeat 1a but read with and w/o valid pauser"); @@ -142,7 +145,7 @@ task fuse_reg_pauser_test; fuse_regval_actual = get_fuse_regval(rname); read_reg_chk_inrange(GET_APB, rname, tid, '0, '0); // get 0's on default pauser repeat (3) @(posedge clk_tb); - read_reg_trans(GET_APB, rdtrans, valid_pauser); + read_reg_trans(GET_APB, rdtrans, valid_pauser); // expect older (stored) values repeat (3) @(posedge clk_tb); if (str_startswith(rname, "FUSE_UDS_SEED") || str_startswith(rname, "FUSE_FIELD_ENTROPY")) @@ -162,7 +165,17 @@ task fuse_reg_pauser_test; print_banner("1d. With matching locked non-default pauser, repeat 1a"); tphase = "1d"; - sb.del_all(); // Fresh scoreboard start (except for errors) + // Programming a non-default valid_pauser and locking it requires waiting for cptra_noncore_rst_b + // to be deasserted after a reset, ie, Caliptra boot. + // + // At the same time ready_for_fuses drops low followed by cptra_noncore_rst_b goingh high, ergo + // writes to fuse regs no longer work (for any pauser value) until a warm reset occurs. + // HOWEVER, a warm reset also resets the valid_pauser register. + // + // The net result (a bug) is that fuse registers can ONLY be written using a default pauser value; + // fuse registers can be read out though using any programmed and locked valid_pauser. + + sb.del_all(); foreach (fuse_regnames[i]) begin rname = fuse_regnames[i]; @@ -179,8 +192,8 @@ task fuse_reg_pauser_test; continue; if (rdtrans.data != (get_mask(rname) & wrtrans.data)) begin - $display("TB ERROR. Mismatch on APB write and read w/valid pauser for reg %-30s (0x%08x). Masked Write value = 0x%08x | expected Read value = 0x%08x", - rname, rdtrans.addr, get_mask(rname) & wrtrans.data, rdtrans.data); + $display("TB ERROR. Mismatch on APB write and read w/valid pauser for reg %-30s (0x%08x). Read value = 0x%08x | expected value = 0x%08x", + rname, rdtrans.addr, rdtrans.data, get_mask(rname) & wrtrans.data); error_ctr += 1; end @@ -207,6 +220,15 @@ task fuse_reg_pauser_test; reset_exp_data(); sb.del_all(); + simulate_caliptra_boot(); + wait (cptra_noncore_rst_b_tb == 1'b1); + + // if (cptra_noncore_rst_b_tb == 1'b0) begin + // $display("TB. WARNING Non core reset is not deasserted. Waiting 1000 cycles"); + // repeat (1000) @(posedge clk_tb); + // $display("TB. DEBUG if status of cptra_noncore_rst_b_tb = 1'b%b", cptra_noncore_rst_b_tb); + // end + read_reg_chk_inrange(GET_APB, "CPTRA_FUSE_PAUSER_LOCK", tid, '0, '0); @(posedge clk_tb); @@ -220,6 +242,15 @@ task fuse_reg_pauser_test; // simulate_caliptra_boot(); sb.del_all(); + simulate_caliptra_boot(); + wait (cptra_noncore_rst_b_tb == 1'b1); + + // if (cptra_noncore_rst_b_tb == 1'b0) begin + // $display("TB. WARNING Non core reset is not deasserted. Waiting 1000 cycles"); + // repeat (1000) @(posedge clk_tb); + // $display("TB. DEBUG if status of cptra_noncore_rst_b_tb = 1'b%b", cptra_noncore_rst_b_tb); + // end + read_reg_chk_inrange(GET_APB, "CPTRA_FUSE_PAUSER_LOCK", tid, '0, '0); @(posedge clk_tb); diff --git a/src/soc_ifc/tb/rvtime_reg_test.svh b/src/soc_ifc/tb/rvtime_reg_test.svh index cec5e4ee9..d2857fe88 100644 --- a/src/soc_ifc/tb/rvtime_reg_test.svh +++ b/src/soc_ifc/tb/rvtime_reg_test.svh @@ -67,7 +67,7 @@ sb.del_all(); error_ctr = 0; - update_CPTRA_FLOW_STATUS(ready_for_fuses); + update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); $display ("\n-------------------------------------------------------------"); @@ -203,7 +203,7 @@ wait (ready_for_fuses == 1'b1); // Some registers need update for specific fields - flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses); + flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); reset_reason = update_CPTRA_RESET_REASON(1, 0); // expect old sticky values which are different from power-on values @@ -228,7 +228,7 @@ wait (ready_for_fuses == 1'b1); // Some registers need update for specific fields - flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses); + flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); reset_reason = update_CPTRA_RESET_REASON(1, 0); // expect old sticky values which are different from power-on values diff --git a/src/soc_ifc/tb/sha_acc_intrblk_test.svh b/src/soc_ifc/tb/sha_acc_intrblk_test.svh index cc6cfd4fb..84a39a9f4 100644 --- a/src/soc_ifc/tb/sha_acc_intrblk_test.svh +++ b/src/soc_ifc/tb/sha_acc_intrblk_test.svh @@ -75,7 +75,7 @@ $display("Executing task sha_acc_intrblk_test"); $display("---------------------------------\n"); - set_security_state('{device_lifecycle: DEVICE_PRODUCTION, debug_locked: DEBUG_UNLOCKED}); + // set_security_state_byname("DEBUG_UNLOCKED_PRODCUTION"); tc_ctr = tc_ctr + 1; wrtrans = new(); @@ -95,7 +95,7 @@ repeat (20) @(posedge clk_tb); sb.del_all(); - update_CPTRA_FLOW_STATUS(ready_for_fuses); + update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); $display ("\n1a. Writing over AHB, APB then reading back over APB"); diff --git a/src/soc_ifc/tb/single_soc_reg_test.svh b/src/soc_ifc/tb/single_soc_reg_test.svh index 1bdf1c1dd..d66a67338 100644 --- a/src/soc_ifc/tb/single_soc_reg_test.svh +++ b/src/soc_ifc/tb/single_soc_reg_test.svh @@ -62,7 +62,8 @@ simulate_caliptra_boot(); repeat (20) @(posedge clk_tb); sb.del_all(); - update_CPTRA_FLOW_STATUS(ready_for_fuses); + update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); + end diff --git a/src/soc_ifc/tb/soc_ifc_tb.sv b/src/soc_ifc/tb/soc_ifc_tb.sv index 99a6b1370..f78a9190c 100644 --- a/src/soc_ifc/tb/soc_ifc_tb.sv +++ b/src/soc_ifc/tb/soc_ifc_tb.sv @@ -25,6 +25,12 @@ import "DPI-C" function string getenv(input string env_name); +`define AHB64_HI 63:32 +`define AHB64_LO 31:0 + +`define REG_HIER_BOOT_FSM_PS dut.boot_fsm_ps +`define REG_HIER_PFX dut.i_soc_ifc_reg.field_storage + module soc_ifc_tb import soc_ifc_pkg::*; import soc_ifc_tb_pkg::*; @@ -41,6 +47,7 @@ module soc_ifc_tb string tphase; + //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- @@ -67,11 +74,11 @@ module soc_ifc_tb parameter MBOX_FE_ADDR = 32'h3003_0230; parameter MBOX_FUSE_DONE_ADDR = 32'h3003_00ac; - parameter AHB_ADDR_WIDTH = 18; // `CALIPTRA_SLAVE_ADDR_WIDTH(`CALIPTRA_SLAVE_SEL_SOC_IFC); // 18 - parameter AHB_DATA_WIDTH = 32; // `CALIPTRA_AHB_HDATA_SIZE; // 32 - parameter APB_ADDR_WIDTH = 18; // `CALIPTRA_SLAVE_ADDR_WIDTH(`CALIPTRA_SLAVE_SEL_SOC_IFC); // 18 - parameter APB_DATA_WIDTH = 32; // `CALIPTRA_APB_DATA_WIDTH; // 32 - parameter APB_USER_WIDTH = 32; // `CALIPTRA_APB_USER_WIDTH; // 32 + parameter AHB_ADDR_WIDTH = `CALIPTRA_SLAVE_ADDR_WIDTH(`CALIPTRA_SLAVE_SEL_SOC_IFC); // 18 + parameter AHB_DATA_WIDTH = `CALIPTRA_AHB_HDATA_SIZE; // 32 + parameter APB_ADDR_WIDTH = `CALIPTRA_SLAVE_ADDR_WIDTH(`CALIPTRA_SLAVE_SEL_SOC_IFC); // 18 + parameter APB_DATA_WIDTH = `CALIPTRA_APB_DATA_WIDTH; // 32 + parameter APB_USER_WIDTH = `CALIPTRA_APB_USER_WIDTH; // 32 parameter AHB_HTRANS_IDLE = 0; @@ -81,6 +88,7 @@ module soc_ifc_tb localparam PAUSER_DEFAULT = 32'hffff_ffff; + //---------------------------------------------------------------- // Register and Wire declarations. //---------------------------------------------------------------- @@ -182,11 +190,11 @@ module soc_ifc_tb // Device Under Test. //---------------------------------------------------------------- soc_ifc_top #( - .AHB_DATA_WIDTH(AHB_DATA_WIDTH), // .AHB_DATA_WIDTH(32), - .AHB_ADDR_WIDTH(AHB_ADDR_WIDTH), // .AHB_ADDR_WIDTH(18), - .APB_USER_WIDTH(APB_USER_WIDTH), // .APB_USER_WIDTH(32), - .APB_ADDR_WIDTH(APB_ADDR_WIDTH), // .APB_ADDR_WIDTH(18), - .APB_DATA_WIDTH(APB_DATA_WIDTH) // .APB_DATA_WIDTH(32) + .AHB_DATA_WIDTH(AHB_DATA_WIDTH), + .AHB_ADDR_WIDTH(AHB_ADDR_WIDTH), + .APB_USER_WIDTH(APB_USER_WIDTH), + .APB_ADDR_WIDTH(APB_ADDR_WIDTH), + .APB_DATA_WIDTH(APB_DATA_WIDTH) ) dut ( .clk(clk_tb), @@ -295,6 +303,7 @@ module soc_ifc_tb ); + // Other special and aggregate data type instantiations struct { string reg_name; WordTransaction wr_trans; @@ -367,13 +376,11 @@ module soc_ifc_tb //---------------------------------------------------------------- always @(posedge clk_tb or negedge cptra_rst_b_tb) begin : generic_input_detector if (!cptra_rst_b_tb) begin - // gen_input_wire_toggle <= 1'b1; - generic_input_wires0_q <= 32'b0; - generic_input_wires0_q <= 32'b0; - end else begin - // gen_input_wire_toggle <= 1'b1; - generic_input_wires0_q <= generic_input_wires0; - generic_input_wires1_q <= generic_input_wires1; + generic_input_wires0_q <= '0; + generic_input_wires1_q <= '0; + end else begin + generic_input_wires0_q <= cptra_noncore_rst_b_tb ? generic_input_wires0 : generic_input_wires0_q; + generic_input_wires1_q <= cptra_noncore_rst_b_tb ? generic_input_wires1 : generic_input_wires1_q; end end @@ -408,13 +415,13 @@ module soc_ifc_tb // CPTRA SECUIRTY_STATE, FLOW_STATUS, GENERIC_INPUT_WIRES //---------------------------------------------------------------- - always_comb begin - update_CPTRA_SECURITY_STATE(scan_mode_f, security_state.debug_locked, security_state.device_lifecycle); - update_CPTRA_FLOW_STATUS(ready_for_fuses); - update_CPTRA_GENERIC_INPUT_WIRES(generic_input_wires1, generic_input_wires0); - update_INTR_BRF_NOTIF_INTERNAL_INTR_R(gen_input_wire_toggle, security_state.debug_locked); + always_comb update_CPTRA_SECURITY_STATE(scan_mode_f, security_state.debug_locked, security_state.device_lifecycle); + always_comb update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); + always_comb update_CPTRA_GENERIC_INPUT_WIRES(generic_input_wires1_q, 1'b1); + always_comb update_CPTRA_GENERIC_INPUT_WIRES(generic_input_wires0_q, 1'b0); + always_comb update_INTR_BRF_NOTIF_INTERNAL_INTR_R(gen_input_wire_toggle, security_state.debug_locked); + - end //---------------------------------------------------------------- // reset_dut() @@ -568,6 +575,7 @@ module soc_ifc_tb //---------------------------------------------------------------- task write_single_word_ahb(input [31 : 0] address, input [31 : 0] word); + begin hsel_i_tb <= 1; haddr_i_tb <= address; @@ -577,7 +585,7 @@ module soc_ifc_tb @(posedge clk_tb); haddr_i_tb <= 'Z; - hwdata_i_tb <= word; + hwdata_i_tb <= address[2] ? {word, 32'h0}: {32'h0, word}; hwrite_i_tb <= 0; htrans_i_tb <= AHB_HTRANS_IDLE; wait(hreadyout_o_tb == 1'b1); @@ -755,13 +763,13 @@ module soc_ifc_tb begin read_single_word_ahb(MBOX_ADDR_DATAOUT); - r_data[127 : 96] = hrdata_o_tb; + r_data[127 : 96] = MBOX_ADDR_DATAOUT[2] ? hrdata_o_tb[`AHB64_HI] : hrdata_o_tb[`AHB64_LO]; read_single_word_ahb(MBOX_ADDR_DATAOUT); - r_data[95 : 64] = hrdata_o_tb; + r_data[95 : 64] = MBOX_ADDR_DATAOUT[2] ? hrdata_o_tb[`AHB64_HI] : hrdata_o_tb[`AHB64_LO]; read_single_word_ahb(MBOX_ADDR_DATAOUT); - r_data[63 : 32] = hrdata_o_tb; + r_data[63 : 32] = MBOX_ADDR_DATAOUT[2] ? hrdata_o_tb[`AHB64_HI] : hrdata_o_tb[`AHB64_LO]; read_single_word_ahb(MBOX_ADDR_DATAOUT); - r_data[31 : 0] = hrdata_o_tb; + r_data[31 : 0] = MBOX_ADDR_DATAOUT[2] ? hrdata_o_tb[`AHB64_HI] : hrdata_o_tb[`AHB64_LO]; end endtask // read_result_ahb @@ -791,11 +799,16 @@ module soc_ifc_tb // wait for the mailbox to unlock before send in anything //---------------------------------------------------------------- task wait_unlock_ahb; + + automatic logic [31:0] valid_hrdata; + begin read_single_word_ahb(MBOX_ADDR_LOCK); - while (hrdata_o_tb != 0) + valid_hrdata = MBOX_ADDR_LOCK[2] ? hrdata_o_tb[`AHB64_HI] :hrdata_o_tb[`AHB64_LO]; + while (valid_hrdata != 0) begin read_single_word_ahb(MBOX_ADDR_LOCK); + valid_hrdata = MBOX_ADDR_LOCK[2] ? hrdata_o_tb[`AHB64_HI] :hrdata_o_tb[`AHB64_LO]; end end endtask // wait_unlock_ahb @@ -816,43 +829,6 @@ module soc_ifc_tb endtask // wait_unlock_apb - //---------------------------------------------------------------- - // set_security_state() - // - // sets the security state explicily to any valid value - //---------------------------------------------------------------- - task set_security_state(input security_state_t ss); - // TODO. Has hardwired mask bit positions in here. Ideally they should be pulled from tb package. - - dword_t intr_notif_val; - - begin - security_state = '{device_lifecycle: ss.device_lifecycle, debug_locked: ss.debug_locked}; - - set_initval("CPTRA_SECURITY_STATE", ss & 32'h7); - update_exp_regval("CPTRA_SECURITY_STATE", ss & 32'h7, SET_DIRECT); - - - intr_notif_val = get_initval("INTR_BRF_NOTIF_INTERNAL_INTR_R") & 32'hffff_fffb | ss.debug_locked & 32'h4; - set_initval("INTR_BRF_NOTIF_INTERNAL_INTR_R", intr_notif_val); - update_exp_regval("INTR_BRF_NOTIF_INTERNAL_INTR_R", intr_notif_val, SET_DIRECT); - end - endtask // set_security_state - - - //---------------------------------------------------------------- - // set_security_state_random() - // - // convenience function to set the security state to random - //---------------------------------------------------------------- - task set_security_state_random; - - automatic int ss_code = $urandom_range(0, 7); - ss_code = $urandom_range(0, 7); - set_security_state(security_state_t'(ss_code)); - - endtask // set_security_state_random - //---------------------------------------------------------------- // reset_generic_input_wires() @@ -864,10 +840,11 @@ module soc_ifc_tb begin generic_input_wires0 = (v0 < 0) ? $urandom() : v0; generic_input_wires1 = (v1 < 0) ? $urandom() : v1; - set_initval("CPTRA_GENERIC_INPUT_WIRES0", generic_input_wires0); - set_initval("CPTRA_GENERIC_INPUT_WIRES1", generic_input_wires1); - update_exp_regval("CPTRA_GENERIC_INPUT_WIRES0", generic_input_wires0, SET_DIRECT); - update_exp_regval("CPTRA_GENERIC_INPUT_WIRES1", generic_input_wires1, SET_DIRECT); + repeat (2) @(posedge clk_tb); + set_initval("CPTRA_GENERIC_INPUT_WIRES0", generic_input_wires0_q); + set_initval("CPTRA_GENERIC_INPUT_WIRES1", generic_input_wires1_q); + update_CPTRA_GENERIC_INPUT_WIRES(generic_input_wires0_q, 1'b0); + update_CPTRA_GENERIC_INPUT_WIRES(generic_input_wires1_q, 1'b1); @(posedge clk_tb); end @@ -884,7 +861,7 @@ module soc_ifc_tb begin set_initval("CPTRA_FLOW_STATUS", '0); - update_CPTRA_FLOW_STATUS('0); + update_CPTRA_FLOW_STATUS('0, `REG_HIER_BOOT_FSM_PS); end endtask @@ -1045,11 +1022,16 @@ module soc_ifc_tb //---------------------------------------------------------------- task sim_dut_init; - int sscode = -1; + // int sscode = -1; + string ssname = "UNSET"; begin - sscode = int'(security_state); - if (!((sscode >= 0) || (sscode <= 7))) + // sscode = int'(security_state); + // if (!((sscode >= 0) || (sscode <= 7))) + // $error("Have to explictily set security_state for soc_ifc_top for test to run!"); + + ssname = get_ss_name(int'(security_state)); + if ((ssname == "") || (ssname == "UNSET")) $error("Have to explictily set security_state for soc_ifc_top for test to run!"); else begin @@ -1057,8 +1039,9 @@ module soc_ifc_tb reset_dut(); wait (ready_for_fuses == 1'b1); - set_initval("CPTRA_FLOW_STATUS", 32'h4000_0000); - update_exp_regval("CPTRA_FLOW_STATUS", 32'h4000_0000, SET_DIRECT); + update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); + // set_initval("CPTRA_FLOW_STATUS", 32'h4000_0000); + // update_exp_regval("CPTRA_FLOW_STATUS", 32'h4000_0000, SET_DIRECT); repeat (5) @(posedge clk_tb); end @@ -1146,6 +1129,7 @@ module soc_ifc_tb word_addr_t addr; WordTransaction rdtrans; + automatic logic [31:0] valid_hrdata; begin rdtrans = new(); @@ -1153,8 +1137,9 @@ module soc_ifc_tb if (modifier == GET_AHB) begin read_single_word_ahb(addr); - $display(" Read over AHB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, hrdata_o_tb); - rdtrans.update(addr, hrdata_o_tb, tid); + valid_hrdata = addr[2] ? hrdata_o_tb[`AHB64_HI] :hrdata_o_tb[`AHB64_LO]; + $display(" Read over AHB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, valid_hrdata); + rdtrans.update(addr, valid_hrdata, tid); end else if (modifier == GET_APB) begin read_single_word_apb(addr); $display(" Read over APB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, prdata_o_tb); @@ -1215,6 +1200,7 @@ module soc_ifc_tb input logic [31:0] pauser=PAUSER_DEFAULT); string rname; word_addr_t addr; + automatic logic [31:0] valid_hrdata; begin addr = rdtrans.addr; @@ -1222,7 +1208,8 @@ module soc_ifc_tb if (modifier == GET_AHB) begin read_single_word_ahb(addr); - rdtrans.data = hrdata_o_tb; + valid_hrdata = addr[2] ? hrdata_o_tb[`AHB64_HI] :hrdata_o_tb[`AHB64_LO]; + rdtrans.data = valid_hrdata; $display(" Read over AHB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, rdtrans.data); end else if (modifier == GET_APB) begin if (pauser != PAUSER_DEFAULT) begin @@ -1254,6 +1241,7 @@ module soc_ifc_tb WordTransaction rdtrans; int tid_autoinc; + automatic logic [31:0] valid_hrdata; begin rdtrans = new(); @@ -1273,8 +1261,9 @@ module soc_ifc_tb if (modifier == GET_AHB) begin read_single_word_ahb(addr); - $display(" Read over AHB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, hrdata_o_tb); - rdtrans.update(addr, hrdata_o_tb, tid); + valid_hrdata = addr[2] ? hrdata_o_tb[`AHB64_HI] :hrdata_o_tb[`AHB64_LO]; + $display(" Read over AHB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, valid_hrdata); + rdtrans.update(addr, valid_hrdata, tid); end else if (modifier == GET_APB) begin read_single_word_apb(addr); $display(" Read over APB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, prdata_o_tb); @@ -1306,6 +1295,7 @@ module soc_ifc_tb WordTransaction wrtrans; int tid_autoinc; + automatic logic [31:0] valid_hrdata; begin wrtrans = new(); @@ -1356,8 +1346,9 @@ module soc_ifc_tb // read phase if (rd_modifier == GET_AHB) begin read_single_word_ahb(addr); - $display(" Read over AHB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, hrdata_o_tb); - rdtrans.update(addr, hrdata_o_tb, tid); + valid_hrdata = addr[2] ? hrdata_o_tb[`AHB64_HI] : hrdata_o_tb[`AHB64_LO]; + $display(" Read over AHB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, valid_hrdata); + rdtrans.update(addr, valid_hrdata, tid); end else if (rd_modifier == GET_APB) begin read_single_word_apb(addr); $display(" Read over APB: addr = %-40s (0x%08x), data = 0x%08x", rname, addr, prdata_o_tb); @@ -1377,6 +1368,50 @@ module soc_ifc_tb endtask // write_read_regs + //================================================================ + // Function Definitions + //================================================================ + + + //---------------------------------------------------------------- + // set_security_state() + // + // sets the security state explicily to any value between 0..7 + //---------------------------------------------------------------- + function automatic void set_security_state(input security_state_t ss); + + dword_t intr_notif_val; + + begin + security_state = '{device_lifecycle: ss.device_lifecycle, debug_locked: ss.debug_locked}; + + // TODO. Has hardwired mask bit positions in here. Ideally they should be pulled from tb package. + // Eg: in update_CPTRA_SECURITY_STATE(...) + set_initval("CPTRA_SECURITY_STATE", ss & 32'h7); + update_exp_regval("CPTRA_SECURITY_STATE", ss & 32'h7, SET_DIRECT); + + intr_notif_val = get_initval("INTR_BRF_NOTIF_INTERNAL_INTR_R") & 32'hffff_fffb | ss.debug_locked & 32'h4; + set_initval("INTR_BRF_NOTIF_INTERNAL_INTR_R", intr_notif_val); + update_exp_regval("INTR_BRF_NOTIF_INTERNAL_INTR_R", intr_notif_val, SET_DIRECT); + end + endfunction // set_security_state + + + //---------------------------------------------------------------- + // set_security_state_byname() + // + // sets security state by name, eg: "DEBUG_LOCKED_PRODUCTION", "RANDOM" + //---------------------------------------------------------------- + function automatic security_state_t set_security_state_byname(input string ss_name="RANDOM"); + + bit [2:0] ss_code; + + begin + ss_code = (ss_name == "RANDOM") ? $urandom_range(0, 7) : get_ss_code(ss_name); + set_security_state(security_state_t'(ss_code)); + return security_state_t'(ss_code); + end + endfunction // set_security_state_byname //---------------------------------------------------------------- @@ -1409,9 +1444,6 @@ module soc_ifc_tb // common initialization steps for all tests - // set_security_state(DEVICE_PRODUCTION, DEBUG_LOCKED); - // update_exp_regval(socregs.get_addr("CPTRA_SECURITY_STATE"), dword_t'(security_state), SET_DIRECT); - generic_input_wires0 = 32'h0; generic_input_wires1 = 32'h0; @@ -1423,10 +1455,6 @@ module soc_ifc_tb $display(" Running SOC_IFC_TEST = %s", soc_ifc_testname); $display(" ================================================================="); - //if (!($value$plusargs("SECURITY_STATE=%s", security_state_testname))) - // security_state_testname = "RANDOM"; - // soc_reg_pwron_test(security_state_testname); - if (soc_ifc_testname == "soc_reg_pwron_test") begin if (!($value$plusargs("SECURITY_STATE=%s", security_state_testname))) security_state_testname = "RANDOM"; @@ -1489,7 +1517,7 @@ module soc_ifc_tb fuse_reg_perm_test(); end else if (soc_ifc_testname == "fuse_reg_pauser_test") begin - set_security_state_random; + set_security_state_byname("RANDOM"); sim_dut_init(); fuse_reg_pauser_test(); diff --git a/src/soc_ifc/tb/soc_ifc_tb_pkg.sv b/src/soc_ifc/tb/soc_ifc_tb_pkg.sv index 8e6d7fa99..866528805 100644 --- a/src/soc_ifc/tb/soc_ifc_tb_pkg.sv +++ b/src/soc_ifc/tb/soc_ifc_tb_pkg.sv @@ -299,6 +299,7 @@ package soc_ifc_tb_pkg; }; + // mask bits that reflect which fields can be modified dword_t _soc_register_mask_dict [string] = { "CPTRA_HW_CONFIG" : (`SOC_IFC_REG_CPTRA_HW_CONFIG_ITRNG_EN_MASK | @@ -308,10 +309,12 @@ package soc_ifc_tb_pkg; "FUSE_KEY_MANIFEST_PK_HASH_MASK" : `SOC_IFC_REG_FUSE_KEY_MANIFEST_PK_HASH_MASK_MASK_MASK, "FUSE_LIFE_CYCLE" : `SOC_IFC_REG_FUSE_LIFE_CYCLE_LIFE_CYCLE_MASK, "FUSE_LMS_VERIFY" : `SOC_IFC_REG_FUSE_LMS_VERIFY_LMS_VERIFY_MASK, - "CPTRA_FLOW_STATUS" : (`SOC_IFC_REG_CPTRA_FLOW_STATUS_STATUS_MASK | - `SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_FW_MASK | - `SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_RUNTIME_MASK | - `SOC_IFC_REG_CPTRA_FLOW_STATUS_MAILBOX_FLOW_DONE_MASK), + "CPTRA_FLOW_STATUS" : (`SOC_IFC_REG_CPTRA_FLOW_STATUS_STATUS_MASK | + `SOC_IFC_REG_CPTRA_FLOW_STATUS_BOOT_FSM_PS_MASK | + `SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_FW_MASK | + `SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_RUNTIME_MASK | + `SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_FUSES_MASK | + `SOC_IFC_REG_CPTRA_FLOW_STATUS_MAILBOX_FLOW_DONE_MASK), "CPTRA_MBOX_PAUSER_LOCK" : `SOC_IFC_REG_CPTRA_MBOX_PAUSER_LOCK_0_LOCK_MASK, // same for all 5 pausers "CPTRA_TRNG_PAUSER_LOCK" : `SOC_IFC_REG_CPTRA_TRNG_PAUSER_LOCK_LOCK_MASK, "CPTRA_TRNG_STATUS.APB" : `SOC_IFC_REG_CPTRA_TRNG_STATUS_DATA_WR_DONE_MASK, @@ -496,7 +499,7 @@ package soc_ifc_tb_pkg; // Needs RMW of register without APB or AHB writes - function dword_t update_CPTRA_SECURITY_STATE(logic scan_mode, logic debug_state, logic [1:0] lifecycle); + function automatic dword_t update_CPTRA_SECURITY_STATE(logic scan_mode, logic debug_state, logic [1:0] lifecycle); begin update_exp_regval("CPTRA_SECURITY_STATE", @@ -512,23 +515,26 @@ package soc_ifc_tb_pkg; endfunction // update_CPTRA_SECURITY_STATE - // Needs RMW of register without APB or AHB writes - function logic [63:0] update_CPTRA_GENERIC_INPUT_WIRES(logic [31:0] wires1, logic [31:0] wires0); + // Can update only 1 GENERIC_INPUT_WIRE bus at a time + function automatic dword_t update_CPTRA_GENERIC_INPUT_WIRES(logic [31:0] generic_wires, bit upper); begin - update_exp_regval("CPTRA_GENERIC_INPUT_WIRES0", wires0, SET_DIRECT); - update_exp_regval("CPTRA_GENERIC_INPUT_WIRES1", wires1, SET_DIRECT); - - $display ("TB INFO. Fields for CPTRA_GENERIC_INPUT_WIRES0 changed to 0x%08x", _exp_register_data_dict["CPTRA_GENERIC_INPUT_WIRES0"]); - $display ("TB INFO. Fields for CPTRA_GENERIC_INPUT_WIRES1 changed to 0x%08x", _exp_register_data_dict["CPTRA_GENERIC_INPUT_WIRES1"]); - return {_exp_register_data_dict["CPTRA_GENERIC_INPUT_WIRES1"], _exp_register_data_dict["CPTRA_GENERIC_INPUT_WIRES0"]}; + if (upper) begin + update_exp_regval("CPTRA_GENERIC_INPUT_WIRES1", generic_wires, SET_DIRECT); + $display ("TB INFO. CPTRA_GENERIC_INPUT_WIRES1 changed to 0x%08x", _exp_register_data_dict["CPTRA_GENERIC_INPUT_WIRES1"]); + return _exp_register_data_dict["CPTRA_GENERIC_INPUT_WIRES1"]; + end else begin + update_exp_regval("CPTRA_GENERIC_INPUT_WIRES0", generic_wires, SET_DIRECT); + $display ("TB INFO. CPTRA_GENERIC_INPUT_WIRES0 changed to 0x%08x", _exp_register_data_dict["CPTRA_GENERIC_INPUT_WIRES0"]); + return _exp_register_data_dict["CPTRA_GENERIC_INPUT_WIRES0"]; + end end endfunction // update_CPTRA_GENERIC_INPUT_WIRES // Needs RMW of register without APB or AHB writes - function logic [31:0] update_INTR_BRF_NOTIF_INTERNAL_INTR_R(logic gen_input_wire_toggle, logic debug_locked); + function automatic logic [31:0] update_INTR_BRF_NOTIF_INTERNAL_INTR_R(logic gen_input_wire_toggle, logic debug_locked); dword_t tmp_data; @@ -549,15 +555,18 @@ package soc_ifc_tb_pkg; // Needs RMW of register without APB or AHB writes - function dword_t update_CPTRA_FLOW_STATUS(int fuse_ready_val); + function automatic dword_t update_CPTRA_FLOW_STATUS(int fuse_ready_val, logic [2:0] boot_fsm_ps); dword_t tmp_data; begin - tmp_data = _exp_register_data_dict["CPTRA_FLOW_STATUS"]; + + tmp_data = _exp_register_data_dict["CPTRA_FLOW_STATUS"]; // then preserve read-only bit fields per masks tmp_data = tmp_data & (32'hffff_ffff ^ `SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_FUSES_MASK); tmp_data = tmp_data | mask_shifted(fuse_ready_val, `SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_FUSES_MASK); - // $display( "TB INFO. update_CPTRA_FLOW_STATUS(%d) at time %t. new tmp_data = 0x%08x", fuse_ready_val, $realtime, tmp_data); + tmp_data = tmp_data & (32'hffff_ffff ^ `SOC_IFC_REG_CPTRA_FLOW_STATUS_BOOT_FSM_PS_MASK); + tmp_data = tmp_data | mask_shifted(boot_fsm_ps, `SOC_IFC_REG_CPTRA_FLOW_STATUS_BOOT_FSM_PS_MASK); + $display( "TB DEBUG. update_CPTRA_FLOW_STATUS(%x, %x) at time %t. new tmp_data = 0x%08x", fuse_ready_val, boot_fsm_ps, $realtime, tmp_data); update_exp_regval("CPTRA_FLOW_STATUS", tmp_data, SET_DIRECT); @@ -569,7 +578,7 @@ package soc_ifc_tb_pkg; // Needs RMW of register without APB or AHB writes - function dword_t update_CPTRA_RESET_REASON(int wrm_rst, int fw_upd); + function automatic dword_t update_CPTRA_RESET_REASON(int wrm_rst, int fw_upd); begin update_exp_regval("CPTRA_RESET_REASON", diff --git a/src/soc_ifc/tb/soc_reg_intrblk_test.svh b/src/soc_ifc/tb/soc_reg_intrblk_test.svh index 51ffb6bca..0cd8283cc 100644 --- a/src/soc_ifc/tb/soc_reg_intrblk_test.svh +++ b/src/soc_ifc/tb/soc_reg_intrblk_test.svh @@ -141,7 +141,7 @@ $display("Executing task soc_reg_intrblk_test"); $display("-----------------------------------\n"); - // set_security_state('{device_lifecycle: DEVICE_PRODUCTION, debug_locked: DEBUG_UNLOCKED}); + // set_security_state_byname("DEBUG_UNLOCKED_PRODCUTION"); tc_ctr = tc_ctr + 1; @@ -168,7 +168,7 @@ // are written using APB as part of Caliptra boot. Scoreboard update not // needed for readonly fields which are set directly by wires. simulate_caliptra_boot(); - update_CPTRA_FLOW_STATUS(ready_for_fuses); + update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); repeat (20) @(posedge clk_tb); sb.del_all(); diff --git a/src/soc_ifc/tb/soc_reg_invalid_test.svh b/src/soc_ifc/tb/soc_reg_invalid_test.svh index cdd2f064b..bff53679f 100644 --- a/src/soc_ifc/tb/soc_reg_invalid_test.svh +++ b/src/soc_ifc/tb/soc_reg_invalid_test.svh @@ -35,6 +35,7 @@ strq_t soc_regnames; word_addrq_t undef_regs; + automatic dword_t valid_hrdata; begin $display("Executing task soc_reg_invalid_test"); @@ -109,8 +110,9 @@ write_single_word_ahb(addr, wdata); read_single_word_ahb(addr); + valid_hrdata = addr[2] ? hrdata_o_tb[`AHB64_HI] : hrdata_o_tb[`AHB64_LO]; $display("Control condtion; test over AHB to aligned address (expect read to mirro write value) : addr = 0x%08x, wdata = 0x%08x, rdata = 0x%x", - addr, wdata, hrdata_o_tb); + addr, wdata, valid_hrdata); foreach (undef_regs[i]) begin @@ -120,10 +122,11 @@ write_single_word_ahb(undef_addr, wdata); read_single_word_ahb(undef_addr); - $display("Write & read over AHB : undefined addr = 0x%08x, wdata = 0x%08x, rdata = 0x%x", undef_addr, wdata, hrdata_o_tb); + valid_hrdata = addr[2] ? hrdata_o_tb[`AHB64_HI] : hrdata_o_tb[`AHB64_LO]; + $display("Write & read over AHB : undefined addr = 0x%08x, wdata = 0x%08x, rdata = 0x%x", undef_addr, wdata, valid_hrdata); - if (hrdata_o_tb != 0) begin - $display("ERROR. undefined addr = 0x%08x, returns non-zero value 0x%08x over AHB!", undef_addr, hrdata_o_tb); + if (valid_hrdata != 0) begin + $display("ERROR. undefined addr = 0x%08x, returns non-zero value 0x%08x over AHB!", undef_addr, valid_hrdata); error_ctr += 1; end end @@ -143,10 +146,11 @@ write_single_word_ahb(unaligned_addr, wdata); read_single_word_ahb(unaligned_addr); - $display("Write & read over AHB : unaligned addr = 0x%08x, wdata = 0x%08x, rdata = %x", unaligned_addr, wdata, hrdata_o_tb); + valid_hrdata = addr[2] ? hrdata_o_tb[`AHB64_HI] : hrdata_o_tb[`AHB64_LO]; + $display("Write & read over AHB : unaligned addr = 0x%08x, wdata = 0x%08x, rdata = %x", unaligned_addr, wdata, valid_hrdata); - if (hrdata_o_tb != 0) begin - $display("ERROR. unaligned addr = 0x%08x, returns non-zero value 0x%08x over AHB!", unaligned_addr, hrdata_o_tb); + if (valid_hrdata != 0) begin + $display("ERROR. unaligned addr = 0x%08x, returns non-zero value 0x%08x over AHB!", unaligned_addr, valid_hrdata); error_ctr += 1; end diff --git a/src/soc_ifc/tb/soc_reg_reset_test.svh b/src/soc_ifc/tb/soc_reg_reset_test.svh index e21dea4a3..dda5a6404 100644 --- a/src/soc_ifc/tb/soc_reg_reset_test.svh +++ b/src/soc_ifc/tb/soc_reg_reset_test.svh @@ -15,7 +15,6 @@ //====================================================================== - //---------------------------------------------------------------- // soc_reg_pwron_test() // @@ -31,25 +30,18 @@ WordTransaction rdtrans = new(); string rname_dyn; - word_addr_t raddr_dyn; + dword_t flow_status; + dword_t regval; + int tmp_i = 1000; // max 1000 cycle wait time begin - $display("\nExecuting task soc_reg_pwron_test"); - $display("---------------------------------\n"); - - // set_security_state('{device_lifecycle: DEVICE_PRODUCTION, debug_locked: DEBUG_LOCKED}); - if (ss_name == "RANDOM") begin - random_security_state = $urandom_range(0, 7); - set_security_state(security_state_t'(random_security_state)); - end else begin - random_security_state = get_ss_code(ss_name); - set_security_state(security_state_t'(random_security_state)); - end + print_banner("\nExecuting task soc_reg_pwron_test", "="); + + set_security_state_byname(ss_name); sim_dut_init(); tc_ctr = tc_ctr + 1; - $display("Current security state = 0b%03b", security_state); soc_regnames = get_soc_regnames_minus_intr(); @@ -58,46 +50,56 @@ $display ("0a. Checking Power-on values\n"); - // --------------------------------------------------------------- - // Phase 1. Inialize soc_regs ON COLD BOOT, then check values - // --------------------------------------------------------------- - $display ("1. Init values beyond reset at start of simulation "); + print_banner("Phase 1. Inialize soc_regs ON COLD BOOT, then check values"); + // -------------------------------------------------------------------------- + sb.record_reset_values(0, COLD_RESET); + flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); + @(posedge clk_tb); read_regs(GET_APB, soc_regnames, 0, 3); + _read_special_register(GET_APB, "INTERNAL_RV_MTIME_L", 0); // *** special register *** - // *** begin - special register *** - rname_dyn = "INTERNAL_RV_MTIME_L"; // dynamic value due to auto-update - raddr_dyn = socregs.get_addr(rname_dyn); + simulate_caliptra_boot(); + flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); + + // *** begin - special registers GENERIC_INPUT_WIRES *** + if (cptra_noncore_rst_b_tb == 1'b0) begin + fork + begin + wait (cptra_noncore_rst_b_tb == 1'b1); + $display("TB. INFO Finished waiting for cptra_noncore_rst_b_tb; current value = 1'b%b", cptra_noncore_rst_b_tb); + end + begin + repeat(tmp_i) @(posedge clk_tb); + $display("TB. ERROR Timed out while waiting for cptra_noncore_rst_b_tb; current value = 1'b%b", cptra_noncore_rst_b_tb); + end + join_any + end - read_reg_chk_inrange(GET_APB, rname_dyn, 0, cycle_ctr_since_pwrgood - 'd1 , cycle_ctr_since_pwrgood + 'd20); - repeat (3) @(posedge clk_tb); - // *** end - special register *** + _read_special_register(GET_APB, "CPTRA_GENERIC_INPUT_WIRES0", 0); + _read_special_register(GET_APB, "CPTRA_GENERIC_INPUT_WIRES1", 0); + // *** end - special registers *** - simulate_caliptra_boot(); repeat (10) @(posedge clk_tb); // FUSE_WR_DONE and BOOTFSM_GO are both 'h1 // no point in checking over ahb; pwron is long done - // --------------------------------------------------------------- - // Phase 2. Repeat COLD BOOT, then check values - // --------------------------------------------------------------- - $display ("1. Init values after asserting new cold reset"); + + print_banner("Phase 2. Repeat COLD BOOT, init explicitly as needed, then check values"); + // --------------------------------------------------------------------------------------- + reset_dut(); sb.del_all(); sb.record_reset_values(0, COLD_RESET); + reset_generic_input_wires(0, 0); read_regs(GET_APB, soc_regnames, 0, 3); - - // *** begin - special register *** - read_reg_chk_inrange(GET_APB, rname_dyn, 0, cycle_ctr_since_pwrgood - 'd1 , cycle_ctr_since_pwrgood + 'd20); - repeat (3) @(posedge clk_tb); - // *** end - special register *** - + _read_special_register(GET_APB, "INTERNAL_RV_MTIME_L", 0); // *** special register *** error_ctr = sb.err_count; end @@ -114,7 +116,7 @@ task soc_reg_wrmrst_test(input string ss_name="RANDOM"); int tid = 0; // TID is to be updated ONLY if multiple writes to an address - strq_t soc_regnames; + strq_t soc_regnames, fuse_regnames; logic [2:0] random_security_state; @@ -124,37 +126,23 @@ WordTransaction transaction; string rname_dyn; - word_addr_t raddr_dyn; begin - $display("\nExecuting task soc_reg_wrmrst_test"); - $display("----------------------------------\n"); + print_banner("\nExecuting task soc_reg_wrmrst_test", "="); transaction = new(); - // --------------------------------------------------------------- - // Phase 1. Inialize soc_regs ON COLD BOOT, overwrite w/new values - // --------------------------------------------------------------- - - if (ss_name == "RANDOM") begin - random_security_state = $urandom_range(0, 7); - set_security_state(security_state_t'(random_security_state)); - end else begin - random_security_state = get_ss_code(ss_name); - set_security_state(security_state_t'(random_security_state)); - end - + set_security_state_byname("RANDOM"); sim_dut_init(); tc_ctr = tc_ctr + 1; - $display ("\n1a. Write to registers after cold boot and check back writes"); - - soc_regnames = get_soc_regnames_minus_intr(); - + fuse_regnames = get_fuse_regnames(); + soc_regnames = get_soc_regnames_minus_fuse_intr(); foreach (soc_regnames[ix]) begin - if ((soc_regnames[ix] == "CPTRA_FUSE_WR_DONE") || (soc_regnames[ix] == "CPTRA_TRNG_STATUS")) begin + if ((soc_regnames[ix] == "CPTRA_FUSE_WR_DONE") || (soc_regnames[ix] == "CPTRA_TRNG_STATUS") || + (soc_regnames[ix] == "CPTRA_TRNG_DATA")) begin soc_regnames.delete(ix); // can cause problem downstream if fuse_wr_done == True continue; end @@ -162,18 +150,32 @@ del_from_strq(soc_regnames, "INTERNAL_RV_MTIME_L"); // Exclude CPTRA_RV_MTIME_L - write_regs(SET_APB, soc_regnames, 0, 3); - read_regs(GET_APB, soc_regnames, 0, 3); // just so we see what was written + + tphase = "1"; + print_banner("\nPhase 1. Initialize registers after cold boot, overwrite and check"); + // --------------------------------------------------------------------------------- + + write_regs(SET_APB, fuse_regnames, 0, 3); + read_regs(GET_APB, fuse_regnames, 0, 3); // just so we see what was written + + // Have to wait until after cptra_noncore_rst_b_tb is high + // write_regs(SET_APB, soc_regnames, 0, 3); + // read_regs(GET_APB, soc_regnames, 0, 3); // just so we see what was written simulate_caliptra_boot(); + wait (cptra_noncore_rst_b_tb == 1'b1); - repeat (10) @(posedge clk_tb); + repeat (5) @(posedge clk_tb); + + write_regs(SET_APB, soc_regnames, 0, 3); + read_regs(GET_APB, soc_regnames, 0, 3); // just so we see what was written + + repeat (5) @(posedge clk_tb); - // ----------------------------------------------------------------- - // Phase 2. Perform Warm Reset, read values over APB & AHB - // ----------------------------------------------------------------- - $display ("\n2a. Perform a warm reset then just read regs"); + tphase = "2a"; + print_banner("\nPhase 2a. Perform a warm reset then just read regs over APB"); + // -------------------------------------------------------------------------- sb.del_all(); warm_reset_dut(); @@ -182,9 +184,11 @@ wait (ready_for_fuses == 1'b1); // Some registers need update for specific fields - flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses); + flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); reset_reason = update_CPTRA_RESET_REASON(1, 0); + + $display("TB DEBUG. -- caliptra flow status updated = 0x%08x --", flow_status); sb.del_entries("CPTRA_FLOW_STATUS"); transaction.update_byname("CPTRA_FLOW_STATUS", flow_status, 0); sb.record_entry(transaction, SET_DIRECT); @@ -193,24 +197,32 @@ transaction.update_byname("CPTRA_RESET_REASON", reset_reason, 0); sb.record_entry(transaction, SET_DIRECT); + // Treat GENERIC_INPUT_WIRES slightly differently + del_from_strq(soc_regnames, "CPTRA_GENERIC_INPUT_WIRES0"); + del_from_strq(soc_regnames, "CPTRA_GENERIC_INPUT_WIRES1"); + // expect old sticky values which are different from power-on values + read_regs(GET_APB, fuse_regnames, 0, 3); read_regs(GET_APB, soc_regnames, 0, 3); - // *** begin - special register *** - rname_dyn = "INTERNAL_RV_MTIME_L"; // dynamic value due to auto-update - raddr_dyn = socregs.get_addr(rname_dyn); + // *** begin - special registers *** + _read_special_register(GET_APB, "INTERNAL_RV_MTIME_L", 0); + _read_special_register(GET_APB, "CPTRA_GENERIC_INPUT_WIRES0", 0); + _read_special_register(GET_APB, "CPTRA_GENERIC_INPUT_WIRES1", 0); + // *** end - special registers *** + - read_reg_chk_inrange(GET_APB, rname_dyn, 0, cycle_ctr_since_pwrgood - 'd1 , cycle_ctr_since_pwrgood + 'd20); - repeat (3) @(posedge clk_tb); - // *** end - special register *** + tphase = "2b"; + print_banner("\nPhase 2b. Simulate boot and read regs over AHB adjusting for boot regs"); + // ------------------------------------------------------------------------------------- simulate_caliptra_boot(); $display ("WRM_RST_TEST: After caliptra boot, Ready for fuses = %d, Flow status value is %x", ready_for_fuses, flow_status); // DEBUG sb.del_entries("CPTRA_FLOW_STATUS"); - flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses); + flow_status = update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); transaction.update_byname("CPTRA_FLOW_STATUS", flow_status, 0); transaction.display(); // DEBUG sb.record_entry(transaction, SET_APB); @@ -221,14 +233,49 @@ transaction.update_byname("CPTRA_BOOTFSM_GO", 32'h1, 0); sb.record_entry(transaction, SET_APB); + read_regs(GET_AHB, fuse_regnames, 0, 3); read_regs(GET_AHB, soc_regnames, 0, 3); - // *** begin - special register *** - read_reg_chk_inrange(GET_APB, rname_dyn, 0, cycle_ctr_since_pwrgood - 'd1 , cycle_ctr_since_pwrgood + 'd20); - repeat (3) @(posedge clk_tb); - // *** end - special register *** + // *** begin - special registers *** + _read_special_register(GET_AHB, "INTERNAL_RV_MTIME_L", 0); + _read_special_register(GET_AHB, "CPTRA_GENERIC_INPUT_WIRES0", 0); + _read_special_register(GET_AHB, "CPTRA_GENERIC_INPUT_WIRES1", 0); + // *** end - special registers *** error_ctr = sb.err_count; end endtask // soc_reg_wrmrst_test; + + + //---------------------------------------------------------------- + // _read_special_register() + // + // Registers that have special read outcomes. Uses on global tb-level signals + //---------------------------------------------------------------- + + task _read_special_register(access_t modifier, string regname, int tid); + + begin + case (regname) + "INTERNAL_RV_MTIME_L": read_reg_chk_inrange(modifier, regname, tid, cycle_ctr_since_pwrgood - 'd1 , cycle_ctr_since_pwrgood + 'd20); + + "CPTRA_GENERIC_INPUT_WIRES0": + if (cptra_noncore_rst_b_tb) + read_reg_chk_inrange(modifier, regname, tid, generic_input_wires0_q, generic_input_wires0_q); + else + read_reg_chk_inrange(modifier, regname, tid, '0, '0); + + "CPTRA_GENERIC_INPUT_WIRES1": + if (cptra_noncore_rst_b_tb) + read_reg_chk_inrange(modifier, regname, tid, generic_input_wires1_q, generic_input_wires1_q); + else + read_reg_chk_inrange(modifier, regname, tid, '0, '0); + + default: $display( "TB ERROR. Unsupported special register %s", regname); + + endcase + + @(posedge clk_tb); + end + endtask \ No newline at end of file diff --git a/src/soc_ifc/tb/soc_reg_test.svh b/src/soc_ifc/tb/soc_reg_test.svh index cfd9e5260..300ab621e 100644 --- a/src/soc_ifc/tb/soc_reg_test.svh +++ b/src/soc_ifc/tb/soc_reg_test.svh @@ -64,7 +64,7 @@ sb.del_all(); error_ctr = 0; - update_CPTRA_FLOW_STATUS(ready_for_fuses); + update_CPTRA_FLOW_STATUS(ready_for_fuses, `REG_HIER_BOOT_FSM_PS); $display ("\n-------------------------------------------------------------");