From 26c9ba70236994ec89cb9cd211f533bb3bd45b8c Mon Sep 17 00:00:00 2001 From: Neeraj Upasani Date: Mon, 15 Apr 2024 15:41:52 -0700 Subject: [PATCH] [pwrmgr] Take external SoC reset into account in FSM 1. Internally generated reset request passed to SoC. 2. Create a sticky assertion internally to log request. Sticky flag cleared only upon external reset deassertion. 3. SoC transfers this request to platform to assert external reset. 4. External SoC reset deasserts after some time. 5. Pwrmgr stays in FastPwrStateRstWait state until the external SoC reset deasserts. 6. Boot / reset sequence continues. 7. Also fixes the external reset signal glitch filter to use the por reset. This is required to make sure that the external reset state does not self-reset once asserted and faithfully forwards that state to pwrmgr. 8. Added some debug visibility signals for pwrmgr. 9. Added temporary reset loop back path in pwrmgr TB to translate internal reset req from OT --> ext reset from SoC to OT. Needs a proper fix in testbench (issue #22710). Signed-off-by: Neeraj Upasani --- hw/ip/pwrmgr/data/pwrmgr.hjson.tpl | 14 ++++ hw/ip/pwrmgr/dv/tb.sv | 5 +- hw/ip/pwrmgr/pwrmgr_pkg.core | 1 + hw/ip/pwrmgr/rtl/pwrmgr.sv | 49 ++++++++++-- hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv | 54 +++++++++++-- hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv | 10 +++ .../data/autogen/top_darjeeling.gen.hjson | 75 ++++++++++++++++--- hw/top_darjeeling/data/top_darjeeling.hjson | 16 +++- .../dv/autogen/rstmgr_tgl_excl.cfg | 1 + .../ip/pwrmgr/data/autogen/pwrmgr.hjson | 14 ++++ .../rstmgr/dv/env/autogen/rstmgr_env_pkg.sv | 1 - .../ip/rstmgr/rtl/autogen/rstmgr.sv | 30 ++------ .../ip/soc_proxy/data/soc_proxy.hjson | 2 +- .../ip/soc_proxy/rtl/soc_proxy.sv | 8 +- .../rtl/autogen/chip_darjeeling_asic.sv | 34 ++++++++- .../rtl/autogen/chip_darjeeling_cw310.sv | 2 + .../rtl/autogen/top_darjeeling.sv | 8 +- .../rtl/chip_darjeeling_verilator.sv | 35 ++++++++- .../data/autogen/top_earlgrey.gen.hjson | 33 +++++++- .../ip/pwrmgr/data/autogen/pwrmgr.hjson | 14 ++++ .../rtl/autogen/chip_earlgrey_cw310.sv | 1 + hw/top_earlgrey/rtl/autogen/top_earlgrey.sv | 5 +- util/topgen/templates/chiplevel.sv.tpl | 37 ++++++++- 23 files changed, 386 insertions(+), 63 deletions(-) diff --git a/hw/ip/pwrmgr/data/pwrmgr.hjson.tpl b/hw/ip/pwrmgr/data/pwrmgr.hjson.tpl index 627be2cd9471f..2e4e1a88ad725 100644 --- a/hw/ip/pwrmgr/data/pwrmgr.hjson.tpl +++ b/hw/ip/pwrmgr/data/pwrmgr.hjson.tpl @@ -68,6 +68,12 @@ ], inter_signal_list: [ + { struct: "pwr_boot_status", + type: "uni", + name: "boot_status", + act: "req", + package: "pwrmgr_pkg", + }, { struct: "pwr_ast", type: "req_rsp", name: "pwr_ast", @@ -223,6 +229,14 @@ % endfor + { name: "PwrFsmWaitForExtRst", + desc: "Wait for external reset to complete", + type: "bit", + default: "0", + local: "false", + expose: "true" + }, + { name: "NumRstReqs", desc: "Number of peripheral reset requets", type: "int", diff --git a/hw/ip/pwrmgr/dv/tb.sv b/hw/ip/pwrmgr/dv/tb.sv index 9fb11d5a7329c..a1ecbd1bcbcc4 100644 --- a/hw/ip/pwrmgr/dv/tb.sv +++ b/hw/ip/pwrmgr/dv/tb.sv @@ -19,6 +19,7 @@ module tb; wire clk_slow, rst_slow_n; wire devmode; wire [NUM_MAX_INTERRUPTS-1:0] interrupts; + wire int_reset_req; // interfaces clk_rst_if clk_rst_if ( @@ -49,6 +50,7 @@ module tb; ); assign interrupts[0] = pwrmgr_if.intr_wakeup; + assign int_reset_req = tb.dut.internal_reset_req ; pwrmgr_if pwrmgr_if ( .clk, @@ -97,7 +99,8 @@ module tb; .fetch_en_o(pwrmgr_if.fetch_en), .wakeups_i (pwrmgr_if.wakeups_i), - .rstreqs_i (pwrmgr_if.rstreqs_i), + // TOOD(#22710): properly cooperate with `pwrmgr_if.rstreqs_i[1]` + .rstreqs_i ({int_reset_req, pwrmgr_if.rstreqs_i[0]}), .ndmreset_req_i(pwrmgr_if.cpu_i.ndmreset_req), .lc_dft_en_i (pwrmgr_if.lc_dft_en), diff --git a/hw/ip/pwrmgr/pwrmgr_pkg.core b/hw/ip/pwrmgr/pwrmgr_pkg.core index 3e83cde44fd12..795d0811b6b07 100644 --- a/hw/ip/pwrmgr/pwrmgr_pkg.core +++ b/hw/ip/pwrmgr/pwrmgr_pkg.core @@ -9,6 +9,7 @@ filesets: files_rtl: depend: - lowrisc:ip:pwrmgr_reg + - lowrisc:ip:rom_ctrl_pkg files: - rtl/pwrmgr_pkg.sv file_type: systemVerilogSource diff --git a/hw/ip/pwrmgr/rtl/pwrmgr.sv b/hw/ip/pwrmgr/rtl/pwrmgr.sv index 2ff4b2c52d6c2..b02690b5de613 100644 --- a/hw/ip/pwrmgr/rtl/pwrmgr.sv +++ b/hw/ip/pwrmgr/rtl/pwrmgr.sv @@ -11,7 +11,8 @@ module pwrmgr import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*; #( - parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}} + parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, + parameter bit PwrFsmWaitForExtRst = 0 ) ( // Clocks and resets input clk_slow_i, @@ -59,12 +60,13 @@ module pwrmgr input pwr_cpu_t pwr_cpu_i, // SEC_CM: LC_CTRL.INTERSIG.MUBI output lc_ctrl_pkg::lc_tx_t fetch_en_o, - input lc_ctrl_pkg::lc_tx_t lc_hw_debug_en_i, - input lc_ctrl_pkg::lc_tx_t lc_dft_en_i, + input lc_ctrl_pkg::lc_tx_t lc_hw_debug_en_i, + input lc_ctrl_pkg::lc_tx_t lc_dft_en_i, + output pwr_boot_status_t boot_status_o, // peripherals wakeup and reset requests - input [NumWkups-1:0] wakeups_i, - input [NumRstReqs-1:0] rstreqs_i, + input [NumWkups-1:0] wakeups_i, + input [NumRstReqs-1:0] rstreqs_i, // cpu related inputs input ndmreset_req_i, @@ -88,6 +90,11 @@ module pwrmgr output intr_wakeup_o ); + + logic internal_reset_req; + logic strap_sampled; + logic ext_reset_req; + //////////////////////////////////////////////////// // Input handling // //////////////////////////////////////////////////// @@ -504,6 +511,21 @@ module pwrmgr {NumIntRstReqs{1'b1}}, slow_reset_en}; + // TODO(#22711): Make this work also when `rstreqs` is structured differently. + assign internal_reset_req =|( + slow_peri_reqs.rstreqs & + {{NumSwRstReq{1'b1}}, // SW driven reset + {NumDebugRstReqs{1'b1}}, // debugger reset + {NumIntRstReqs{1'b1}}, // {ESC reset, slow_fsm} + // exclude the external async reset + {1'b0, slow_reset_en[0]} + } + ); + + // The MSB of `slow_peri_reqs.rstreqs` is the external reset request. We want it to always + // propagate, in order to continue from the Reset Wait state in the fast FSM. + assign ext_reset_req = slow_peri_reqs.rstreqs[NumRstReqs-1]; + for (genvar i = 0; i < NumWkups; i++) begin : gen_wakeup_status assign hw2reg.wake_status[i].de = 1'b1; assign hw2reg.wake_status[i].d = peri_reqs_masked.wakeups[i]; @@ -574,7 +596,9 @@ module pwrmgr assign low_power_hint = reg2hw.control.low_power_hint.q == LowPower; - pwrmgr_fsm u_fsm ( + pwrmgr_fsm #( + .PwrFsmWaitForExtRst(PwrFsmWaitForExtRst) + ) u_fsm ( .clk_i, .rst_ni, .clk_slow_i, @@ -602,6 +626,8 @@ module pwrmgr .fall_through_o (low_power_fall_through), .abort_o (low_power_abort), .clr_hint_o (clr_hint), + .int_reset_req_i (internal_reset_req), + .ext_reset_req_i (ext_reset_req), // rstmgr .pwr_rst_o (pwr_rst_o), @@ -635,6 +661,7 @@ module pwrmgr // pinmux and other peripherals .strap_o, + .strap_sampled_o (strap_sampled), // to debug monitoring logic .low_power_o ); @@ -685,6 +712,16 @@ module pwrmgr .intr_o (intr_wakeup_o) ); + //////////////////////////////////////////////////// + // Routing sstaus signal outputs for monitoring + //////////////////////////////////////////////////// + assign boot_status_o.cpu_fetch_en = fetch_en_o; + assign boot_status_o.rom_ctrl_status = rom_ctrl_i; + assign boot_status_o.lc_done = pwr_lc_i.lc_done; + assign boot_status_o.otp_done = otp_rsp.otp_done; + assign boot_status_o.clk_status = pwr_clk_i; + assign boot_status_o.light_reset_req = internal_reset_req; + assign boot_status_o.strap_sampled = strap_sampled; //////////////////////////// /// Assertions diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv b/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv index 2bbc5bb975eb6..3145cd3872b59 100644 --- a/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv +++ b/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv @@ -7,7 +7,12 @@ `include "prim_assert.sv" -module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( +module pwrmgr_fsm + import pwrmgr_pkg::*; + import pwrmgr_reg_pkg::*; +#( + parameter bit PwrFsmWaitForExtRst = 0 +) ( input clk_i, input rst_ni, input clk_slow_i, @@ -33,6 +38,9 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( output logic abort_o, output logic clr_hint_o, output logic clr_cfg_lock_o, + input logic int_reset_req_i, // internally generated reset request. + // Send to platform to assert reset + input logic ext_reset_req_i, // Internal Req held until ext reset deasserts // rstmgr output pwr_rst_req_t pwr_rst_o, @@ -63,6 +71,7 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( // pinmux output logic strap_o, + output logic strap_sampled_o, output logic low_power_o, // processing elements @@ -103,7 +112,6 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( // strap sample should only happen on cold boot or when the // the system goes through a reset cycle - logic strap_sampled; // disable processing element fetching lc_ctrl_pkg::lc_tx_t fetch_en_q, fetch_en_d; @@ -118,6 +126,8 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( logic otp_init; logic lc_init; logic low_power_q, low_power_d; + logic ext_rst_req_d, ext_rst_req_q; + logic ext_rst_pending_q; assign pd_n_rsts_asserted = pwr_rst_i.rst_lc_src_n[PowerDomains-1:OffDomainSelStart] == '0 & pwr_rst_i.rst_sys_src_n[PowerDomains-1:OffDomainSelStart] == '0; @@ -153,6 +163,34 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( assign reset_valid = reset_cause_q == LowPwrEntry ? main_pd_ni | pd_n_rsts_asserted : reset_cause_q == HwReq ? all_rsts_asserted : 1'b0; + // Provide the ability to control the reset to OpenTitan RoT from an external source. The logic + // below makes sure that when an internal reset request is generated, it is held high until the + // external SoC reset logic asserts and then deasserts deasserts the external reset signal. The + // pwrmgr fast FSM is held in FastPwrStateResetWait state until the external reset deasserts. + // This ensure that the OT reset exit is synchronized with the rest of the SoC & platform. + if (PwrFsmWaitForExtRst) begin : gen_wait2ext_rst + + assign ext_rst_req_d = ext_reset_req_i; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + ext_rst_pending_q <= 1'b0; + ext_rst_req_q <= 1'b0; + end else begin + ext_rst_req_q <= ext_rst_req_d; + if (ext_rst_pending_q && !ext_rst_req_d && ext_rst_req_q) begin + ext_rst_pending_q <= 1'b0; + end else if (int_reset_req_i) begin + ext_rst_pending_q <= 1'b1; + end + end + end + end else begin : gen_no_wait2ext_rst + assign ext_rst_pending_q = 1'b0; + assign ext_rst_req_q = 1'b0; + assign ext_rst_req_d = 1'b0; + end : gen_no_wait2ext_rst + always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin ack_pwrup_q <= 1'b0; @@ -180,11 +218,11 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin - strap_sampled <= 1'b0; + strap_sampled_o <= 1'b0; end else if (&rst_sys_req_q) begin - strap_sampled <= 1'b0; + strap_sampled_o <= 1'b0; end else if (strap_o) begin - strap_sampled <= 1'b1; + strap_sampled_o <= 1'b1; end end @@ -338,7 +376,7 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( end FastPwrStateStrap: begin - strap_o = ~strap_sampled; + strap_o = ~strap_sampled_o; state_d = FastPwrStateRomCheckDone; end @@ -471,7 +509,9 @@ module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;( // cleared before proceeding. This also implies if the system is under a persistent // glitch, or if someone just turned off the power before pwrmgr turns it off itself, // we will stay stuck here and perpetually hold the system in reset. - if (reset_valid && !reset_reqs_i[ResetMainPwrIdx]) begin + // Need to hold in reset until external reset deasserts (i.e. ext_rst_pending_q goes low) + if (reset_valid && !reset_reqs_i[ResetMainPwrIdx] + && !ext_rst_pending_q ) begin state_d = FastPwrStateLowPower; end end diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv b/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv index c86e8fb4959da..8443603982087 100644 --- a/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv +++ b/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv @@ -155,6 +155,16 @@ package pwrmgr_pkg; logic ndmreset_req; } pwrmgr_cpu_t; + typedef struct packed { + lc_ctrl_pkg::lc_tx_t cpu_fetch_en; + rom_ctrl_pkg::pwrmgr_data_t [pwrmgr_reg_pkg::NumRomInputs-1:0] rom_ctrl_status; + logic lc_done; + logic otp_done; + logic strap_sampled; + logic light_reset_req; + pwr_clk_rsp_t clk_status; + } pwr_boot_status_t; + // exported resets // default value for pwrmgr_ast_rsp_t (for dangling ports) diff --git a/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson b/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson index 16728c62de0d8..478033f9730cc 100644 --- a/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson +++ b/hw/top_darjeeling/data/autogen/top_darjeeling.gen.hjson @@ -310,7 +310,6 @@ domains: [ Aon - "0" ] shadowed: false sw: false @@ -2055,6 +2054,10 @@ { name: pwrmgr_aon type: pwrmgr + param_decl: + { + PwrFsmWaitForExtRst: "1" + } clock_group: powerup clock_srcs: { @@ -2108,10 +2111,34 @@ clk_lc_i: clkmgr_aon_clocks.clk_io_div4_powerup clk_esc_i: clkmgr_aon_clocks.clk_io_div4_secure } - param_decl: {} - param_list: [] + memory: {} + param_list: + [ + { + name: PwrFsmWaitForExtRst + desc: Wait for external reset to complete + type: bit + default: "1" + expose: "true" + name_top: PwrmgrAonPwrFsmWaitForExtRst + } + ] inter_signal_list: [ + { + name: boot_status + struct: pwr_boot_status + package: pwrmgr_pkg + type: uni + act: req + width: 1 + inst_name: pwrmgr_aon + default: "" + external: true + top_signame: pwrmgr_boot_status + conn_type: false + index: -1 + } { name: pwr_ast struct: pwr_ast @@ -3687,12 +3714,17 @@ name: lc domain: "0" } - rst_aon_ni: + rst_por_ni: { - name: lc_aon - domain: "0" + name: por_io_div4 + domain: Aon } } + domain: + [ + Aon + "0" + ] base_addrs: { core: @@ -3722,10 +3754,6 @@ clk_i: clkmgr_aon_clocks.clk_main_infra clk_aon_i: clkmgr_aon_clocks.clk_aon_infra } - domain: - [ - "0" - ] param_decl: {} param_list: [] inter_signal_list: @@ -9604,6 +9632,7 @@ ast.ram_1p_cfg: ram_1p_cfg ast.spi_ram_2p_cfg: spi_ram_2p_cfg ast.rom_cfg: rom_cfg + pwrmgr_aon.boot_status: pwrmgr_boot_status clkmgr_aon.jitter_en: clk_main_jitter_en clkmgr_aon.io_clk_byp_req: io_clk_byp_req clkmgr_aon.io_clk_byp_ack: io_clk_byp_ack @@ -18416,6 +18445,20 @@ top_signame: spi_host0_tl index: -1 } + { + name: boot_status + struct: pwr_boot_status + package: pwrmgr_pkg + type: uni + act: req + width: 1 + inst_name: pwrmgr_aon + default: "" + external: true + top_signame: pwrmgr_boot_status + conn_type: false + index: -1 + } { name: pwr_ast struct: pwr_ast @@ -23530,6 +23573,18 @@ index: -1 netname: ast_rom_cfg } + { + package: pwrmgr_pkg + struct: pwr_boot_status + signame: pwrmgr_boot_status_o + width: 1 + type: uni + default: "" + direction: out + conn_type: false + index: -1 + netname: pwrmgr_boot_status + } { package: prim_mubi_pkg struct: mubi4 diff --git a/hw/top_darjeeling/data/top_darjeeling.hjson b/hw/top_darjeeling/data/top_darjeeling.hjson index 3893f22372097..ff74ba4ab0c30 100644 --- a/hw/top_darjeeling/data/top_darjeeling.hjson +++ b/hw/top_darjeeling/data/top_darjeeling.hjson @@ -292,6 +292,9 @@ }, { name: "pwrmgr_aon", type: "pwrmgr", + param_decl: { + PwrFsmWaitForExtRst: "1" + } clock_group: "powerup", clock_srcs: { clk_i: "io_div4", @@ -510,7 +513,17 @@ type: "soc_proxy", clock_srcs: {clk_i: "main", clk_aon_i: "aon"}, clock_group: "infra", - reset_connections: {rst_ni: "lc", rst_aon_ni: "lc_aon"}, + reset_connections: { + rst_ni: { + name: "lc", + domain: "0", + }, + rst_por_ni: { + name: "por_io_div4", + domain: "Aon", + }, + }, + domain: ["Aon", "0"], base_addrs: { core: {hart: "0x22030000"}, ctn: {hart: "0x40000000"}, @@ -1214,6 +1227,7 @@ 'ast.ram_1p_cfg' : 'ram_1p_cfg', 'ast.spi_ram_2p_cfg' : 'spi_ram_2p_cfg', 'ast.rom_cfg' : 'rom_cfg', + 'pwrmgr_aon.boot_status' : 'pwrmgr_boot_status', 'clkmgr_aon.jitter_en' : 'clk_main_jitter_en', 'clkmgr_aon.io_clk_byp_req' : 'io_clk_byp_req', 'clkmgr_aon.io_clk_byp_ack' : 'io_clk_byp_ack', diff --git a/hw/top_darjeeling/dv/autogen/rstmgr_tgl_excl.cfg b/hw/top_darjeeling/dv/autogen/rstmgr_tgl_excl.cfg index d4763e5384aa2..fb9f50d0f8896 100644 --- a/hw/top_darjeeling/dv/autogen/rstmgr_tgl_excl.cfg +++ b/hw/top_darjeeling/dv/autogen/rstmgr_tgl_excl.cfg @@ -19,6 +19,7 @@ -node tb.dut*.u_rstmgr_aon.resets_o.rst_por_io_n[1] -node tb.dut*.u_rstmgr_aon.resets_o.rst_por_io_div2_n[1] -node tb.dut*.u_rstmgr_aon.resets_o.rst_por_io_div4_n[1] +-node tb.dut*.u_rstmgr_aon.resets_o.rst_lc_aon_n[1] -node tb.dut*.u_rstmgr_aon.resets_o.rst_lc_io_div2_n[1] -node tb.dut*.u_rstmgr_aon.resets_o.rst_sys_n[0] -node tb.dut*.u_rstmgr_aon.resets_o.rst_sys_io_div4_n[1] diff --git a/hw/top_darjeeling/ip/pwrmgr/data/autogen/pwrmgr.hjson b/hw/top_darjeeling/ip/pwrmgr/data/autogen/pwrmgr.hjson index cf513b5249714..725216a362114 100644 --- a/hw/top_darjeeling/ip/pwrmgr/data/autogen/pwrmgr.hjson +++ b/hw/top_darjeeling/ip/pwrmgr/data/autogen/pwrmgr.hjson @@ -69,6 +69,12 @@ ], inter_signal_list: [ + { struct: "pwr_boot_status", + type: "uni", + name: "boot_status", + act: "req", + package: "pwrmgr_pkg", + }, { struct: "pwr_ast", type: "req_rsp", name: "pwr_ast", @@ -257,6 +263,14 @@ }, + { name: "PwrFsmWaitForExtRst", + desc: "Wait for external reset to complete", + type: "bit", + default: "0", + local: "false", + expose: "true" + }, + { name: "NumRstReqs", desc: "Number of peripheral reset requets", type: "int", diff --git a/hw/top_darjeeling/ip/rstmgr/dv/env/autogen/rstmgr_env_pkg.sv b/hw/top_darjeeling/ip/rstmgr/dv/env/autogen/rstmgr_env_pkg.sv index 6923aeceddde0..1d6c4e5194543 100644 --- a/hw/top_darjeeling/ip/rstmgr/dv/env/autogen/rstmgr_env_pkg.sv +++ b/hw/top_darjeeling/ip/rstmgr/dv/env/autogen/rstmgr_env_pkg.sv @@ -47,7 +47,6 @@ package rstmgr_env_pkg; "u_daon_lc", "u_daon_lc_shadowed", "u_daon_lc_aon", - "u_d0_lc_aon", "u_daon_lc_io", "u_d0_lc_io", "u_daon_lc_io_div2", diff --git a/hw/top_darjeeling/ip/rstmgr/rtl/autogen/rstmgr.sv b/hw/top_darjeeling/ip/rstmgr/rtl/autogen/rstmgr.sv index d4ea11bcef2ab..c66faa19b5f34 100644 --- a/hw/top_darjeeling/ip/rstmgr/rtl/autogen/rstmgr.sv +++ b/hw/top_darjeeling/ip/rstmgr/rtl/autogen/rstmgr.sv @@ -585,7 +585,7 @@ module rstmgr end // Generating resets for lc_aon - // Power Domains: ['Aon', '0'] + // Power Domains: ['Aon'] // Shadowed: False rstmgr_leaf_rst #( .SecCheck(SecCheck), @@ -611,30 +611,10 @@ module rstmgr u_daon_lc_aon.gen_rst_chk.u_rst_chk.u_state_regs, alert_tx_o[0]) end - rstmgr_leaf_rst #( - .SecCheck(SecCheck), - .SecMaxSyncDelay(SecMaxSyncDelay), - .SwRstReq(1'b0) - ) u_d0_lc_aon ( - .clk_i, - .rst_ni, - .leaf_clk_i(clk_aon_i), - .parent_rst_ni(rst_lc_src_n[Domain0Sel]), - .sw_rst_req_ni(1'b1), - .scan_rst_ni, - .scanmode_i, - .rst_en_o(rst_en_o.lc_aon[Domain0Sel]), - .leaf_rst_o(resets_o.rst_lc_aon_n[Domain0Sel]), - .err_o(cnsty_chk_errs[6][Domain0Sel]), - .fsm_err_o(fsm_errs[6][Domain0Sel]) - ); - - if (SecCheck) begin : gen_d0_lc_aon_assert - `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT( - D0LcAonFsmCheck_A, - u_d0_lc_aon.gen_rst_chk.u_rst_chk.u_state_regs, - alert_tx_o[0]) - end + assign resets_o.rst_lc_aon_n[Domain0Sel] = '0; + assign cnsty_chk_errs[6][Domain0Sel] = '0; + assign fsm_errs[6][Domain0Sel] = '0; + assign rst_en_o.lc_aon[Domain0Sel] = MuBi4True; assign shadow_cnsty_chk_errs[6] = '0; assign shadow_fsm_errs[6] = '0; diff --git a/hw/top_darjeeling/ip/soc_proxy/data/soc_proxy.hjson b/hw/top_darjeeling/ip/soc_proxy/data/soc_proxy.hjson index e1d97d87177f8..5ed02a0438df1 100644 --- a/hw/top_darjeeling/ip/soc_proxy/data/soc_proxy.hjson +++ b/hw/top_darjeeling/ip/soc_proxy/data/soc_proxy.hjson @@ -33,7 +33,7 @@ clocking: [ { clock: "clk_i", reset: "rst_ni", primary: true } - { clock: "clk_aon_i", reset: "rst_aon_ni" } + { clock: "clk_aon_i", reset: "rst_por_ni" } ] bus_interfaces: [ diff --git a/hw/top_darjeeling/ip/soc_proxy/rtl/soc_proxy.sv b/hw/top_darjeeling/ip/soc_proxy/rtl/soc_proxy.sv index c8fb7eb163655..cf63a793843b1 100644 --- a/hw/top_darjeeling/ip/soc_proxy/rtl/soc_proxy.sv +++ b/hw/top_darjeeling/ip/soc_proxy/rtl/soc_proxy.sv @@ -15,7 +15,7 @@ module soc_proxy input logic clk_i, input logic rst_ni, input logic clk_aon_i, - input logic rst_aon_ni, + input logic rst_por_ni, input tlul_pkg::tl_h2d_t core_tl_i, output tlul_pkg::tl_d2h_t core_tl_o, @@ -373,7 +373,7 @@ module soc_proxy .Width(1) ) u_prim_flop_2sync_soc_wkup ( .clk_i (clk_aon_i), - .rst_ni (rst_aon_ni), + .rst_ni (rst_por_ni), .d_i (soc_wkup_async_i), .q_o (wkup_external_req_o) ); @@ -388,7 +388,7 @@ module soc_proxy .Cycles(3) ) u_prim_filter_wkup ( .clk_i (clk_aon_i), - .rst_ni (rst_aon_ni), + .rst_ni (rst_por_ni), .enable_i (1'b1), .filter_i (async_wkup), .filter_o (wkup_internal_req_o) @@ -400,7 +400,7 @@ module soc_proxy .Cycles(4) ) u_prim_filter_soc_rst_req ( .clk_i (clk_aon_i), - .rst_ni (rst_aon_ni), + .rst_ni (rst_por_ni), .enable_i (1'b1), .filter_i (soc_rst_req_async_i), .filter_o (rst_req_external_o) diff --git a/hw/top_darjeeling/rtl/autogen/chip_darjeeling_asic.sv b/hw/top_darjeeling/rtl/autogen/chip_darjeeling_asic.sv index 9918f78ad39c2..492ea9dd85594 100644 --- a/hw/top_darjeeling/rtl/autogen/chip_darjeeling_asic.sv +++ b/hw/top_darjeeling/rtl/autogen/chip_darjeeling_asic.sv @@ -1035,6 +1035,7 @@ module chip_darjeeling_asic #( // pwrmgr interface pwrmgr_pkg::pwr_ast_req_t base_ast_pwr; pwrmgr_pkg::pwr_ast_rsp_t ast_base_pwr; + pwrmgr_pkg::pwr_boot_status_t pwrmgr_boot_status; // assorted ast status ast_pkg::ast_pwst_t ast_pwst; @@ -1513,6 +1514,35 @@ module chip_darjeeling_asic #( {soc_proxy_pkg::NumFatalExternalAlerts{soc_proxy_pkg::SOC_ALERT_REQ_DEFAULT}}; assign soc_recov_alert_req = {soc_proxy_pkg::NumRecovExternalAlerts{soc_proxy_pkg::SOC_ALERT_REQ_DEFAULT}}; + // The logic below is a is a loopback path. It listens to the internal reset request generated by + // the power manager and translates this request into a stretched pulse (modeled by the counter). + // The stretched pulse is fed back to top_darjeeling as external async SoC reset request. + // TODO(#22710): This should be moved to the DV environment, and we need to extend the code to be + // able to asynchronously assert the external reset pin without any internal request. + logic internal_request_d, internal_request_q; + logic external_reset, count_up; + logic [3:0] count; + assign internal_request_d = pwrmgr_boot_status.light_reset_req; + always_ff @(posedge ast_base_clks.clk_aon or negedge por_n[0]) begin + if (!por_n[0]) begin + external_reset <= 1'b0; + internal_request_q <= 1'b0; + count_up <= '0; + count <= '0; + end else begin + internal_request_q <= internal_request_d; + if (!internal_request_q && internal_request_d) begin + count_up <= 1'b1; + external_reset <= 1; + end else if (count == 'd8) begin + count_up <= 0; + external_reset <= 0; + count <= '0; + end else if (count_up) begin + count <= count + 1; + end + end + end ////////////////////// // Top-level design // @@ -1556,13 +1586,15 @@ module chip_darjeeling_asic #( .dma_ctn_tl_d2h_i ( ctn_tl_d2h[1] ), .mbx_tl_req_i ( tlul_pkg::TL_H2D_DEFAULT ), .mbx_tl_rsp_o ( ), + .pwrmgr_boot_status_o ( pwrmgr_boot_status ), .soc_fatal_alert_req_i ( soc_fatal_alert_req ), .soc_fatal_alert_rsp_o ( ), .soc_recov_alert_req_i ( soc_recov_alert_req ), .soc_recov_alert_rsp_o ( ), .soc_intr_async_i ( '0 ), .soc_wkup_async_i ( 1'b0 ), - .soc_rst_req_async_i ( 1'b0 ), + // TODO(#22710): this should come from modeled SoC (e.g., from TB). + .soc_rst_req_async_i ( external_reset ), .soc_lsio_trigger_i ( '0 ), .entropy_src_hw_if_req_o ( entropy_src_hw_if_req ), .entropy_src_hw_if_rsp_i ( entropy_src_hw_if_rsp ), diff --git a/hw/top_darjeeling/rtl/autogen/chip_darjeeling_cw310.sv b/hw/top_darjeeling/rtl/autogen/chip_darjeeling_cw310.sv index 3178a740b4ddf..9b28f0721dd11 100644 --- a/hw/top_darjeeling/rtl/autogen/chip_darjeeling_cw310.sv +++ b/hw/top_darjeeling/rtl/autogen/chip_darjeeling_cw310.sv @@ -875,6 +875,7 @@ module chip_darjeeling_cw310 #( // pwrmgr interface pwrmgr_pkg::pwr_ast_req_t base_ast_pwr; pwrmgr_pkg::pwr_ast_rsp_t ast_base_pwr; + pwrmgr_pkg::pwr_boot_status_t pwrmgr_boot_status; // assorted ast status ast_pkg::ast_pwst_t ast_pwst; @@ -1362,6 +1363,7 @@ module chip_darjeeling_cw310 #( assign srst_n = manual_in_por_button_n; + ////////////////////// // Top-level design // ////////////////////// diff --git a/hw/top_darjeeling/rtl/autogen/top_darjeeling.sv b/hw/top_darjeeling/rtl/autogen/top_darjeeling.sv index 4c5ea9885b947..c974cfd4e15b1 100644 --- a/hw/top_darjeeling/rtl/autogen/top_darjeeling.sv +++ b/hw/top_darjeeling/rtl/autogen/top_darjeeling.sv @@ -33,6 +33,7 @@ module top_darjeeling #( // parameters for alert_handler // parameters for spi_host0 // parameters for pwrmgr_aon + parameter bit PwrmgrAonPwrFsmWaitForExtRst = 1, // parameters for rstmgr_aon parameter bit SecRstmgrAonCheck = 1'b1, parameter int SecRstmgrAonMaxSyncDelay = 2, @@ -148,6 +149,7 @@ module top_darjeeling #( input prim_ram_1p_pkg::ram_1p_cfg_t ram_1p_cfg_i, input prim_ram_2p_pkg::ram_2p_cfg_t spi_ram_2p_cfg_i, input prim_rom_pkg::rom_cfg_t rom_cfg_i, + output pwrmgr_pkg::pwr_boot_status_t pwrmgr_boot_status_o, output prim_mubi_pkg::mubi4_t clk_main_jitter_en_o, output prim_mubi_pkg::mubi4_t io_clk_byp_req_o, input prim_mubi_pkg::mubi4_t io_clk_byp_ack_i, @@ -1293,7 +1295,8 @@ module top_darjeeling #( .rst_ni (rstmgr_aon_resets.rst_spi_host0_n[rstmgr_pkg::Domain0Sel]) ); pwrmgr #( - .AlertAsyncOn(alert_handler_reg_pkg::AsyncOn[14:14]) + .AlertAsyncOn(alert_handler_reg_pkg::AsyncOn[14:14]), + .PwrFsmWaitForExtRst(PwrmgrAonPwrFsmWaitForExtRst) ) u_pwrmgr_aon ( // Interrupt @@ -1303,6 +1306,7 @@ module top_darjeeling #( .alert_rx_i ( alert_rx[14:14] ), // Inter-module signals + .boot_status_o(pwrmgr_boot_status_o), .pwr_ast_o(pwrmgr_ast_req_o), .pwr_ast_i(pwrmgr_ast_rsp_i), .pwr_rst_o(pwrmgr_aon_pwr_rst_req), @@ -1623,7 +1627,7 @@ module top_darjeeling #( .clk_i (clkmgr_aon_clocks.clk_main_infra), .clk_aon_i (clkmgr_aon_clocks.clk_aon_infra), .rst_ni (rstmgr_aon_resets.rst_lc_n[rstmgr_pkg::Domain0Sel]), - .rst_aon_ni (rstmgr_aon_resets.rst_lc_aon_n[rstmgr_pkg::Domain0Sel]) + .rst_por_ni (rstmgr_aon_resets.rst_por_io_div4_n[rstmgr_pkg::DomainAonSel]) ); sram_ctrl #( .AlertAsyncOn(alert_handler_reg_pkg::AsyncOn[52:52]), diff --git a/hw/top_darjeeling/rtl/chip_darjeeling_verilator.sv b/hw/top_darjeeling/rtl/chip_darjeeling_verilator.sv index 39928e209fdde..2779497f29f35 100644 --- a/hw/top_darjeeling/rtl/chip_darjeeling_verilator.sv +++ b/hw/top_darjeeling/rtl/chip_darjeeling_verilator.sv @@ -164,6 +164,7 @@ module chip_darjeeling_verilator ( // pwrmgr interface pwrmgr_pkg::pwr_ast_req_t base_ast_pwr; pwrmgr_pkg::pwr_ast_rsp_t ast_base_pwr; + pwrmgr_pkg::pwr_boot_status_t pwrmgr_boot_status; ast_pkg::ast_clks_t ast_base_clks; @@ -540,6 +541,36 @@ module chip_darjeeling_verilator ( logic [rstmgr_pkg::PowerDomains-1:0] por_n; assign por_n = {ast_pwst.main_pok, ast_pwst.aon_pok}; + // The logic below is a is a loopback path. It listens to the internal reset request generated by + // the power manager and translates this request into a stretched pulse (modeled by the counter). + // The stretched pulse is fed back to top_darjeeling as external async SoC reset request. + // TODO(#22710): This should be moved to the DV environment, and we need to extend the code to be + // able to asynchronously assert the external reset pin without any internal request. + logic internal_request_d, internal_request_q; + logic external_reset, count_up; + logic [3:0] count; + assign internal_request_d = pwrmgr_boot_status.light_reset_req; + always_ff @(posedge ast_base_clks.clk_aon or negedge por_n[0]) begin + if (!por_n[0]) begin + external_reset <= 1'b0; + internal_request_q <= 1'b0; + count_up <= '0; + count <= '0; + end else begin + internal_request_q <= internal_request_d; + if (!internal_request_q && internal_request_d) begin + count_up <= 1'b1; + external_reset <= 1; + end else if (count == 'd8) begin + count_up <= 0; + external_reset <= 0; + count <= '0; + end else if (count_up) begin + count <= count + 1; + end + end + end + top_darjeeling #( .PinmuxAonTargetCfg(PinmuxTargetCfg), .SecAesAllowForcingMasks(1'b1), @@ -593,13 +624,15 @@ module chip_darjeeling_verilator ( .dma_sys_rsp_i ( '0 ), .dma_ctn_tl_h2d_o ( ), .dma_ctn_tl_d2h_i ( tlul_pkg::TL_D2H_DEFAULT ), + .pwrmgr_boot_status_o ( pwrmgr_boot_status ), .soc_fatal_alert_req_i ( 1'b0 ), .soc_fatal_alert_rsp_o ( ), .soc_recov_alert_req_i ( ), .soc_recov_alert_rsp_o ( ), .soc_intr_async_i ( '0 ), .soc_wkup_async_i ( 1'b0 ), - .soc_rst_req_async_i ( 1'b0 ), + // TODO(#22710): this should come from modeled SoC (e.g., from TB). + .soc_rst_req_async_i ( external_reset), .soc_lsio_trigger_i ( '0 ), // OTP external voltage diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson index d6679910b2957..0ffefc38b735a 100644 --- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson +++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson @@ -2873,9 +2873,30 @@ clk_esc_i: clkmgr_aon_clocks.clk_io_div4_secure } param_decl: {} - param_list: [] + memory: {} + param_list: + [ + { + name: PwrFsmWaitForExtRst + desc: Wait for external reset to complete + type: bit + default: "0" + expose: "true" + name_top: PwrmgrAonPwrFsmWaitForExtRst + } + ] inter_signal_list: [ + { + name: boot_status + struct: pwr_boot_status + package: pwrmgr_pkg + type: uni + act: req + width: 1 + inst_name: pwrmgr_aon + index: -1 + } { name: pwr_ast struct: pwr_ast @@ -17147,6 +17168,16 @@ top_signame: usbdev_tl index: -1 } + { + name: boot_status + struct: pwr_boot_status + package: pwrmgr_pkg + type: uni + act: req + width: 1 + inst_name: pwrmgr_aon + index: -1 + } { name: pwr_ast struct: pwr_ast diff --git a/hw/top_earlgrey/ip/pwrmgr/data/autogen/pwrmgr.hjson b/hw/top_earlgrey/ip/pwrmgr/data/autogen/pwrmgr.hjson index f58eb4ce30333..9a8681ca2a632 100644 --- a/hw/top_earlgrey/ip/pwrmgr/data/autogen/pwrmgr.hjson +++ b/hw/top_earlgrey/ip/pwrmgr/data/autogen/pwrmgr.hjson @@ -69,6 +69,12 @@ ], inter_signal_list: [ + { struct: "pwr_boot_status", + type: "uni", + name: "boot_status", + act: "req", + package: "pwrmgr_pkg", + }, { struct: "pwr_ast", type: "req_rsp", name: "pwr_ast", @@ -257,6 +263,14 @@ }, + { name: "PwrFsmWaitForExtRst", + desc: "Wait for external reset to complete", + type: "bit", + default: "0", + local: "false", + expose: "true" + }, + { name: "NumRstReqs", desc: "Number of peripheral reset requets", type: "int", diff --git a/hw/top_earlgrey/rtl/autogen/chip_earlgrey_cw310.sv b/hw/top_earlgrey/rtl/autogen/chip_earlgrey_cw310.sv index 846beec5314dd..edfad81678840 100644 --- a/hw/top_earlgrey/rtl/autogen/chip_earlgrey_cw310.sv +++ b/hw/top_earlgrey/rtl/autogen/chip_earlgrey_cw310.sv @@ -976,6 +976,7 @@ module chip_earlgrey_cw310 #( assign srst_n = manual_in_por_button_n; + ////////////////////// // Top-level design // ////////////////////// diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv index 397cc8ba53efc..b834ef660bec4 100644 --- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv +++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv @@ -44,6 +44,7 @@ module top_earlgrey #( parameter bit UsbdevStub = 0, parameter int UsbdevRcvrWakeTimeUs = 100, // parameters for pwrmgr_aon + parameter bit PwrmgrAonPwrFsmWaitForExtRst = 0, // parameters for rstmgr_aon parameter bit SecRstmgrAonCheck = 1'b1, parameter int SecRstmgrAonMaxSyncDelay = 2, @@ -1703,7 +1704,8 @@ module top_earlgrey #( .rst_aon_ni (rstmgr_aon_resets.rst_usb_aon_n[rstmgr_pkg::Domain0Sel]) ); pwrmgr #( - .AlertAsyncOn(alert_handler_reg_pkg::AsyncOn[22:22]) + .AlertAsyncOn(alert_handler_reg_pkg::AsyncOn[22:22]), + .PwrFsmWaitForExtRst(PwrmgrAonPwrFsmWaitForExtRst) ) u_pwrmgr_aon ( // Interrupt @@ -1713,6 +1715,7 @@ module top_earlgrey #( .alert_rx_i ( alert_rx[22:22] ), // Inter-module signals + .boot_status_o(), .pwr_ast_o(pwrmgr_ast_req_o), .pwr_ast_i(pwrmgr_ast_rsp_i), .pwr_rst_o(pwrmgr_aon_pwr_rst_req), diff --git a/util/topgen/templates/chiplevel.sv.tpl b/util/topgen/templates/chiplevel.sv.tpl index 6e07e3eeb6e60..8cd816a60e0bd 100644 --- a/util/topgen/templates/chiplevel.sv.tpl +++ b/util/topgen/templates/chiplevel.sv.tpl @@ -498,6 +498,9 @@ module chip_${top["name"]}_${target["name"]} #( // pwrmgr interface pwrmgr_pkg::pwr_ast_req_t base_ast_pwr; pwrmgr_pkg::pwr_ast_rsp_t ast_base_pwr; +% if top["name"] == "darjeeling": + pwrmgr_pkg::pwr_boot_status_t pwrmgr_boot_status; +% endif // assorted ast status ast_pkg::ast_pwst_t ast_pwst; @@ -1222,6 +1225,35 @@ module chip_${top["name"]}_${target["name"]} #( {soc_proxy_pkg::NumFatalExternalAlerts{soc_proxy_pkg::SOC_ALERT_REQ_DEFAULT}}; assign soc_recov_alert_req = {soc_proxy_pkg::NumRecovExternalAlerts{soc_proxy_pkg::SOC_ALERT_REQ_DEFAULT}}; + // The logic below is a is a loopback path. It listens to the internal reset request generated by + // the power manager and translates this request into a stretched pulse (modeled by the counter). + // The stretched pulse is fed back to top_darjeeling as external async SoC reset request. + // TODO(#22710): This should be moved to the DV environment, and we need to extend the code to be + // able to asynchronously assert the external reset pin without any internal request. + logic internal_request_d, internal_request_q; + logic external_reset, count_up; + logic [3:0] count; + assign internal_request_d = pwrmgr_boot_status.light_reset_req; + always_ff @(posedge ast_base_clks.clk_aon or negedge por_n[0]) begin + if (!por_n[0]) begin + external_reset <= 1'b0; + internal_request_q <= 1'b0; + count_up <= '0; + count <= '0; + end else begin + internal_request_q <= internal_request_d; + if (!internal_request_q && internal_request_d) begin + count_up <= 1'b1; + external_reset <= 1; + end else if (count == 'd8) begin + count_up <= 0; + external_reset <= 0; + count <= '0; + end else if (count_up) begin + count <= count + 1; + end + end + end % endif ////////////////////// @@ -1288,13 +1320,15 @@ module chip_${top["name"]}_${target["name"]} #( .dma_ctn_tl_d2h_i ( ctn_tl_d2h[1] ), .mbx_tl_req_i ( tlul_pkg::TL_H2D_DEFAULT ), .mbx_tl_rsp_o ( ), + .pwrmgr_boot_status_o ( pwrmgr_boot_status ), .soc_fatal_alert_req_i ( soc_fatal_alert_req ), .soc_fatal_alert_rsp_o ( ), .soc_recov_alert_req_i ( soc_recov_alert_req ), .soc_recov_alert_rsp_o ( ), .soc_intr_async_i ( '0 ), .soc_wkup_async_i ( 1'b0 ), - .soc_rst_req_async_i ( 1'b0 ), + // TODO(#22710): this should come from modeled SoC (e.g., from TB). + .soc_rst_req_async_i ( external_reset ), .soc_lsio_trigger_i ( '0 ), .entropy_src_hw_if_req_o ( entropy_src_hw_if_req ), .entropy_src_hw_if_rsp_i ( entropy_src_hw_if_rsp ), @@ -1438,6 +1472,7 @@ module chip_${top["name"]}_${target["name"]} #( assign otp_obs_o = '0; % endif + ////////////////////// // Top-level design // //////////////////////