diff --git a/hw/ip/soc_dbg_ctrl/data/soc_dbg_ctrl.hjson b/hw/ip/soc_dbg_ctrl/data/soc_dbg_ctrl.hjson index 80803479aae2c5..c93b0bb0095433 100644 --- a/hw/ip/soc_dbg_ctrl/data/soc_dbg_ctrl.hjson +++ b/hw/ip/soc_dbg_ctrl/data/soc_dbg_ctrl.hjson @@ -100,6 +100,31 @@ This signals enables TEST & RMA mode accesses. ''' } + { struct: "lc_tx" + type: "uni" + name: "lc_raw_test_rma" + act: "rcv" + default: "lc_ctrl_pkg::Off" + package: "lc_ctrl_pkg" + desc: ''' + Test enable qualifier coming from life cycle controller. + This signals enables RAW, TEST and RMA mode accesses. + ''' + } + { struct: 'logic' + type: 'uni' + name: 'halt_cpu_boot' + act: 'rcv' + } + { struct: 'pwrmgr_data' + type: 'uni' + name: 'continue_cpu_boot' + package: 'rom_ctrl_pkg' + act: 'req' + desc: ''' + Artificial ROM control input to the pwrmgr to halt the boot process. + ''' + } ] regwidth: "32" @@ -239,6 +264,20 @@ } ] } + { name: "JTAG_CONTROL" + desc: "JTAG control register to interact with the boot flow." + swaccess: "rw" + hwaccess: "hro" + fields: [ + { bits: "0" + resval: "0" + name: "boot_continue" + desc: ''' + JTAG bit to stop or continue the boot flow if Ibex. + ''' + } + ] + } ] } } diff --git a/hw/ip/soc_dbg_ctrl/doc/registers.md b/hw/ip/soc_dbg_ctrl/doc/registers.md index 90bf20daf5889e..1d7aa489fed897 100644 --- a/hw/ip/soc_dbg_ctrl/doc/registers.md +++ b/hw/ip/soc_dbg_ctrl/doc/registers.md @@ -127,6 +127,7 @@ Trace register to observe the valid or relocked state that is either determined |:-------------------------------------------------------------------------------------------------|:---------|---------:|:---------------------------------------------------------------------------------------------------------| | soc_dbg_ctrl.[`JTAG_TRACE_DEBUG_POLICY_CATEGORY`](#jtag_trace_debug_policy_category) | 0x0 | 4 | Trace register to observe the debug category that is either determined by hardware or software. | | soc_dbg_ctrl.[`JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED`](#jtag_trace_debug_policy_valid_relocked) | 0x4 | 4 | Trace register to observe the valid or relocked state that is either determined by hardware or software. | +| soc_dbg_ctrl.[`JTAG_CONTROL`](#jtag_control) | 0x8 | 4 | JTAG control register to interact with the boot flow. | ## JTAG_TRACE_DEBUG_POLICY_CATEGORY Trace register to observe the debug category that is either determined by hardware or software. @@ -163,5 +164,22 @@ Trace register to observe the valid or relocked state that is either determined | 7:4 | ro | 0x9 | relocked | The relocked state determined by hardware or software. | | 3:0 | ro | 0x9 | valid | The valid state determined by hardware or software. | +## JTAG_CONTROL +JTAG control register to interact with the boot flow. +- Offset: `0x8` +- Reset default: `0x0` +- Reset mask: `0x1` + +### Fields + +```wavejson +{"reg": [{"name": "boot_continue", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 31}], "config": {"lanes": 1, "fontsize": 10, "vspace": 150}} +``` + +| Bits | Type | Reset | Name | Description | +|:------:|:------:|:-------:|:--------------|:----------------------------------------------------| +| 31:1 | | | | Reserved | +| 0 | rw | 0x0 | boot_continue | JTAG bit to stop or continue the boot flow if Ibex. | + diff --git a/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl.sv b/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl.sv index 39741eaf35606f..9772a9ffa9073d 100644 --- a/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl.sv +++ b/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl.sv @@ -30,18 +30,24 @@ module soc_dbg_ctrl input lc_ctrl_state_pkg::soc_dbg_state_t soc_dbg_state_i, input lc_ctrl_pkg::lc_tx_t lc_dft_en_i, input lc_ctrl_pkg::lc_tx_t lc_hw_debug_en_i, - // Boot information from the pwrmgr + input lc_ctrl_pkg::lc_tx_t lc_raw_test_rma_i, input pwrmgr_pkg::pwr_boot_status_t boot_status_i + // Boot information from the pwrmgr + // Halts CPU boot in early lifecycle stages after reset based on an external signal + // Halt functionality disappears in the production lifecycle + input logic halt_cpu_boot_i, + output rom_ctrl_pkg::pwrmgr_data_t continue_cpu_boot_o ); socdbg_ctrl_core_reg2hw_t core_reg2hw; socdbg_ctrl_core_hw2reg_t core_hw2reg; + socdbg_ctrl_jtag_reg2hw_t jtag_reg2hw; socdbg_ctrl_jtag_hw2reg_t jtag_hw2reg; ////////////////////////////////////////////////////////////////////////////////////////////////// // Alert Management ////////////////////////////////////////////////////////////////////////////////////////////////// - logic core_tl_intg_err, jtag_tl_intg_err; + logic core_tl_intg_err, jtag_tl_intg_err, halt_fsm_err; logic shadowed_storage_err, shadowed_update_err; logic policy_shadowed_storage_err, policy_shadowed_update_err; logic [NumAlerts-1:0] alert_test, alert; @@ -53,7 +59,7 @@ module soc_dbg_ctrl core_reg2hw.alert_test.recov_ctrl_update_err.qe }; assign alert[0] = core_tl_intg_err | jtag_tl_intg_err | shadowed_storage_err | - policy_shadowed_storage_err; + policy_shadowed_storage_err | halt_fsm_err; assign alert[1] = shadowed_update_err | policy_shadowed_update_err; localparam logic [NumAlerts-1:0] IsFatal = {1'b0, 1'b1}; @@ -97,6 +103,7 @@ module soc_dbg_ctrl .rst_ni, .tl_i (jtag_tl_i), .tl_o (jtag_tl_o), + .reg2hw (jtag_reg2hw), .hw2reg (jtag_hw2reg), // SEC_CM: BUS.INTEGRITY .intg_err_o (jtag_tl_intg_err) @@ -232,6 +239,85 @@ module soc_dbg_ctrl assign jtag_hw2reg.jtag_trace_debug_policy_valid_relocked.relocked.de = 1'b1; assign jtag_hw2reg.jtag_trace_debug_policy_valid_relocked.relocked.d = soc_dbg_policy_q.relocked; + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Ibex Halt feature via the pwrmgr's ROM_CTRL input + ////////////////////////////////////////////////////////////////////////////////////////////////// + + // Synchronize the input pin to io_div4 clk --> same as the pwrmgr fsm clk + logic halt_cpu_boot_sync; + prim_flop_2sync #( + .Width(1) + ) u_prim_flop_2sync ( + .clk_i, + .rst_ni, + .d_i(halt_cpu_boot_i), + .q_o(halt_cpu_boot_sync) + ); + + halt_state_e halt_state_d, halt_state_q; + + always_comb begin + // Default assignments + halt_state_d = halt_state_q; + alert_fsm_error = 0; + continue_cpu_boot_o.done = prim_mubi_pkg::mubi4_t'(MuBi4False); + + unique case (halt_state_q) + Idle: begin + if (boot_status_i.lc_done) begin + halt_state_d = CheckLifecycleState; + end + end + + CheckLifecycleState: begin + // If RAW state, wait for volatile unlock + if (lc_tx_test_true_strict(lc_raw_test_rma_i)) begin + halt_state_d = Wait4DftEn; + end else begin + halt_state_d = HaltDone; + end + end + + Wait4DftEn: begin + // Wait in this state until Volatile Raw Unlock is performed + // If !SecVolatileRawUnlockEn this is a passthrough state as lc_dft_en + // should be asserted along with lc_raw_test_rma + if (lc_tx_test_true_strict(lc_dft_en_i)) begin + halt_state_d = CheckHaltPin; + end + end + + CheckHaltPin: begin + // Go to halt state if required + if (halt_cpu_boot_sync) begin + halt_state_d = CheckJtagGo; + end else begin + halt_state_d = HaltDone; + end + end + + CheckJtagGo: begin + // Stay in halt state until JTAG command + if (jtag_reg2hw.jtag_control.q) begin + halt_state_d = HaltDone; + end + end + + HaltDone: begin + // Stay here until the next reset + continue_cpu_boot_o.done = prim_mubi_pkg::mubi4_t'(MuBi4True) + end + + default: begin + // Should not enter this state + alert_fsm_error = 1'b1; + end + endcase + end + + // SEC_CM: FSM.SPARSE + `PRIM_FLOP_SPARSE_FSM(u_state_regs, halt_state_d, halt_state_q, halt_state_e, Idle) + logic unused_signals; assign unused_signals = ^{boot_status_i.clk_status, boot_status_i.cpu_fetch_en, @@ -251,4 +337,6 @@ module soc_dbg_ctrl `ASSERT_PRIM_REG_WE_ONEHOT_ERROR_TRIGGER_ALERT(RegWeOnehotCheck_A, u_core_reg, alert_tx_o[0]) `ASSERT_PRIM_REG_WE_ONEHOT_ERROR_TRIGGER_ALERT(JtagRegWeOnehotCheck_A, u_jtag_reg, alert_tx_o[0]) + // Alert assertion for sparse FSM. + `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(HaltStateFsmCheck_A, u_state_regs, alert_tx_o[0]) endmodule diff --git a/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_jtag_reg_top.sv b/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_jtag_reg_top.sv index d15273a7e10f2b..c1c1bb87d72d0a 100644 --- a/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_jtag_reg_top.sv +++ b/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_jtag_reg_top.sv @@ -12,6 +12,7 @@ module soc_dbg_ctrl_jtag_reg_top ( input tlul_pkg::tl_h2d_t tl_i, output tlul_pkg::tl_d2h_t tl_o, // To HW + output soc_dbg_ctrl_reg_pkg::soc_dbg_ctrl_jtag_reg2hw_t reg2hw, // Write input soc_dbg_ctrl_reg_pkg::soc_dbg_ctrl_jtag_hw2reg_t hw2reg, // Read // Integrity check errors @@ -20,7 +21,7 @@ module soc_dbg_ctrl_jtag_reg_top ( import soc_dbg_ctrl_reg_pkg::* ; - localparam int AW = 3; + localparam int AW = 4; localparam int DW = 32; localparam int DBW = DW/8; // Byte Width @@ -51,9 +52,9 @@ module soc_dbg_ctrl_jtag_reg_top ( // also check for spurious write enables logic reg_we_err; - logic [1:0] reg_we_check; + logic [2:0] reg_we_check; prim_reg_we_check #( - .OneHotWidth(2) + .OneHotWidth(3) ) u_prim_reg_we_check ( .clk_i(clk_i), .rst_ni(rst_ni), @@ -123,6 +124,9 @@ module soc_dbg_ctrl_jtag_reg_top ( logic [6:0] jtag_trace_debug_policy_category_qs; logic [3:0] jtag_trace_debug_policy_valid_relocked_valid_qs; logic [3:0] jtag_trace_debug_policy_valid_relocked_relocked_qs; + logic jtag_control_we; + logic jtag_control_qs; + logic jtag_control_wd; // Register instances // R[jtag_trace_debug_policy_category]: V(False) @@ -209,12 +213,41 @@ module soc_dbg_ctrl_jtag_reg_top ( ); + // R[jtag_control]: V(False) + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_jtag_control ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (jtag_control_we), + .wd (jtag_control_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.jtag_control.q), + .ds (), + + // to register interface (read) + .qs (jtag_control_qs) + ); - logic [1:0] addr_hit; + + + logic [2:0] addr_hit; always_comb begin addr_hit = '0; addr_hit[0] = (reg_addr == SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_CATEGORY_OFFSET); addr_hit[1] = (reg_addr == SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED_OFFSET); + addr_hit[2] = (reg_addr == SOC_DBG_CTRL_JTAG_CONTROL_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -223,16 +256,21 @@ module soc_dbg_ctrl_jtag_reg_top ( always_comb begin wr_err = (reg_we & ((addr_hit[0] & (|(SOC_DBG_CTRL_JTAG_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(SOC_DBG_CTRL_JTAG_PERMIT[1] & ~reg_be))))); + (addr_hit[1] & (|(SOC_DBG_CTRL_JTAG_PERMIT[1] & ~reg_be))) | + (addr_hit[2] & (|(SOC_DBG_CTRL_JTAG_PERMIT[2] & ~reg_be))))); end // Generate write-enables + assign jtag_control_we = addr_hit[2] & reg_we & !reg_error; + + assign jtag_control_wd = reg_wdata[0]; // Assign write-enables to checker logic vector. always_comb begin reg_we_check = '0; reg_we_check[0] = 1'b0; reg_we_check[1] = 1'b0; + reg_we_check[2] = jtag_control_we; end // Read data return @@ -248,6 +286,10 @@ module soc_dbg_ctrl_jtag_reg_top ( reg_rdata_next[7:4] = jtag_trace_debug_policy_valid_relocked_relocked_qs; end + addr_hit[2]: begin + reg_rdata_next[0] = jtag_control_qs; + end + default: begin reg_rdata_next = '1; end diff --git a/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_pkg.sv b/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_pkg.sv index 28f624965bc742..d5c10611702e1e 100644 --- a/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_pkg.sv +++ b/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_pkg.sv @@ -43,4 +43,33 @@ package soc_dbg_ctrl_pkg; prim_mubi_pkg::mubi4_t relocked; } soc_dbg_policy_t; + // Encoding generated with: + // $ ./util/design/sparse-fsm-encode.py -d 3 -m 6 -n 6 \ + // -s 1870242553 --language=sv + // + // Hamming distance histogram: + // + // 0: -- + // 1: -- + // 2: -- + // 3: |||||||||||||||||||| (53.33%) + // 4: ||||||||||||||||| (46.67%) + // 5: -- + // 6: -- + // + // Minimum Hamming distance: 3 + // Maximum Hamming distance: 4 + // Minimum Hamming weight: 2 + // Maximum Hamming weight: 5 + // + localparam int StateWidth = 6; + typedef enum logic [StateWidth-1:0] { + Idle = 6'b101000, + CheckLifecycleState = 6'b011101, + Wait4DftEn = 6'b000110, + CheckHaltPin = 6'b110011, + CheckJtagGo = 6'b111110, + HaltDone = 6'b100101 + } halt_state_e; + endpackage diff --git a/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_reg_pkg.sv b/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_reg_pkg.sv index fcccc65669f882..d244edcbb68a4f 100644 --- a/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_reg_pkg.sv +++ b/hw/ip/soc_dbg_ctrl/rtl/soc_dbg_ctrl_reg_pkg.sv @@ -11,7 +11,7 @@ package soc_dbg_ctrl_reg_pkg; // Address widths within the block parameter int CoreAw = 5; - parameter int JtagAw = 3; + parameter int JtagAw = 4; /////////////////////////////////////////////// // Typedefs for registers for core interface // @@ -121,6 +121,10 @@ package soc_dbg_ctrl_reg_pkg; // Typedefs for registers for jtag interface // /////////////////////////////////////////////// + typedef struct packed { + logic q; + } soc_dbg_ctrl_reg2hw_jtag_control_reg_t; + typedef struct packed { logic [6:0] d; logic de; @@ -137,6 +141,11 @@ package soc_dbg_ctrl_reg_pkg; } relocked; } soc_dbg_ctrl_hw2reg_jtag_trace_debug_policy_valid_relocked_reg_t; + // Register -> HW type for jtag interface + typedef struct packed { + soc_dbg_ctrl_reg2hw_jtag_control_reg_t jtag_control; // [0:0] + } soc_dbg_ctrl_jtag_reg2hw_t; + // HW -> register type for jtag interface typedef struct packed { soc_dbg_ctrl_hw2reg_jtag_trace_debug_policy_category_reg_t @@ -146,19 +155,22 @@ package soc_dbg_ctrl_reg_pkg; } soc_dbg_ctrl_jtag_hw2reg_t; // Register offsets for jtag interface - parameter logic [JtagAw-1:0] SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_CATEGORY_OFFSET = 3'h 0; - parameter logic [JtagAw-1:0] SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED_OFFSET = 3'h 4; + parameter logic [JtagAw-1:0] SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_CATEGORY_OFFSET = 4'h 0; + parameter logic [JtagAw-1:0] SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED_OFFSET = 4'h 4; + parameter logic [JtagAw-1:0] SOC_DBG_CTRL_JTAG_CONTROL_OFFSET = 4'h 8; // Register index for jtag interface typedef enum int { SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_CATEGORY, - SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED + SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED, + SOC_DBG_CTRL_JTAG_CONTROL } soc_dbg_ctrl_jtag_id_e; // Register width information to check illegal writes for jtag interface - parameter logic [3:0] SOC_DBG_CTRL_JTAG_PERMIT [2] = '{ + parameter logic [3:0] SOC_DBG_CTRL_JTAG_PERMIT [3] = '{ 4'b 0001, // index[0] SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_CATEGORY - 4'b 0001 // index[1] SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED + 4'b 0001, // index[1] SOC_DBG_CTRL_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED + 4'b 0001 // index[2] SOC_DBG_CTRL_JTAG_CONTROL }; endpackage diff --git a/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson b/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson index ecf3abcb3aa98d..5accfa44662f05 100644 --- a/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson +++ b/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson @@ -22,6 +22,7 @@ ] default: "0" wait_for_external_reset: true + halt_ibex_via_rom_ctrl: true } unmanaged_clocks: {} clocks: @@ -1706,6 +1707,9 @@ width: 1 default: lc_ctrl_pkg::Off inst_name: lc_ctrl + end_idx: -1 + top_type: broadcast + top_signame: lc_ctrl_lc_raw_test_rma index: -1 } { @@ -2511,7 +2515,7 @@ package: rom_ctrl_pkg type: uni act: rcv - width: 2 + width: 3 default: rom_ctrl_pkg::PWRMGR_DATA_DEFAULT inst_name: pwrmgr_aon end_idx: -1 @@ -8480,6 +8484,50 @@ top_signame: lc_ctrl_lc_dft_en index: -1 } + { + name: lc_raw_test_rma + desc: + ''' + Test enable qualifier coming from life cycle controller. + This signals enables RAW, TEST and RMA mode accesses. + ''' + struct: lc_tx + package: lc_ctrl_pkg + type: uni + act: rcv + width: 1 + default: lc_ctrl_pkg::Off + inst_name: soc_dbg_ctrl + top_signame: lc_ctrl_lc_raw_test_rma + index: -1 + } + { + name: halt_cpu_boot + struct: logic + type: uni + act: rcv + width: 1 + inst_name: soc_dbg_ctrl + default: "" + package: "" + external: true + top_signame: debug_halt_cpu_boot + conn_type: false + index: -1 + } + { + name: continue_cpu_boot + desc: Artificial ROM control input to the pwrmgr to halt the boot process. + struct: pwrmgr_data + package: rom_ctrl_pkg + type: uni + act: req + width: 1 + inst_name: soc_dbg_ctrl + default: "" + top_signame: pwrmgr_aon_rom_ctrl + index: 2 + } { name: core_tl struct: tl @@ -9346,6 +9394,7 @@ [ rom_ctrl0.pwrmgr_data rom_ctrl1.pwrmgr_data + soc_dbg_ctrl.continue_cpu_boot ] pwrmgr_aon.boot_status: [ @@ -9453,6 +9502,10 @@ [ rv_dm.strap_en_override ] + lc_ctrl.lc_raw_test_rma: + [ + soc_dbg_ctrl.lc_raw_test_rma + ] lc_ctrl.lc_dft_en: [ otp_ctrl.lc_dft_en @@ -9984,6 +10037,7 @@ soc_proxy.soc_gpo_async: soc_gpo_async spi_device.sck_monitor: sck_monitor soc_dbg_ctrl.soc_dbg_policy_bus: soc_dbg_policy_bus + soc_dbg_ctrl.halt_cpu_boot: debug_halt_cpu_boot } } xbar: @@ -12962,7 +13016,7 @@ { soc_dbg: 0x2300 } - size_byte: 0x8 + size_byte: 0x10 } ] xbar: false @@ -18625,6 +18679,9 @@ width: 1 default: lc_ctrl_pkg::Off inst_name: lc_ctrl + end_idx: -1 + top_type: broadcast + top_signame: lc_ctrl_lc_raw_test_rma index: -1 } { @@ -19260,7 +19317,7 @@ package: rom_ctrl_pkg type: uni act: rcv - width: 2 + width: 3 default: rom_ctrl_pkg::PWRMGR_DATA_DEFAULT inst_name: pwrmgr_aon end_idx: -1 @@ -22562,6 +22619,50 @@ top_signame: lc_ctrl_lc_dft_en index: -1 } + { + name: lc_raw_test_rma + desc: + ''' + Test enable qualifier coming from life cycle controller. + This signals enables RAW, TEST and RMA mode accesses. + ''' + struct: lc_tx + package: lc_ctrl_pkg + type: uni + act: rcv + width: 1 + default: lc_ctrl_pkg::Off + inst_name: soc_dbg_ctrl + top_signame: lc_ctrl_lc_raw_test_rma + index: -1 + } + { + name: halt_cpu_boot + struct: logic + type: uni + act: rcv + width: 1 + inst_name: soc_dbg_ctrl + default: "" + package: "" + external: true + top_signame: debug_halt_cpu_boot + conn_type: false + index: -1 + } + { + name: continue_cpu_boot + desc: Artificial ROM control input to the pwrmgr to halt the boot process. + struct: pwrmgr_data + package: rom_ctrl_pkg + type: uni + act: req + width: 1 + inst_name: soc_dbg_ctrl + default: "" + top_signame: pwrmgr_aon_rom_ctrl + index: 2 + } { name: core_tl struct: tl @@ -25134,6 +25235,18 @@ index: -1 netname: soc_dbg_policy_bus } + { + package: "" + struct: logic + signame: debug_halt_cpu_boot_i + width: 1 + type: uni + default: "" + direction: in + conn_type: false + index: -1 + netname: debug_halt_cpu_boot + } ] definitions: [ @@ -25394,7 +25507,7 @@ package: rom_ctrl_pkg struct: pwrmgr_data signame: pwrmgr_aon_rom_ctrl - width: 2 + width: 3 type: uni end_idx: -1 act: rcv @@ -25740,6 +25853,17 @@ suffix: "" default: 1'b0 } + { + package: lc_ctrl_pkg + struct: lc_tx + signame: lc_ctrl_lc_raw_test_rma + width: 1 + type: uni + end_idx: -1 + act: req + suffix: "" + default: lc_ctrl_pkg::Off + } { package: lc_ctrl_pkg struct: lc_tx diff --git a/hw/top_darjeeling/data/top_darjeeling.hjson b/hw/top_darjeeling/data/top_darjeeling.hjson index a339b22d5b7613..bea2c9b044dcc3 100644 --- a/hw/top_darjeeling/data/top_darjeeling.hjson +++ b/hw/top_darjeeling/data/top_darjeeling.hjson @@ -27,6 +27,9 @@ // Wait for external resets for integrated OpenTitan wait_for_external_reset: true + + // Ibex halt feature via additional ROM Control input + halt_ibex_via_rom_ctrl: true }, // List of unmanaged external clocks @@ -1142,7 +1145,8 @@ 'aon_timer_aon.sleep_mode'], 'pwrmgr_aon.fetch_en' : ['rv_core_ibex.pwrmgr_cpu_en'], 'pwrmgr_aon.rom_ctrl' : ['rom_ctrl0.pwrmgr_data', - 'rom_ctrl1.pwrmgr_data'], + 'rom_ctrl1.pwrmgr_data', + 'soc_dbg_ctrl.continue_cpu_boot'], 'pwrmgr_aon.boot_status' : ['soc_dbg_ctrl.boot_status'], 'keymgr_dpe.rom_digest' : ['rom_ctrl0.keymgr_data', 'rom_ctrl1.keymgr_data'], @@ -1200,6 +1204,7 @@ 'lc_ctrl.strap_en_override' : ['rv_dm.strap_en_override'], // LC function control signal broadcast + 'lc_ctrl.lc_raw_test_rma' : ['soc_dbg_ctrl.lc_raw_test_rma'] 'lc_ctrl.lc_dft_en' : ['otp_ctrl.lc_dft_en', 'ast.lc_dft_en', 'pwrmgr_aon.lc_dft_en', @@ -1380,6 +1385,7 @@ 'soc_proxy.soc_gpo_async' : 'soc_gpo_async', 'spi_device.sck_monitor' : 'sck_monitor', 'soc_dbg_ctrl.soc_dbg_policy_bus' : 'soc_dbg_policy_bus', + 'soc_dbg_ctrl.halt_cpu_boot' : 'debug_halt_cpu_boot', }, }, diff --git a/hw/top_darjeeling/dv/autogen/xbar_env_pkg__params.sv b/hw/top_darjeeling/dv/autogen/xbar_env_pkg__params.sv index 7642c30bc1439c..9078fb599d7e02 100644 --- a/hw/top_darjeeling/dv/autogen/xbar_env_pkg__params.sv +++ b/hw/top_darjeeling/dv/autogen/xbar_env_pkg__params.sv @@ -203,7 +203,7 @@ tl_device_t xbar_devices[$] = '{ '{32'h00020000, 32'h00020fff} }}, '{"soc_dbg_ctrl__jtag", '{ - '{32'h00002300, 32'h00002307} + '{32'h00002300, 32'h0000230f} }}}; // List of Xbar hosts diff --git a/hw/top_darjeeling/dv/autogen/xbar_tgl_excl.cfg b/hw/top_darjeeling/dv/autogen/xbar_tgl_excl.cfg index 7c955a7f3bfdf2..c6e6cb0df4240a 100644 --- a/hw/top_darjeeling/dv/autogen/xbar_tgl_excl.cfg +++ b/hw/top_darjeeling/dv/autogen/xbar_tgl_excl.cfg @@ -287,6 +287,6 @@ -node tb.dut*.u_mbx_jtag soc_tl_*i.a_address[31:13] -node tb.dut*.u_lc_ctrl dmi_tl_*i.a_address[16:12] -node tb.dut*.u_lc_ctrl dmi_tl_*i.a_address[31:18] --node tb.dut*.u_soc_dbg_ctrl jtag_tl_*i.a_address[7:3] +-node tb.dut*.u_soc_dbg_ctrl jtag_tl_*i.a_address[7:4] -node tb.dut*.u_soc_dbg_ctrl jtag_tl_*i.a_address[12:10] -node tb.dut*.u_soc_dbg_ctrl jtag_tl_*i.a_address[31:14] diff --git a/hw/top_darjeeling/ip/xbar_dbg/data/autogen/xbar_dbg.gen.hjson b/hw/top_darjeeling/ip/xbar_dbg/data/autogen/xbar_dbg.gen.hjson index cdbd17c39c4bf6..a7c2afa34d8819 100644 --- a/hw/top_darjeeling/ip/xbar_dbg/data/autogen/xbar_dbg.gen.hjson +++ b/hw/top_darjeeling/ip/xbar_dbg/data/autogen/xbar_dbg.gen.hjson @@ -139,7 +139,7 @@ { soc_dbg: 0x2300 } - size_byte: 0x8 + size_byte: 0x10 } ] xbar: false diff --git a/hw/top_darjeeling/ip/xbar_dbg/dv/autogen/xbar_cover.cfg b/hw/top_darjeeling/ip/xbar_dbg/dv/autogen/xbar_cover.cfg index 7fbaf13b026d97..5a9d9a19a18335 100644 --- a/hw/top_darjeeling/ip/xbar_dbg/dv/autogen/xbar_cover.cfg +++ b/hw/top_darjeeling/ip/xbar_dbg/dv/autogen/xbar_cover.cfg @@ -26,7 +26,7 @@ -node tb.dut tl_mbx_jtag__soc_o.a_address[31:13] -node tb.dut tl_lc_ctrl__dmi_o.a_address[16:12] -node tb.dut tl_lc_ctrl__dmi_o.a_address[31:18] --node tb.dut tl_soc_dbg_ctrl__jtag_o.a_address[7:3] +-node tb.dut tl_soc_dbg_ctrl__jtag_o.a_address[7:4] -node tb.dut tl_soc_dbg_ctrl__jtag_o.a_address[12:10] -node tb.dut tl_soc_dbg_ctrl__jtag_o.a_address[31:14] diff --git a/hw/top_darjeeling/ip/xbar_dbg/dv/autogen/xbar_env_pkg__params.sv b/hw/top_darjeeling/ip/xbar_dbg/dv/autogen/xbar_env_pkg__params.sv index 8bf0b73d829eac..93532a2d173cd7 100644 --- a/hw/top_darjeeling/ip/xbar_dbg/dv/autogen/xbar_env_pkg__params.sv +++ b/hw/top_darjeeling/ip/xbar_dbg/dv/autogen/xbar_env_pkg__params.sv @@ -17,7 +17,7 @@ tl_device_t xbar_devices[$] = '{ '{32'h00020000, 32'h00020fff} }}, '{"soc_dbg_ctrl__jtag", '{ - '{32'h00002300, 32'h00002307} + '{32'h00002300, 32'h0000230f} }}}; // List of Xbar hosts diff --git a/hw/top_darjeeling/ip/xbar_dbg/rtl/autogen/tl_dbg_pkg.sv b/hw/top_darjeeling/ip/xbar_dbg/rtl/autogen/tl_dbg_pkg.sv index 5f47dd4eeb4c1c..ef7b8234bd7e0f 100644 --- a/hw/top_darjeeling/ip/xbar_dbg/rtl/autogen/tl_dbg_pkg.sv +++ b/hw/top_darjeeling/ip/xbar_dbg/rtl/autogen/tl_dbg_pkg.sv @@ -14,7 +14,7 @@ package tl_dbg_pkg; localparam logic [31:0] ADDR_MASK_RV_DM__DBG = 32'h 000001ff; localparam logic [31:0] ADDR_MASK_MBX_JTAG__SOC = 32'h 0000001f; localparam logic [31:0] ADDR_MASK_LC_CTRL__DMI = 32'h 00000fff; - localparam logic [31:0] ADDR_MASK_SOC_DBG_CTRL__JTAG = 32'h 00000007; + localparam logic [31:0] ADDR_MASK_SOC_DBG_CTRL__JTAG = 32'h 0000000f; localparam int N_HOST = 1; localparam int N_DEVICE = 4; diff --git a/hw/top_darjeeling/ip_autogen/pwrmgr/data/pwrmgr.hjson b/hw/top_darjeeling/ip_autogen/pwrmgr/data/pwrmgr.hjson index 70ef52bd947f36..a68e586e279bb6 100644 --- a/hw/top_darjeeling/ip_autogen/pwrmgr/data/pwrmgr.hjson +++ b/hw/top_darjeeling/ip_autogen/pwrmgr/data/pwrmgr.hjson @@ -264,7 +264,7 @@ type: "uni", name: "rom_ctrl", act: "rcv", - width: "2" + width: "3" package: "rom_ctrl_pkg", default: "rom_ctrl_pkg::PWRMGR_DATA_DEFAULT" }, @@ -366,7 +366,7 @@ { name: "NumRomInputs", desc: "Number of inputs from ROM_CTRL", type: "int", - default: "2", + default: "3", local: "true" }, diff --git a/hw/top_darjeeling/ip_autogen/pwrmgr/data/top_darjeeling_pwrmgr.ipconfig.hjson b/hw/top_darjeeling/ip_autogen/pwrmgr/data/top_darjeeling_pwrmgr.ipconfig.hjson index 0824e2c6807b70..6e9bf616f0d28f 100644 --- a/hw/top_darjeeling/ip_autogen/pwrmgr/data/top_darjeeling_pwrmgr.ipconfig.hjson +++ b/hw/top_darjeeling/ip_autogen/pwrmgr/data/top_darjeeling_pwrmgr.ipconfig.hjson @@ -75,7 +75,7 @@ } NumRstReqs: 2 wait_for_external_reset: true - NumRomInputs: 2 + NumRomInputs: 3 topname: darjeeling } } diff --git a/hw/top_darjeeling/ip_autogen/pwrmgr/doc/interfaces.md b/hw/top_darjeeling/ip_autogen/pwrmgr/doc/interfaces.md index 1eb627f2e7359b..243f7e2239f4fe 100644 --- a/hw/top_darjeeling/ip_autogen/pwrmgr/doc/interfaces.md +++ b/hw/top_darjeeling/ip_autogen/pwrmgr/doc/interfaces.md @@ -27,7 +27,7 @@ Referring to the [Comportable guideline for peripheral device functionality](htt | ndmreset_req | logic | uni | rcv | 1 | | | strap | logic | uni | req | 1 | | | low_power | logic | uni | req | 1 | | -| rom_ctrl | rom_ctrl_pkg::pwrmgr_data | uni | rcv | 2 | | +| rom_ctrl | rom_ctrl_pkg::pwrmgr_data | uni | rcv | 3 | | | fetch_en | lc_ctrl_pkg::lc_tx | uni | req | 1 | | | lc_dft_en | lc_ctrl_pkg::lc_tx | uni | rcv | 1 | | | lc_hw_debug_en | lc_ctrl_pkg::lc_tx | uni | rcv | 1 | | diff --git a/hw/top_darjeeling/ip_autogen/pwrmgr/dv/cov/pwrmgr_cov_bind.sv b/hw/top_darjeeling/ip_autogen/pwrmgr/dv/cov/pwrmgr_cov_bind.sv index 46ec3f38141758..2df5f893d621d6 100644 --- a/hw/top_darjeeling/ip_autogen/pwrmgr/dv/cov/pwrmgr_cov_bind.sv +++ b/hw/top_darjeeling/ip_autogen/pwrmgr/dv/cov/pwrmgr_cov_bind.sv @@ -36,6 +36,16 @@ module pwrmgr_cov_bind; .mubi (rom_ctrl_i[1].good) ); + bind pwrmgr cip_mubi_cov_if #(.Width(prim_mubi_pkg::MuBi4Width)) u_rom_ctrl2_good_mubi_cov_if ( + .rst_ni (rst_ni), + .mubi (rom_ctrl_i[2].done) + ); + + bind pwrmgr cip_mubi_cov_if #(.Width(prim_mubi_pkg::MuBi4Width)) u_rom_ctrl2_done_mubi_cov_if ( + .rst_ni (rst_ni), + .mubi (rom_ctrl_i[2].good) + ); + bind pwrmgr cip_mubi_cov_if #(.Width(prim_mubi_pkg::MuBi4Width)) u_sw_rst_req_mubi_cov_if ( .rst_ni (rst_ni), .mubi (sw_rst_req_i) diff --git a/hw/top_darjeeling/ip_autogen/pwrmgr/rtl/pwrmgr_reg_pkg.sv b/hw/top_darjeeling/ip_autogen/pwrmgr/rtl/pwrmgr_reg_pkg.sv index 010a9367b22cce..0970917f0b9c2d 100644 --- a/hw/top_darjeeling/ip_autogen/pwrmgr/rtl/pwrmgr_reg_pkg.sv +++ b/hw/top_darjeeling/ip_autogen/pwrmgr/rtl/pwrmgr_reg_pkg.sv @@ -16,7 +16,7 @@ package pwrmgr_reg_pkg; parameter int NumRstReqs = 2; parameter int NumIntRstReqs = 2; parameter int NumDebugRstReqs = 1; - parameter int NumRomInputs = 2; + parameter int NumRomInputs = 3; parameter int ResetMainPwrIdx = 2; parameter int ResetEscIdx = 3; parameter int ResetNdmIdx = 4; diff --git a/hw/top_darjeeling/rtl/autogen/top_darjeeling.sv b/hw/top_darjeeling/rtl/autogen/top_darjeeling.sv index ab620f2d9a38f8..590c895d185065 100644 --- a/hw/top_darjeeling/rtl/autogen/top_darjeeling.sv +++ b/hw/top_darjeeling/rtl/autogen/top_darjeeling.sv @@ -251,6 +251,7 @@ module top_darjeeling #( input logic [15:0] soc_gpo_async_i, output logic sck_monitor_o, output soc_dbg_ctrl_pkg::soc_dbg_policy_t soc_dbg_policy_bus_o, + input logic debug_halt_cpu_boot_i, // All externally supplied clocks @@ -494,7 +495,7 @@ module top_darjeeling #( logic pwrmgr_aon_strap; logic pwrmgr_aon_low_power; lc_ctrl_pkg::lc_tx_t pwrmgr_aon_fetch_en; - rom_ctrl_pkg::pwrmgr_data_t [1:0] pwrmgr_aon_rom_ctrl; + rom_ctrl_pkg::pwrmgr_data_t [2:0] pwrmgr_aon_rom_ctrl; pwrmgr_pkg::pwr_boot_status_t pwrmgr_aon_boot_status; rom_ctrl_pkg::keymgr_data_t [1:0] keymgr_dpe_rom_digest; dma_pkg::lsio_trigger_t dma_lsio_trigger; @@ -524,6 +525,7 @@ module top_darjeeling #( otp_ctrl_pkg::lc_otp_vendor_test_rsp_t lc_ctrl_lc_otp_vendor_test_rsp; lc_ctrl_pkg::lc_keymgr_div_t lc_ctrl_lc_keymgr_div; logic lc_ctrl_strap_en_override; + lc_ctrl_pkg::lc_tx_t lc_ctrl_lc_raw_test_rma; lc_ctrl_pkg::lc_tx_t lc_ctrl_lc_dft_en; lc_ctrl_pkg::lc_tx_t lc_ctrl_lc_hw_debug_en; lc_ctrl_pkg::lc_tx_t lc_ctrl_lc_cpu_en; @@ -1220,7 +1222,7 @@ module top_darjeeling #( .lc_otp_program_i(lc_ctrl_lc_otp_program_rsp), .kmac_data_o(kmac_app_req[1]), .kmac_data_i(kmac_app_rsp[1]), - .lc_raw_test_rma_o(), + .lc_raw_test_rma_o(lc_ctrl_lc_raw_test_rma), .lc_dft_en_o(lc_ctrl_lc_dft_en), .lc_nvm_debug_en_o(), .lc_hw_debug_en_o(lc_ctrl_lc_hw_debug_en), @@ -2445,6 +2447,9 @@ module top_darjeeling #( .soc_dbg_policy_bus_o(soc_dbg_policy_bus_o), .lc_hw_debug_en_i(lc_ctrl_lc_hw_debug_en), .lc_dft_en_i(lc_ctrl_lc_dft_en), + .lc_raw_test_rma_i(lc_ctrl_lc_raw_test_rma), + .halt_cpu_boot_i(debug_halt_cpu_boot_i), + .continue_cpu_boot_o(pwrmgr_aon_rom_ctrl[2]), .core_tl_i(soc_dbg_ctrl_core_tl_req), .core_tl_o(soc_dbg_ctrl_core_tl_rsp), .jtag_tl_i(soc_dbg_ctrl_jtag_tl_req), diff --git a/util/topgen.py b/util/topgen.py index bfd680f6747f7b..03f571f92c3485 100755 --- a/util/topgen.py +++ b/util/topgen.py @@ -407,6 +407,10 @@ def generate_pwrmgr(top: Dict[str, object], out_path: Path) -> None: n_rom_ctrl = lib.num_rom_ctrl(top['module']) assert n_rom_ctrl > 0 + # Add another artificial ROM_CTRL input to allow IBEX halting that input + if top['power'].get('halt_ibex_via_rom_ctrl', False): + n_rom_ctrl += 1 + if n_wkups < 1: n_wkups = 1 log.warning(