From cfa86b293dd07cc5153ae6b4669baf4363a65269 Mon Sep 17 00:00:00 2001 From: Simone Machetti <79547828+simone-machetti@users.noreply.github.com> Date: Thu, 13 Oct 2022 19:28:18 +0200 Subject: [PATCH] memory and peripheral power domains and fast interrupts (#122) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Solved issue #96. Added 2 timers into the ao_peripheral_subsystem and 2 timers into the peripheral_subsystem. * Solved issues #16 and #95. Connected each interrupt to the assigned destination. * Fixed code after review. * Done a parse with Verible. * Solved issue #120. Added wake-up events to power_manager. * Fixed a bug in the interrupt mapping. * Added peripheral_subsystem power domain. * Fixed a bug in power_manager.sv. * Added ram power domains. * Fixed code after review. * Added automatic generation of ram blocks support. * Done a parse with Verible. * Fixed code after review. * Updated .gitignore. * Updated interrupt assignments as previously discussed. * Added core-v-mini-mcu.upf to .gitignore. * Modified .gitignore. * UP template comments and multilines commands. * Solved multi-lines and comments problems during tpl files generation. * Removed automatic generation for power_manager.c. * Updated sw to support fast interrupts. * Added CSR registers saving during core power-gating. * Updated Makefile. * Added example_power_gating_periph and example_power_gating_ram_blocks. * Done a parse with Verible. * Updated .gitignore. * Added plic wake-up event to power_manager. * Added initial version of fast_intr_ctrl module. * Improved fast_intr_ctrl module. * Fixed a bug in spi_host_example.c. * Added interrupt array to power_manager input. * Updated example_power_gating_core.c app. * Ordered interrupts in power_manager. * Added clear fast interrupt in power_manager.c. * Done a parse with Verible. * Solved issue #148. * Fixed a bug in power_manager.hjson.tpl. * Fixed a bug in power_manager.hjson.tpl. * Added iso counters. * Added other iso counters. * Done a parse with Verible. * minor SW updates * update fast interrupt * remove reset mem domain * Fixed a non-functional bug in interrupt handlers. * Improved power_manager.c. * Updated vertors.S. * Updated Makefile. Co-authored-by: Machetti Simone Co-authored-by: BenoƮt Denkinger Co-authored-by: davide schiavone --- .gitignore | 16 +- Makefile | 10 +- core-v-mini-mcu.core | 2 + core-v-mini-mcu.upf | 75 - core-v-mini-mcu.upf.tpl | 156 ++ hw/core-v-mini-mcu/ao_peripheral_subsystem.sv | 159 +- hw/core-v-mini-mcu/core_v_mini_mcu.sv | 254 +- .../include/core_v_mini_mcu_pkg.sv.tpl | 61 +- hw/core-v-mini-mcu/memory_subsystem.sv | 2 + hw/core-v-mini-mcu/peripheral_subsystem.sv | 151 +- hw/core-v-mini-mcu/spi_subsystem.sv | 13 +- hw/ip/boot_rom/boot_rom.dump | 6 +- hw/ip/boot_rom/boot_rom.h | 6 +- hw/ip/boot_rom/boot_rom.sv | 6 +- .../fast_intr_ctrl/data/fast_intr_ctrl.hjson | 32 + hw/ip/fast_intr_ctrl/fast_intr_ctrl.core | 24 + hw/ip/fast_intr_ctrl/fast_intr_ctrl.sh | 5 + hw/ip/fast_intr_ctrl/fast_intr_ctrl.vlt | 9 + hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl.sv | 74 + .../rtl/fast_intr_ctrl_reg_pkg.sv | 59 + .../rtl/fast_intr_ctrl_reg_top.sv | 181 ++ hw/ip/power_manager/data/power_manager.hjson | 460 ---- .../data/power_manager.hjson.tpl | 403 ++++ hw/ip/power_manager/data/power_manager.sv.tpl | 500 ++++ hw/ip/power_manager/power_manager.vlt | 1 + hw/ip/power_manager/rtl/power_manager.sv | 168 -- .../rtl/power_manager_reg_pkg.sv | 364 --- .../rtl/power_manager_reg_top.sv | 2120 ----------------- .../hw/ip/rv_timer/data/rv_timer.hjson | 100 +- .../hw/ip/rv_timer/rtl/rv_timer.sv | 92 +- .../hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv | 159 +- .../hw/ip/rv_timer/rtl/rv_timer_reg_top.sv | 435 +++- .../patches/lowrisc_opentitan/rv_timer.patch | 1020 +++++++- mcu_cfg.hjson | 132 +- sw/Makefile | 41 +- sw/applications/dma_example/dma_example.c | 64 +- .../example_power_gating_core.c | 110 +- .../example_power_gating_periph.c | 50 + .../example_power_gating_ram_blocks.c | 59 + sw/applications/gpio_pmw/gpio_pmw.c | 3 - sw/applications/matadd/matadd.c | 7 +- sw/applications/matadd/matrixAdd32.h | 96 +- .../spi_host_dma_example.c | 58 +- .../spi_host_example/spi_host_example.c | 49 +- sw/device/lib/crt/vectors.S | 32 +- sw/device/lib/crt_flash_exec/vectors.S | 32 +- sw/device/lib/crt_flash_load/vectors.S | 32 +- .../drivers/fast_intr_ctrl/fast_intr_ctrl.c | 24 + .../drivers/fast_intr_ctrl/fast_intr_ctrl.h | 62 + .../fast_intr_ctrl/fast_intr_ctrl_regs.h | 37 + .../power_manager/data/power_manager.h.tpl | 103 + .../lib/drivers/power_manager/power_manager.c | 206 +- .../lib/drivers/power_manager/power_manager.h | 70 - .../power_manager/power_manager_regs.h | 179 -- .../lib/drivers/rv_timer/rv_timer_regs.h | 55 +- sw/device/lib/runtime/core_v_mini_mcu.h.tpl | 58 +- sw/device/lib/runtime/handler.c | 78 + sw/device/lib/runtime/handler.h | 108 +- util/mcu_gen.py | 101 +- 59 files changed, 4698 insertions(+), 4271 deletions(-) delete mode 100644 core-v-mini-mcu.upf create mode 100644 core-v-mini-mcu.upf.tpl create mode 100644 hw/ip/fast_intr_ctrl/data/fast_intr_ctrl.hjson create mode 100644 hw/ip/fast_intr_ctrl/fast_intr_ctrl.core create mode 100644 hw/ip/fast_intr_ctrl/fast_intr_ctrl.sh create mode 100644 hw/ip/fast_intr_ctrl/fast_intr_ctrl.vlt create mode 100644 hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl.sv create mode 100644 hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl_reg_pkg.sv create mode 100644 hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl_reg_top.sv delete mode 100644 hw/ip/power_manager/data/power_manager.hjson create mode 100644 hw/ip/power_manager/data/power_manager.hjson.tpl create mode 100644 hw/ip/power_manager/data/power_manager.sv.tpl delete mode 100644 hw/ip/power_manager/rtl/power_manager.sv delete mode 100644 hw/ip/power_manager/rtl/power_manager_reg_pkg.sv delete mode 100644 hw/ip/power_manager/rtl/power_manager_reg_top.sv create mode 100644 sw/applications/example_power_gating_periph/example_power_gating_periph.c create mode 100644 sw/applications/example_power_gating_ram_blocks/example_power_gating_ram_blocks.c create mode 100644 sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.c create mode 100644 sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.h create mode 100644 sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl_regs.h create mode 100644 sw/device/lib/drivers/power_manager/data/power_manager.h.tpl delete mode 100644 sw/device/lib/drivers/power_manager/power_manager.h delete mode 100644 sw/device/lib/drivers/power_manager/power_manager_regs.h diff --git a/.gitignore b/.gitignore index 95a0da1e0..4d3c5330a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,13 +8,23 @@ build/ *.map *.do -# ignore core-v-mini-mcu pkg that is automatically generated by Makefile +# ignore the following hw automatically generated files +core-v-mini-mcu.upf +tb/tb_util.svh hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv hw/core-v-mini-mcu/system_bus.sv hw/core-v-mini-mcu/pad_ring.sv -tb/tb_util.svh -# same for the C header file and linker scripts +hw/ip/power_manager/data/power_manager.hjson +hw/ip/power_manager/rtl/power_manager.sv +hw/ip/power_manager/rtl/power_manager_reg_top.sv +hw/ip/power_manager/rtl/power_manager_reg_pkg.sv + +# ignore the following sw automatically generated files sw/device/lib/runtime/core_v_mini_mcu.h sw/linker/link.ld +sw/linker/link_spiflash.ld +sw/linker/link_spihost.ld sw/linker/link_flash_exec.ld sw/linker/link_flash_load.ld +sw/device/lib/drivers/power_manager/power_manager_regs.h +sw/device/lib/drivers/power_manager/power_manager.h diff --git a/Makefile b/Makefile index 39e1307fc..3c1b631a8 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ .PHONY: clean help -TARGET ?= sim +TARGET ?= sim # Generates mcu files mcu-gen: @@ -15,11 +15,17 @@ mcu-gen: python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir hw/core-v-mini-mcu/ --memorybanks $(MEMORY_BANKS) --tpl-sv hw/core-v-mini-mcu/system_bus.sv.tpl python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir tb/ --memorybanks $(MEMORY_BANKS) --tpl-sv tb/tb_util.svh.tpl python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir hw/core-v-mini-mcu/ --tpl-sv hw/core-v-mini-mcu/pad_ring.sv.tpl - python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir sw/device/lib/runtime --cpu $(CPU) --header-c sw/device/lib/runtime/core_v_mini_mcu.h.tpl + python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir sw/device/lib/runtime --cpu $(CPU) --memorybanks $(MEMORY_BANKS) --header-c sw/device/lib/runtime/core_v_mini_mcu.h.tpl python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir sw/linker --memorybanks $(MEMORY_BANKS) --linker_script sw/linker/link.ld.tpl + python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir . --memorybanks $(MEMORY_BANKS) --pkg-sv ./core-v-mini-mcu.upf.tpl + python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir hw/ip/power_manager/rtl --memorybanks $(MEMORY_BANKS) --pkg-sv hw/ip/power_manager/data/power_manager.sv.tpl + python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir hw/ip/power_manager/data --memorybanks $(MEMORY_BANKS) --pkg-sv hw/ip/power_manager/data/power_manager.hjson.tpl + bash -c "cd hw/ip/power_manager; source power_manager_gen.sh; cd ../../../" + python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir sw/device/lib/drivers/power_manager --memorybanks $(MEMORY_BANKS) --pkg-sv sw/device/lib/drivers/power_manager/data/power_manager.h.tpl python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir sw/linker --memorybanks $(MEMORY_BANKS) --linker_script sw/linker/link_flash_exec.ld.tpl python util/mcu_gen.py --cfg mcu_cfg.hjson --outdir sw/linker --memorybanks $(MEMORY_BANKS) --linker_script sw/linker/link_flash_load.ld.tpl $(MAKE) verible + # Display mcu_gen.py help mcu-gen-help: python util/mcu_gen.py -h diff --git a/core-v-mini-mcu.core b/core-v-mini-mcu.core index 486112f82..53c481358 100644 --- a/core-v-mini-mcu.core +++ b/core-v-mini-mcu.core @@ -30,6 +30,7 @@ filesets: - x-heep:ip:boot_rom - x-heep:ip:dma - x-heep:ip:power_manager + - x-heep:ip:fast_intr_ctrl - x-heep:ip:pad_attribute files: - hw/core-v-mini-mcu/core_v_mini_mcu.sv @@ -70,6 +71,7 @@ filesets: - hw/ip/obi_spimemio/obi_spimemio.vlt - hw/ip/dma/dma.vlt - hw/ip/power_manager/power_manager.vlt + - hw/ip/fast_intr_ctrl/fast_intr_ctrl.vlt - hw/ip/pad_attribute/pad_attribute.vlt file_type: vlt diff --git a/core-v-mini-mcu.upf b/core-v-mini-mcu.upf deleted file mode 100644 index 5250c05d7..000000000 --- a/core-v-mini-mcu.upf +++ /dev/null @@ -1,75 +0,0 @@ -upf_version 2.1 - -set_design_top core_v_mini_mcu -set_scope . - -##################### -## POWER DOMAINS ## -##################### - -create_power_domain PD_TOP -include_scope -create_power_domain PD_CPU -elements {cpu_subsystem_i} - - -#################### -## POWER STATES ## -#################### - -add_power_state PD_CPU.primary -state CPU_ON \ - {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} - -add_power_state PD_CPU.primary -state CPU_OFF \ - {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT - -add_power_state PD_TOP.primary -state TOP_ON \ - {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} - - -################### -## SUPPLY NETS ## -################### - -create_supply_port VDD -direction in -create_supply_port VSS -direction in - -create_supply_net VDD -create_supply_net VSS - -connect_supply_net VDD -ports VDD -connect_supply_net VSS -ports VSS - -create_supply_set PD_TOP.primary -function {power VDD} -function {ground VSS} -update - -create_supply_net VDD_CPU -create_supply_set PD_CPU.primary -function {power VDD_CPU} -function {ground VSS} -update - - -################ -## SWITCHES ## -################ - - -create_power_switch switch_PD_CPU \ - -supply_set PD_TOP.primary \ - -domain PD_CPU \ - -input_supply_port {sw_in VDD} \ - -output_supply_port {sw_out VDD_CPU} \ - -control_port {sw_ctrl cpu_subsystem_powergate_switch} \ - -on_state {on_state sw_in {sw_ctrl}} \ - -off_state {off_state {!sw_ctrl}} - - -################# -## ISOLATION ## -################# - -set_isolation cpu_iso \ - -domain PD_CPU \ - -isolation_power_net VDD \ - -isolation_ground_net VSS \ - -isolation_signal cpu_subsystem_powergate_switch \ - -isolation_sense low \ - -clamp_value 0 \ - -applies_to both \ - -name_prefix cpu_iso_cell \ - -location parent diff --git a/core-v-mini-mcu.upf.tpl b/core-v-mini-mcu.upf.tpl new file mode 100644 index 000000000..1be3ce5d7 --- /dev/null +++ b/core-v-mini-mcu.upf.tpl @@ -0,0 +1,156 @@ +upf_version 2.1 + +set_design_top core_v_mini_mcu +set_scope . + + +<%text> +##################### +## POWER DOMAINS ## +##################### +\ + +create_power_domain PD_TOP -include_scope +create_power_domain PD_CPU -elements {cpu_subsystem_i} +create_power_domain PD_PERIP_SUBS -elements {peripheral_subsystem_i} +% for bank in range(ram_numbanks): +create_power_domain PD_MEM_BANK_${bank} -elements {memory_subsystem_i/gen_sram[${bank}].ram_i} +% endfor + + +<%text> +#################### +## POWER STATES ## +#################### +\ + +add_power_state PD_TOP.primary -state TOP_ON <%text>\ + {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} + +add_power_state PD_CPU.primary -state CPU_ON <%text>\ + {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} + +add_power_state PD_CPU.primary -state CPU_OFF <%text>\ + {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT + +add_power_state PD_PERIP_SUBS.primary -state PERIP_SUBS_ON <%text>\ + {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} + +add_power_state PD_PERIP_SUBS.primary -state PERIP_SUBS_OFF <%text>\ + {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT + +% for bank in range(ram_numbanks): +add_power_state PD_MEM_BANK_${bank}.primary -state MEM_BANK_${bank}_ON <%text>\ + {-supply_expr {power == `{FULL_ON, 1.2} && ground == `{FULL_ON, 0.0}}} + +add_power_state PD_MEM_BANK_${bank}.primary -state MEM_BANK_${bank}_OFF <%text>\ + {-supply_expr {power == `{OFF} && ground == `{FULL_ON, 0.0}}} -simstate CORRUPT + +% endfor + +<%text> +################### +## SUPPLY NETS ## +################### +\ + +create_supply_port VDD -direction in +create_supply_port VSS -direction in + +create_supply_net VDD +create_supply_net VSS + +connect_supply_net VDD -ports VDD +connect_supply_net VSS -ports VSS + +create_supply_set PD_TOP.primary -function {power VDD} -function {ground VSS} -update + +create_supply_net VDD_CPU +create_supply_set PD_CPU.primary -function {power VDD_CPU} -function {ground VSS} -update + +create_supply_net VDD_PERIP_SUBS +create_supply_set PD_PERIP_SUBS.primary -function {power VDD_PERIP_SUBS} -function {ground VSS} -update + +% for bank in range(ram_numbanks): +create_supply_net VDD_MEM_BANK_${bank} +create_supply_set PD_MEM_BANK_${bank}.primary -function {power VDD_MEM_BANK_${bank}} -function {ground VSS} -update + +% endfor + +<%text> +################ +## SWITCHES ## +################ +\ + +create_power_switch switch_PD_CPU <%text>\ + -supply_set PD_TOP.primary <%text>\ + -domain PD_CPU <%text>\ + -input_supply_port {sw_in VDD} <%text>\ + -output_supply_port {sw_out VDD_CPU} <%text>\ + -control_port {sw_ctrl cpu_subsystem_powergate_switch} <%text>\ + -on_state {on_state sw_in {sw_ctrl}} <%text>\ + -off_state {off_state {!sw_ctrl}} + +create_power_switch switch_PD_PERIP_SUBS <%text>\ + -supply_set PD_TOP.primary <%text>\ + -domain PD_PERIP_SUBS <%text>\ + -input_supply_port {sw_in VDD} <%text>\ + -output_supply_port {sw_out VDD_PERIP_SUBS} <%text>\ + -control_port {sw_ctrl peripheral_subsystem_powergate_switch} <%text>\ + -on_state {on_state sw_in {sw_ctrl}} <%text>\ + -off_state {off_state {!sw_ctrl}} + +% for bank in range(ram_numbanks): +create_power_switch switch_PD_MEM_BANK_${bank} <%text>\ + -supply_set PD_TOP.primary <%text>\ + -domain PD_MEM_BANK_${bank} <%text>\ + -input_supply_port {sw_in VDD} <%text>\ + -output_supply_port {sw_out VDD_MEM_BANK_${bank}} <%text>\ + -control_port {sw_ctrl memory_subsystem_banks_powergate_switch[${bank}]} <%text>\ + -on_state {on_state sw_in {sw_ctrl}} <%text>\ + -off_state {off_state {!sw_ctrl}} + +% endfor + +<%text> +################# +## ISOLATION ## +################# +\ + +set_isolation cpu_iso <%text>\ + -domain PD_CPU <%text>\ + -isolation_power_net VDD <%text>\ + -isolation_ground_net VSS <%text>\ + -isolation_signal cpu_subsystem_powergate_iso <%text>\ + -isolation_sense low <%text>\ + -clamp_value 0 <%text>\ + -applies_to both <%text>\ + -name_prefix cpu_iso_cell <%text>\ + -location parent + +set_isolation perip_subs_iso <%text>\ + -domain PD_PERIP_SUBS <%text>\ + -isolation_power_net VDD <%text>\ + -isolation_ground_net VSS <%text>\ + -isolation_signal peripheral_subsystem_powergate_iso <%text>\ + -isolation_sense low <%text>\ + -clamp_value 0 <%text>\ + -applies_to both <%text>\ + -name_prefix cpu_iso_cell <%text>\ + -location parent + +% for bank in range(ram_numbanks): +set_isolation mem_bank_${bank}_iso <%text>\ + -domain PD_MEM_BANK_${bank} <%text>\ + -isolation_power_net VDD <%text>\ + -isolation_ground_net VSS <%text>\ + -isolation_signal memory_subsystem_banks_powergate_iso[${bank}] <%text>\ + -isolation_sense low <%text>\ + -clamp_value 0 <%text>\ + -applies_to both <%text>\ + -name_prefix cpu_iso_cell <%text>\ + -location parent + +% endfor diff --git a/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv b/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv index fd7854aa7..c5387d0ae 100644 --- a/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv +++ b/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv @@ -12,7 +12,7 @@ module ao_peripheral_subsystem input obi_req_t slave_req_i, output obi_resp_t slave_resp_o, - //SOC CTRL + // SOC CTRL input logic boot_select_i, input logic execute_from_flash_i, output logic exit_valid_o, @@ -39,14 +39,25 @@ module ao_peripheral_subsystem output logic [ 3:0] spi_sd_o, output logic [ 3:0] spi_sd_en_o, input logic [ 3:0] spi_sd_i, + output logic spi_intr_event_o, + output logic spi_flash_intr_event_o, // POWER MANAGER - input logic core_sleep_i, - output logic cpu_subsystem_powergate_switch_o, - output logic cpu_subsystem_rst_no, + input logic [ 31:0] intr_i, + input logic [ core_v_mini_mcu_pkg::NEXT_INT-1:0] ext_intr_i, + input logic core_sleep_i, + output logic cpu_subsystem_powergate_switch_o, + output logic cpu_subsystem_powergate_iso_o, + output logic peripheral_subsystem_powergate_switch_o, + output logic peripheral_subsystem_powergate_iso_o, + output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_o, + output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso_o, + output logic cpu_subsystem_rst_no, + output logic peripheral_subsystem_rst_no, //RV TIMER - output logic rv_timer_irq_timer_o, + output logic rv_timer_0_intr_o, + output logic rv_timer_1_intr_o, // DMA output obi_req_t dma_master0_ch0_req_o, @@ -54,13 +65,17 @@ module ao_peripheral_subsystem output obi_req_t dma_master1_ch0_req_o, input obi_resp_t dma_master1_ch0_resp_i, output logic dma_intr_o, - output logic spi_flash_intr_error_o, - output logic spi_flash_intr_event_o, - output logic spi_intr_error_o, - output logic spi_intr_event_o, - output logic [core_v_mini_mcu_pkg::NUM_PAD-1:0][15:0] pad_attributes_o + // FAST INTR CTRL + input logic [14:0] fast_intr_i, + output logic [14:0] fast_intr_o, + + // EXTERNAL PERIPH + output reg_req_t ext_peripheral_slave_req_o, + input reg_rsp_t ext_peripheral_slave_resp_i, + // PADS + output logic [core_v_mini_mcu_pkg::NUM_PAD-1:0][15:0] pad_attributes_o ); import core_v_mini_mcu_pkg::*; @@ -70,8 +85,8 @@ module ao_peripheral_subsystem reg_pkg::reg_req_t peripheral_req; reg_pkg::reg_rsp_t peripheral_rsp; - reg_pkg::reg_req_t [core_v_mini_mcu_pkg::AO_PERIPHERALS-1:0] peripheral_slv_req; - reg_pkg::reg_rsp_t [core_v_mini_mcu_pkg::AO_PERIPHERALS-1:0] peripheral_slv_rsp; + reg_pkg::reg_req_t [core_v_mini_mcu_pkg::AO_PERIPHERALS-1:0] ao_peripheral_slv_req; + reg_pkg::reg_rsp_t [core_v_mini_mcu_pkg::AO_PERIPHERALS-1:0] ao_peripheral_slv_rsp; tlul_pkg::tl_h2d_t rv_timer_tl_h2d; tlul_pkg::tl_d2h_t rv_timer_tl_d2h; @@ -79,14 +94,15 @@ module ao_peripheral_subsystem logic [AO_PERIPHERALS_PORT_SEL_WIDTH-1:0] peripheral_select; logic use_spimemio; - logic rv_timer_irq_timer; - // SPI->DMA Interface logic spi_rx_valid; logic spi_tx_ready; logic spi_flash_rx_valid; logic spi_flash_tx_ready; + assign ext_peripheral_slave_req_o = ao_peripheral_slv_req[core_v_mini_mcu_pkg::EXT_PERIPH_IDX]; + assign ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::EXT_PERIPH_IDX] = ext_peripheral_slave_resp_i; + periph_to_reg #( .req_t(reg_pkg::reg_req_t), .rsp_t(reg_pkg::reg_rsp_t), @@ -134,8 +150,8 @@ module ao_peripheral_subsystem .in_select_i(peripheral_select), .in_req_i(peripheral_req), .in_rsp_o(peripheral_rsp), - .out_req_o(peripheral_slv_req), - .out_rsp_i(peripheral_slv_rsp) + .out_req_o(ao_peripheral_slv_req), + .out_rsp_i(ao_peripheral_slv_rsp) ); soc_ctrl #( @@ -144,8 +160,8 @@ module ao_peripheral_subsystem ) soc_ctrl_i ( .clk_i, .rst_ni, - .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::SOC_CTRL_IDX]), - .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::SOC_CTRL_IDX]), + .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::SOC_CTRL_IDX]), + .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::SOC_CTRL_IDX]), .boot_select_i, .execute_from_flash_i, .use_spimemio_o(use_spimemio), @@ -154,8 +170,8 @@ module ao_peripheral_subsystem ); boot_rom boot_rom_i ( - .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::BOOTROM_IDX]), - .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::BOOTROM_IDX]) + .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::BOOTROM_IDX]), + .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::BOOTROM_IDX]) ); spi_subsystem spi_subsystem_i ( @@ -164,10 +180,10 @@ module ao_peripheral_subsystem .use_spimemio_i(use_spimemio), .spimemio_req_i, .spimemio_resp_o, - .yo_reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::SPI_MEMIO_IDX]), - .yo_reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_MEMIO_IDX]), - .ot_reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::SPI_FLASH_IDX]), - .ot_reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_FLASH_IDX]), + .yo_reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::SPI_MEMIO_IDX]), + .yo_reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_MEMIO_IDX]), + .ot_reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::SPI_FLASH_IDX]), + .ot_reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_FLASH_IDX]), .spi_flash_sck_o, .spi_flash_sck_en_o, .spi_flash_csb_o, @@ -175,24 +191,54 @@ module ao_peripheral_subsystem .spi_flash_sd_o, .spi_flash_sd_en_o, .spi_flash_sd_i, - .spi_flash_intr_error_o, + .spi_flash_intr_error_o(), .spi_flash_intr_event_o, .spi_flash_rx_valid_o(spi_flash_rx_valid), .spi_flash_tx_ready_o(spi_flash_tx_ready) ); + spi_host #( + .reg_req_t(reg_pkg::reg_req_t), + .reg_rsp_t(reg_pkg::reg_rsp_t) + ) spi_host_dma_i ( + .clk_i, + .rst_ni, + .clk_core_i(clk_i), + .rst_core_ni(rst_ni), + .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::SPI_IDX]), + .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_IDX]), + .cio_sck_o(spi_sck_o), + .cio_sck_en_o(spi_sck_en_o), + .cio_csb_o(spi_csb_o), + .cio_csb_en_o(spi_csb_en_o), + .cio_sd_o(spi_sd_o), + .cio_sd_en_o(spi_sd_en_o), + .cio_sd_i(spi_sd_i), + .rx_valid_o(spi_rx_valid), + .tx_ready_o(spi_tx_ready), + .intr_error_o(), + .intr_spi_event_o(spi_intr_event_o) + ); + power_manager #( .reg_req_t(reg_pkg::reg_req_t), .reg_rsp_t(reg_pkg::reg_rsp_t) ) power_manager_i ( .clk_i, .rst_ni, - .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::POWER_MANAGER_IDX]), - .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::POWER_MANAGER_IDX]), - .rv_timer_irq_i(rv_timer_irq_timer), + .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::POWER_MANAGER_IDX]), + .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::POWER_MANAGER_IDX]), + .intr_i, + .ext_irq_i(ext_intr_i), .core_sleep_i, .cpu_subsystem_powergate_switch_o, - .cpu_subsystem_rst_no + .cpu_subsystem_powergate_iso_o, + .peripheral_subsystem_powergate_switch_o, + .peripheral_subsystem_powergate_iso_o, + .memory_subsystem_banks_powergate_switch_o, + .memory_subsystem_banks_powergate_iso_o, + .cpu_subsystem_rst_no, + .peripheral_subsystem_rst_no ); reg_to_tlul #( @@ -208,20 +254,19 @@ module ao_peripheral_subsystem ) rv_timer_reg_to_tlul_i ( .tl_o(rv_timer_tl_h2d), .tl_i(rv_timer_tl_d2h), - .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::RV_TIMER_IDX]), - .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::RV_TIMER_IDX]) + .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::RV_TIMER_AO_IDX]), + .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::RV_TIMER_AO_IDX]) ); - rv_timer rv_timer_i ( + rv_timer rv_timer_0_1_i ( .clk_i, .rst_ni, .tl_i(rv_timer_tl_h2d), .tl_o(rv_timer_tl_d2h), - .intr_timer_expired_0_0_o(rv_timer_irq_timer) + .intr_timer_expired_0_0_o(rv_timer_0_intr_o), + .intr_timer_expired_1_0_o(rv_timer_1_intr_o) ); - assign rv_timer_irq_timer_o = rv_timer_irq_timer; - dma #( .reg_req_t (reg_pkg::reg_req_t), .reg_rsp_t (reg_pkg::reg_rsp_t), @@ -230,8 +275,8 @@ module ao_peripheral_subsystem ) dma_i ( .clk_i, .rst_ni, - .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::DMA_IDX]), - .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::DMA_IDX]), + .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::DMA_IDX]), + .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::DMA_IDX]), .dma_master0_ch0_req_o, .dma_master0_ch0_resp_i, .dma_master1_ch0_req_o, @@ -243,40 +288,28 @@ module ao_peripheral_subsystem .dma_intr_o ); - pad_attribute #( + fast_intr_ctrl #( .reg_req_t(reg_pkg::reg_req_t), - .reg_rsp_t(reg_pkg::reg_rsp_t), - .NUM_PAD (core_v_mini_mcu_pkg::NUM_PAD) - ) pad_attribute_i ( + .reg_rsp_t(reg_pkg::reg_rsp_t) + ) fast_intr_ctrl_i ( .clk_i, .rst_ni, - .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::PAD_ATTRIBUTE_IDX]), - .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::PAD_ATTRIBUTE_IDX]), - .pad_attributes_o + .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::FAST_INTR_CTRL_IDX]), + .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::FAST_INTR_CTRL_IDX]), + .fast_intr_i, + .fast_intr_o ); - //OpenTitan SPI Snitch Version connected to DMA - spi_host #( + pad_attribute #( .reg_req_t(reg_pkg::reg_req_t), - .reg_rsp_t(reg_pkg::reg_rsp_t) - ) spi_host_dma_i ( + .reg_rsp_t(reg_pkg::reg_rsp_t), + .NUM_PAD (core_v_mini_mcu_pkg::NUM_PAD) + ) pad_attribute_i ( .clk_i, .rst_ni, - .clk_core_i(clk_i), - .rst_core_ni(rst_ni), - .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::SPI_IDX]), - .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::SPI_IDX]), - .cio_sck_o(spi_sck_o), - .cio_sck_en_o(spi_sck_en_o), - .cio_csb_o(spi_csb_o), - .cio_csb_en_o(spi_csb_en_o), - .cio_sd_o(spi_sd_o), - .cio_sd_en_o(spi_sd_en_o), - .cio_sd_i(spi_sd_i), - .rx_valid_o(spi_rx_valid), - .tx_ready_o(spi_tx_ready), - .intr_error_o(spi_intr_error_o), - .intr_spi_event_o(spi_intr_event_o) + .reg_req_i(ao_peripheral_slv_req[core_v_mini_mcu_pkg::PAD_ATTRIBUTE_IDX]), + .reg_rsp_o(ao_peripheral_slv_rsp[core_v_mini_mcu_pkg::PAD_ATTRIBUTE_IDX]), + .pad_attributes_o ); diff --git a/hw/core-v-mini-mcu/core_v_mini_mcu.sv b/hw/core-v-mini-mcu/core_v_mini_mcu.sv index 72e28878d..cdd41ec51 100644 --- a/hw/core-v-mini-mcu/core_v_mini_mcu.sv +++ b/hw/core-v-mini-mcu/core_v_mini_mcu.sv @@ -71,6 +71,8 @@ module core_v_mini_mcu end `endif + logic clk, rst_n, boot_select, execute_from_flash, exit_valid; + // masters signals obi_req_t core_instr_req; obi_resp_t core_instr_resp; @@ -100,6 +102,13 @@ module core_v_mini_mcu // signals to debug unit logic debug_core_req; + // jtag + logic jtag_tck; + logic jtag_tms; + logic jtag_trst_n; + logic jtag_tdi; + logic jtag_tdo; + // core logic core_sleep; @@ -107,14 +116,8 @@ module core_v_mini_mcu logic irq_ack; logic [4:0] irq_id_out; logic irq_software; - logic irq_timer; logic irq_external; - logic [15:0] irq_fast; - - // gpio signals - logic [31:0] gpio_in; - logic [31:0] gpio_out; - logic [31:0] gpio_en; + logic [14:0] irq_fast; // SPI Interface (YosysHW SPI and OpenTitan SPI multiplexed) logic spi_flash_sck; @@ -124,6 +127,8 @@ module core_v_mini_mcu logic [3:0] spi_flash_sd_out; logic [3:0] spi_flash_sd_en; logic [3:0] spi_flash_sd_in; + logic spi_flash_intr; + // Memory Map SPI Region obi_req_t flash_mem_slave_req; obi_resp_t flash_mem_slave_resp; @@ -136,12 +141,37 @@ module core_v_mini_mcu logic [3:0] spi_sd_out; logic [3:0] spi_sd_en; logic [3:0] spi_sd_in; + logic spi_intr; // power manager logic cpu_subsystem_powergate_switch; + logic cpu_subsystem_powergate_iso; + logic peripheral_subsystem_powergate_switch; + logic peripheral_subsystem_powergate_iso; + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch; + logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso; logic cpu_subsystem_rst_n; + logic peripheral_subsystem_rst_n; + + // rv_timer + logic [3:0] rv_timer_intr; + + // dma + logic dma_intr; + + // fast intr ctrl + logic [14:0] fast_intr; + + // uart + logic uart_rx, uart_tx; - // I2C + // gpio signals + logic [31:0] gpio_in; + logic [31:0] gpio_out; + logic [31:0] gpio_en; + logic [7:0] gpio_intr; + + // i2c logic cio_scl_in; logic cio_scl_out; logic cio_scl_en; @@ -149,23 +179,12 @@ module core_v_mini_mcu logic cio_sda_out; logic cio_sda_en; - // DMA - logic dma_intr; - logic spi_flash_intr_error; - logic spi_flash_intr_event; - logic spi_intr_error; - logic spi_intr_event; - - logic clk, rst_n, boot_select, execute_from_flash, exit_valid; - logic jtag_tck; - logic jtag_tms; - logic jtag_trst_n; - logic jtag_tdi; - logic jtag_tdo; - logic uart_rx, uart_tx; - + // pads logic [core_v_mini_mcu_pkg::NUM_PAD-1:0][15:0] pad_attributes; + // interrupt array + logic [31:0] intr; + cpu_subsystem #( .BOOT_ADDR(BOOT_ADDR), .PULP_XPULP(PULP_XPULP), @@ -174,21 +193,33 @@ module core_v_mini_mcu .NUM_MHPMCOUNTERS(NUM_MHPMCOUNTERS), .DM_HALTADDRESS(DM_HALTADDRESS) ) cpu_subsystem_i ( - // Clock and Reset .clk_i(clk), .rst_ni(cpu_subsystem_rst_n), .core_instr_req_o(core_instr_req), .core_instr_resp_i(core_instr_resp), .core_data_req_o(core_data_req), .core_data_resp_i(core_data_resp), - .irq_i({irq_fast, 4'b0, irq_external, 3'b0, irq_timer, 3'b0, irq_software, 3'b0}), + .irq_i(intr), .irq_ack_o(irq_ack), .irq_id_o(irq_id_out), .debug_req_i(debug_core_req), .core_sleep_o(core_sleep) ); - assign irq_fast = '0; + assign intr = { + 1'b0, irq_fast, 4'b0, irq_external, 3'b0, rv_timer_intr[0], 3'b0, irq_software, 3'b0 + }; + + assign fast_intr = { + 1'b0, + gpio_intr, + spi_flash_intr, + spi_intr, + dma_intr, + rv_timer_intr[3], + rv_timer_intr[2], + rv_timer_intr[1] + }; debug_subsystem #( .JTAG_IDCODE(JTAG_IDCODE) @@ -211,32 +242,32 @@ module core_v_mini_mcu .NUM_BANKS(core_v_mini_mcu_pkg::NUM_BANKS), .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER) ) system_bus_i ( - .clk_i (clk), - .rst_ni (rst_n), - .core_instr_req_i (core_instr_req), - .core_instr_resp_o (core_instr_resp), - .core_data_req_i (core_data_req), - .core_data_resp_o (core_data_resp), - .debug_master_req_i (debug_master_req), - .debug_master_resp_o (debug_master_resp), - .dma_master0_ch0_req_i (dma_master0_ch0_req), - .dma_master0_ch0_resp_o (dma_master0_ch0_resp), - .dma_master1_ch0_req_i (dma_master1_ch0_req), - .dma_master1_ch0_resp_o (dma_master1_ch0_resp), - .ext_xbar_master_req_i (ext_xbar_master_req_i), - .ext_xbar_master_resp_o (ext_xbar_master_resp_o), - .ram_req_o (ram_slave_req), - .ram_resp_i (ram_slave_resp), - .debug_slave_req_o (debug_slave_req), - .debug_slave_resp_i (debug_slave_resp), - .ao_peripheral_slave_req_o (ao_peripheral_slave_req), + .clk_i(clk), + .rst_ni(rst_n), + .core_instr_req_i(core_instr_req), + .core_instr_resp_o(core_instr_resp), + .core_data_req_i(core_data_req), + .core_data_resp_o(core_data_resp), + .debug_master_req_i(debug_master_req), + .debug_master_resp_o(debug_master_resp), + .dma_master0_ch0_req_i(dma_master0_ch0_req), + .dma_master0_ch0_resp_o(dma_master0_ch0_resp), + .dma_master1_ch0_req_i(dma_master1_ch0_req), + .dma_master1_ch0_resp_o(dma_master1_ch0_resp), + .ext_xbar_master_req_i(ext_xbar_master_req_i), + .ext_xbar_master_resp_o(ext_xbar_master_resp_o), + .ram_req_o(ram_slave_req), + .ram_resp_i(ram_slave_resp), + .debug_slave_req_o(debug_slave_req), + .debug_slave_resp_i(debug_slave_resp), + .ao_peripheral_slave_req_o(ao_peripheral_slave_req), .ao_peripheral_slave_resp_i(ao_peripheral_slave_resp), - .peripheral_slave_req_o (peripheral_slave_req), - .peripheral_slave_resp_i (peripheral_slave_resp), - .flash_mem_slave_req_o (flash_mem_slave_req), - .flash_mem_slave_resp_i (flash_mem_slave_resp), - .ext_xbar_slave_req_o (ext_xbar_slave_req_o), - .ext_xbar_slave_resp_i (ext_xbar_slave_resp_i) + .peripheral_slave_req_o(peripheral_slave_req), + .peripheral_slave_resp_i(peripheral_slave_resp), + .flash_mem_slave_req_o(flash_mem_slave_req), + .flash_mem_slave_resp_i(flash_mem_slave_resp), + .ext_xbar_slave_req_o(ext_xbar_slave_req_o), + .ext_xbar_slave_resp_i(ext_xbar_slave_resp_i) ); memory_subsystem #( @@ -273,19 +304,30 @@ module core_v_mini_mcu .spi_sd_o(spi_sd_out), .spi_sd_en_o(spi_sd_en), .spi_sd_i(spi_sd_in), + .spi_intr_event_o(spi_intr), + .spi_flash_intr_event_o(spi_flash_intr), + .intr_i(intr), + .ext_intr_i(intr_vector_ext_i), .core_sleep_i(core_sleep), .cpu_subsystem_powergate_switch_o(cpu_subsystem_powergate_switch), + .cpu_subsystem_powergate_iso_o(cpu_subsystem_powergate_iso), + .peripheral_subsystem_powergate_switch_o(peripheral_subsystem_powergate_switch), + .peripheral_subsystem_powergate_iso_o(peripheral_subsystem_powergate_iso), + .memory_subsystem_banks_powergate_switch_o(memory_subsystem_banks_powergate_switch), + .memory_subsystem_banks_powergate_iso_o(memory_subsystem_banks_powergate_iso), .cpu_subsystem_rst_no(cpu_subsystem_rst_n), - .rv_timer_irq_timer_o(irq_timer), + .peripheral_subsystem_rst_no(peripheral_subsystem_rst_n), + .rv_timer_0_intr_o(rv_timer_intr[0]), + .rv_timer_1_intr_o(rv_timer_intr[1]), .dma_master0_ch0_req_o(dma_master0_ch0_req), .dma_master0_ch0_resp_i(dma_master0_ch0_resp), .dma_master1_ch0_req_o(dma_master1_ch0_req), .dma_master1_ch0_resp_i(dma_master1_ch0_resp), .dma_intr_o(dma_intr), - .spi_flash_intr_error_o(spi_flash_intr_error), - .spi_flash_intr_event_o(spi_flash_intr_event), - .spi_intr_error_o(spi_intr_error), - .spi_intr_event_o(spi_intr_event), + .fast_intr_i(fast_intr), + .fast_intr_o(irq_fast), + .ext_peripheral_slave_req_o, + .ext_peripheral_slave_resp_i, .pad_attributes_o(pad_attributes) ); @@ -293,7 +335,7 @@ module core_v_mini_mcu .NEXT_INT(NEXT_INT) ) peripheral_subsystem_i ( .clk_i(clk), - .rst_ni(rst_n), + .rst_ni(peripheral_subsystem_rst_n), .slave_req_i(peripheral_slave_req), .slave_resp_o(peripheral_slave_resp), .intr_vector_ext_i, @@ -305,303 +347,235 @@ module core_v_mini_mcu .cio_gpio_i(gpio_in), .cio_gpio_o(gpio_out), .cio_gpio_en_o(gpio_en), + .cio_gpio_intr_o(gpio_intr), .cio_scl_i(cio_scl_in), .cio_scl_o(cio_scl_out), .cio_scl_en_o(cio_scl_en), .cio_sda_i(cio_sda_in), .cio_sda_o(cio_sda_out), .cio_sda_en_o(cio_sda_en), - .ext_peripheral_slave_req_o(ext_peripheral_slave_req_o), - .ext_peripheral_slave_resp_i(ext_peripheral_slave_resp_i), - .dma_intr_i(dma_intr), - .spi_flash_intr_error_i(spi_flash_intr_error), - .spi_flash_intr_event_i(spi_flash_intr_event), - .spi_intr_error_i(spi_intr_error), - .spi_intr_event_i(spi_intr_event) + .rv_timer_2_intr_o(rv_timer_intr[2]), + .rv_timer_3_intr_o(rv_timer_intr[3]) ); pad_ring pad_ring_i ( - .clk_io(clk_i), - .clk_o (clk), - + .clk_o(clk), .rst_io(rst_ni), - .rst_o (rst_n), - + .rst_o(rst_n), .boot_select_io(boot_select_i), - .boot_select_o (boot_select), - + .boot_select_o(boot_select), .execute_from_flash_io(execute_from_flash_i), - .execute_from_flash_o (execute_from_flash), - + .execute_from_flash_o(execute_from_flash), .jtag_tck_io(jtag_tck_i), - .jtag_tck_o (jtag_tck), - + .jtag_tck_o(jtag_tck), .jtag_tms_io(jtag_tms_i), - .jtag_tms_o (jtag_tms), - + .jtag_tms_o(jtag_tms), .jtag_trst_io(jtag_trst_ni), - .jtag_trst_o (jtag_trst_n), - + .jtag_trst_o(jtag_trst_n), .jtag_tdi_io(jtag_tdi_i), - .jtag_tdi_o (jtag_tdi), - + .jtag_tdi_o(jtag_tdi), .jtag_tdo_io(jtag_tdo_o), - .jtag_tdo_i (jtag_tdo), - + .jtag_tdo_i(jtag_tdo), .uart_rx_io(uart_rx_i), - .uart_rx_o (uart_rx), - + .uart_rx_o(uart_rx), .uart_tx_io(uart_tx_o), - .uart_tx_i (uart_tx), - + .uart_tx_i(uart_tx), .exit_valid_io(exit_valid_o), - .exit_valid_i (exit_valid), - + .exit_valid_i(exit_valid), .gpio_0_io(gpio_io[0]), .gpio_0_i(gpio_out[0]), .gpio_0_o(gpio_in[0]), .gpio_0_oe_i(gpio_en[0]), - .gpio_1_io(gpio_io[1]), .gpio_1_i(gpio_out[1]), .gpio_1_o(gpio_in[1]), .gpio_1_oe_i(gpio_en[1]), - .gpio_2_io(gpio_io[2]), .gpio_2_i(gpio_out[2]), .gpio_2_o(gpio_in[2]), .gpio_2_oe_i(gpio_en[2]), - .gpio_3_io(gpio_io[3]), .gpio_3_i(gpio_out[3]), .gpio_3_o(gpio_in[3]), .gpio_3_oe_i(gpio_en[3]), - .gpio_4_io(gpio_io[4]), .gpio_4_i(gpio_out[4]), .gpio_4_o(gpio_in[4]), .gpio_4_oe_i(gpio_en[4]), - .gpio_5_io(gpio_io[5]), .gpio_5_i(gpio_out[5]), .gpio_5_o(gpio_in[5]), .gpio_5_oe_i(gpio_en[5]), - .gpio_6_io(gpio_io[6]), .gpio_6_i(gpio_out[6]), .gpio_6_o(gpio_in[6]), .gpio_6_oe_i(gpio_en[6]), - .gpio_7_io(gpio_io[7]), .gpio_7_i(gpio_out[7]), .gpio_7_o(gpio_in[7]), .gpio_7_oe_i(gpio_en[7]), - .gpio_8_io(gpio_io[8]), .gpio_8_i(gpio_out[8]), .gpio_8_o(gpio_in[8]), .gpio_8_oe_i(gpio_en[8]), - .gpio_9_io(gpio_io[9]), .gpio_9_i(gpio_out[9]), .gpio_9_o(gpio_in[9]), .gpio_9_oe_i(gpio_en[9]), - .gpio_10_io(gpio_io[10]), .gpio_10_i(gpio_out[10]), .gpio_10_o(gpio_in[10]), .gpio_10_oe_i(gpio_en[10]), - .gpio_11_io(gpio_io[11]), .gpio_11_i(gpio_out[11]), .gpio_11_o(gpio_in[11]), .gpio_11_oe_i(gpio_en[11]), - .gpio_12_io(gpio_io[12]), .gpio_12_i(gpio_out[12]), .gpio_12_o(gpio_in[12]), .gpio_12_oe_i(gpio_en[12]), - .gpio_13_io(gpio_io[13]), .gpio_13_i(gpio_out[13]), .gpio_13_o(gpio_in[13]), .gpio_13_oe_i(gpio_en[13]), - .gpio_14_io(gpio_io[14]), .gpio_14_i(gpio_out[14]), .gpio_14_o(gpio_in[14]), .gpio_14_oe_i(gpio_en[14]), - .gpio_15_io(gpio_io[15]), .gpio_15_i(gpio_out[15]), .gpio_15_o(gpio_in[15]), .gpio_15_oe_i(gpio_en[15]), - .gpio_16_io(gpio_io[16]), .gpio_16_i(gpio_out[16]), .gpio_16_o(gpio_in[16]), .gpio_16_oe_i(gpio_en[16]), - .gpio_17_io(gpio_io[17]), .gpio_17_i(gpio_out[17]), .gpio_17_o(gpio_in[17]), .gpio_17_oe_i(gpio_en[17]), - .gpio_18_io(gpio_io[18]), .gpio_18_i(gpio_out[18]), .gpio_18_o(gpio_in[18]), .gpio_18_oe_i(gpio_en[18]), - .gpio_19_io(gpio_io[19]), .gpio_19_i(gpio_out[19]), .gpio_19_o(gpio_in[19]), .gpio_19_oe_i(gpio_en[19]), - .gpio_20_io(gpio_io[20]), .gpio_20_i(gpio_out[20]), .gpio_20_o(gpio_in[20]), .gpio_20_oe_i(gpio_en[20]), - .gpio_21_io(gpio_io[21]), .gpio_21_i(gpio_out[21]), .gpio_21_o(gpio_in[21]), .gpio_21_oe_i(gpio_en[21]), - .gpio_22_io(gpio_io[22]), .gpio_22_i(gpio_out[22]), .gpio_22_o(gpio_in[22]), .gpio_22_oe_i(gpio_en[22]), - .gpio_23_io(gpio_io[23]), .gpio_23_i(gpio_out[23]), .gpio_23_o(gpio_in[23]), .gpio_23_oe_i(gpio_en[23]), - .gpio_24_io(gpio_io[24]), .gpio_24_i(gpio_out[24]), .gpio_24_o(gpio_in[24]), .gpio_24_oe_i(gpio_en[24]), - .gpio_25_io(gpio_io[25]), .gpio_25_i(gpio_out[25]), .gpio_25_o(gpio_in[25]), .gpio_25_oe_i(gpio_en[25]), - .gpio_26_io(gpio_io[26]), .gpio_26_i(gpio_out[26]), .gpio_26_o(gpio_in[26]), .gpio_26_oe_i(gpio_en[26]), - .gpio_27_io(gpio_io[27]), .gpio_27_i(gpio_out[27]), .gpio_27_o(gpio_in[27]), .gpio_27_oe_i(gpio_en[27]), - .gpio_28_io(gpio_io[28]), .gpio_28_i(gpio_out[28]), .gpio_28_o(gpio_in[28]), .gpio_28_oe_i(gpio_en[28]), - .gpio_29_io(gpio_io[29]), .gpio_29_i(gpio_out[29]), .gpio_29_o(gpio_in[29]), .gpio_29_oe_i(gpio_en[29]), - .gpio_30_io(gpio_io[30]), .gpio_30_i(gpio_out[30]), .gpio_30_o(gpio_in[30]), .gpio_30_oe_i(gpio_en[30]), - .gpio_31_io(gpio_io[31]), .gpio_31_i(gpio_out[31]), .gpio_31_o(gpio_in[31]), .gpio_31_oe_i(gpio_en[31]), - .spi_flash_sck_io(spi_flash_sck_o), .spi_flash_sck_i(spi_flash_sck), .spi_flash_sck_o(), .spi_flash_sck_oe_i(spi_flash_sck_en), - .spi_flash_cs_0_io(spi_flash_csb_o[0]), .spi_flash_cs_0_i(spi_flash_csb[0]), .spi_flash_cs_0_o(), .spi_flash_cs_0_oe_i(spi_flash_csb_en[0]), - .spi_flash_cs_1_io(spi_flash_csb_o[1]), .spi_flash_cs_1_i(spi_flash_csb[1]), .spi_flash_cs_1_o(), .spi_flash_cs_1_oe_i(spi_flash_csb_en[1]), - .spi_flash_sd_0_io(spi_flash_sd_io[0]), .spi_flash_sd_0_i(spi_flash_sd_out[0]), .spi_flash_sd_0_o(spi_flash_sd_in[0]), .spi_flash_sd_0_oe_i(spi_flash_sd_en[0]), - .spi_flash_sd_1_io(spi_flash_sd_io[1]), .spi_flash_sd_1_i(spi_flash_sd_out[1]), .spi_flash_sd_1_o(spi_flash_sd_in[1]), .spi_flash_sd_1_oe_i(spi_flash_sd_en[1]), - .spi_flash_sd_2_io(spi_flash_sd_io[2]), .spi_flash_sd_2_i(spi_flash_sd_out[2]), .spi_flash_sd_2_o(spi_flash_sd_in[2]), .spi_flash_sd_2_oe_i(spi_flash_sd_en[2]), - .spi_flash_sd_3_io(spi_flash_sd_io[3]), .spi_flash_sd_3_i(spi_flash_sd_out[3]), .spi_flash_sd_3_o(spi_flash_sd_in[3]), .spi_flash_sd_3_oe_i(spi_flash_sd_en[3]), - .spi_sck_io(spi_sck_o), .spi_sck_i(spi_sck), .spi_sck_o(), .spi_sck_oe_i(spi_sck_en), - .spi_cs_0_io(spi_csb_o[0]), .spi_cs_0_i(spi_csb[0]), .spi_cs_0_o(), .spi_cs_0_oe_i(spi_csb_en[0]), - .spi_cs_1_io(spi_csb_o[1]), .spi_cs_1_i(spi_csb[1]), .spi_cs_1_o(), .spi_cs_1_oe_i(spi_csb_en[1]), - .spi_sd_0_io(spi_sd_io[0]), .spi_sd_0_i(spi_sd_out[0]), .spi_sd_0_o(spi_sd_in[0]), .spi_sd_0_oe_i(spi_sd_en[0]), - .spi_sd_1_io(spi_sd_io[1]), .spi_sd_1_i(spi_sd_out[1]), .spi_sd_1_o(spi_sd_in[1]), .spi_sd_1_oe_i(spi_sd_en[1]), - .spi_sd_2_io(spi_sd_io[2]), .spi_sd_2_i(spi_sd_out[2]), .spi_sd_2_o(spi_sd_in[2]), .spi_sd_2_oe_i(spi_sd_en[2]), - .spi_sd_3_io(spi_sd_io[3]), .spi_sd_3_i(spi_sd_out[3]), .spi_sd_3_o(spi_sd_in[3]), .spi_sd_3_oe_i(spi_sd_en[3]), - .i2c_scl_io(i2c_scl_io), .i2c_scl_i(cio_scl_out), .i2c_scl_o(cio_scl_in), .i2c_scl_oe_i(cio_scl_en), - .i2c_sda_io(i2c_sda_io), .i2c_sda_i(cio_sda_out), .i2c_sda_o(cio_sda_in), .i2c_sda_oe_i(cio_sda_en), - .pad_attributes_i(pad_attributes) ); - - - endmodule // core_v_mini_mcu diff --git a/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl b/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl index 84af3b008..2b768c3e7 100644 --- a/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl +++ b/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl @@ -101,7 +101,7 @@ package core_v_mini_mcu_pkg; }; //always-on peripherals - localparam AO_PERIPHERALS = 9; + localparam AO_PERIPHERALS = 11; localparam logic[31:0] SOC_CTRL_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${soc_ctrl_start_offset}; localparam logic[31:0] SOC_CTRL_SIZE = 32'h${soc_ctrl_size_address}; @@ -123,41 +123,54 @@ package core_v_mini_mcu_pkg; localparam logic[31:0] SPI_MEMIO_END_ADDRESS = SPI_MEMIO_START_ADDRESS + SPI_MEMIO_SIZE; localparam logic[31:0] SPI_MEMIO_IDX = 32'd3; + localparam logic[31:0] SPI_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${spi_start_offset}; + localparam logic[31:0] SPI_SIZE = 32'h${spi_size_address}; + localparam logic[31:0] SPI_END_ADDRESS = SPI_START_ADDRESS + SPI_SIZE; + localparam logic[31:0] SPI_IDX = 32'd4; + localparam logic [31:0] POWER_MANAGER_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${power_manager_start_offset}; localparam logic [31:0] POWER_MANAGER_SIZE = 32'h${power_manager_size_address}; localparam logic [31:0] POWER_MANAGER_END_ADDRESS = POWER_MANAGER_START_ADDRESS + POWER_MANAGER_SIZE; - localparam logic [31:0] POWER_MANAGER_IDX = 32'd4; + localparam logic [31:0] POWER_MANAGER_IDX = 32'd5; - localparam logic [31:0] RV_TIMER_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${rv_timer_start_offset}; - localparam logic [31:0] RV_TIMER_SIZE = 32'h${rv_timer_size_address}; - localparam logic [31:0] RV_TIMER_END_ADDRESS = RV_TIMER_START_ADDRESS + RV_TIMER_SIZE; - localparam logic [31:0] RV_TIMER_IDX = 32'd5; + localparam logic [31:0] RV_TIMER_AO_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${rv_timer_ao_start_offset}; + localparam logic [31:0] RV_TIMER_AO_SIZE = 32'h${rv_timer_ao_size_address}; + localparam logic [31:0] RV_TIMER_AO_END_ADDRESS = RV_TIMER_AO_START_ADDRESS + RV_TIMER_AO_SIZE; + localparam logic [31:0] RV_TIMER_AO_IDX = 32'd6; localparam logic [31:0] DMA_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${dma_start_offset}; localparam logic [31:0] DMA_SIZE = 32'h${dma_size_address}; localparam logic [31:0] DMA_END_ADDRESS = DMA_START_ADDRESS + DMA_SIZE; - localparam logic [31:0] DMA_IDX = 32'd6; + localparam logic [31:0] DMA_IDX = 32'd7; - localparam logic [31:0] PAD_ATTRIBUTE_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${pad_attribute_start_offset}; - localparam logic [31:0] PAD_ATTRIBUTE_SIZE = 32'h${pad_attribute_size_address}; - localparam logic [31:0] PAD_ATTRIBUTE_END_ADDRESS = PAD_ATTRIBUTE_START_ADDRESS + PAD_ATTRIBUTE_SIZE; - localparam logic [31:0] PAD_ATTRIBUTE_IDX = 32'd7; + localparam logic[31:0] FAST_INTR_CTRL_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${fast_intr_ctrl_start_offset}; + localparam logic[31:0] FAST_INTR_CTRL_SIZE = 32'h${fast_intr_ctrl_size_address}; + localparam logic[31:0] FAST_INTR_CTRL_END_ADDRESS = FAST_INTR_CTRL_START_ADDRESS + FAST_INTR_CTRL_SIZE; + localparam logic[31:0] FAST_INTR_CTRL_IDX = 32'd8; + + localparam logic[31:0] EXT_PERIPH_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${ext_periph_start_offset}; + localparam logic[31:0] EXT_PERIPH_SIZE = 32'h${ext_periph_size_address}; + localparam logic[31:0] EXT_PERIPH_END_ADDRESS = EXT_PERIPH_START_ADDRESS + EXT_PERIPH_SIZE; + localparam logic[31:0] EXT_PERIPH_IDX = 32'd9; + + localparam logic[31:0] PAD_ATTRIBUTE_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${pad_attribute_start_offset}; + localparam logic[31:0] PAD_ATTRIBUTE_SIZE = 32'h${pad_attribute_size_address}; + localparam logic[31:0] PAD_ATTRIBUTE_END_ADDRESS = PAD_ATTRIBUTE_START_ADDRESS + PAD_ATTRIBUTE_SIZE; + localparam logic[31:0] PAD_ATTRIBUTE_IDX = 32'd10; - localparam logic[31:0] SPI_START_ADDRESS = AO_PERIPHERAL_START_ADDRESS + 32'h${spi_start_offset}; - localparam logic[31:0] SPI_SIZE = 32'h${spi_size_address}; - localparam logic[31:0] SPI_END_ADDRESS = SPI_START_ADDRESS + SPI_SIZE; - localparam logic[31:0] SPI_IDX = 32'd8; localparam addr_map_rule_t [AO_PERIPHERALS-1:0] AO_PERIPHERALS_ADDR_RULES = '{ '{ idx: SOC_CTRL_IDX, start_addr: SOC_CTRL_START_ADDRESS, end_addr: SOC_CTRL_END_ADDRESS }, '{ idx: BOOTROM_IDX, start_addr: BOOTROM_START_ADDRESS, end_addr: BOOTROM_END_ADDRESS }, '{ idx: SPI_FLASH_IDX, start_addr: SPI_FLASH_START_ADDRESS, end_addr: SPI_FLASH_END_ADDRESS }, '{ idx: SPI_MEMIO_IDX, start_addr: SPI_MEMIO_START_ADDRESS, end_addr: SPI_MEMIO_END_ADDRESS }, + '{ idx: SPI_IDX, start_addr: SPI_START_ADDRESS, end_addr: SPI_END_ADDRESS }, '{ idx: POWER_MANAGER_IDX, start_addr: POWER_MANAGER_START_ADDRESS, end_addr: POWER_MANAGER_END_ADDRESS }, - '{ idx: RV_TIMER_IDX, start_addr: RV_TIMER_START_ADDRESS, end_addr: RV_TIMER_END_ADDRESS }, + '{ idx: RV_TIMER_AO_IDX, start_addr: RV_TIMER_AO_START_ADDRESS, end_addr: RV_TIMER_AO_END_ADDRESS }, '{ idx: DMA_IDX, start_addr: DMA_START_ADDRESS, end_addr: DMA_END_ADDRESS }, - '{ idx: PAD_ATTRIBUTE_IDX, start_addr: PAD_ATTRIBUTE_START_ADDRESS, end_addr: PAD_ATTRIBUTE_END_ADDRESS }, - '{ idx: SPI_IDX, start_addr: SPI_START_ADDRESS, end_addr: SPI_END_ADDRESS } + '{ idx: FAST_INTR_CTRL_IDX, start_addr: FAST_INTR_CTRL_START_ADDRESS, end_addr: FAST_INTR_CTRL_END_ADDRESS }, + '{ idx: EXT_PERIPH_IDX, start_addr: EXT_PERIPH_START_ADDRESS, end_addr: EXT_PERIPH_END_ADDRESS }, + '{ idx: PAD_ATTRIBUTE_IDX, start_addr: PAD_ATTRIBUTE_START_ADDRESS, end_addr: PAD_ATTRIBUTE_END_ADDRESS } }; localparam int unsigned AO_PERIPHERALS_PORT_SEL_WIDTH = AO_PERIPHERALS > 1 ? $clog2(AO_PERIPHERALS) : 32'd1; @@ -185,24 +198,24 @@ package core_v_mini_mcu_pkg; localparam logic[31:0] I2C_END_ADDRESS = I2C_START_ADDRESS + I2C_SIZE; localparam logic[31:0] I2C_IDX = 32'd3; - localparam logic[31:0] EXT_PERIPH_START_ADDRESS = PERIPHERAL_START_ADDRESS + 32'h${ext_periph_start_offset}; - localparam logic[31:0] EXT_PERIPH_SIZE = 32'h${ext_periph_size_address}; - localparam logic[31:0] EXT_PERIPH_END_ADDRESS = EXT_PERIPH_START_ADDRESS + EXT_PERIPH_SIZE; - localparam logic[31:0] EXT_PERIPH_IDX = 32'd4; + localparam logic [31:0] RV_TIMER_START_ADDRESS = PERIPHERAL_START_ADDRESS + 32'h${rv_timer_start_offset}; + localparam logic [31:0] RV_TIMER_SIZE = 32'h${rv_timer_size_address}; + localparam logic [31:0] RV_TIMER_END_ADDRESS = RV_TIMER_START_ADDRESS + RV_TIMER_SIZE; + localparam logic [31:0] RV_TIMER_IDX = 32'd4; localparam addr_map_rule_t [PERIPHERALS-1:0] PERIPHERALS_ADDR_RULES = '{ '{ idx: PLIC_IDX, start_addr: PLIC_START_ADDRESS, end_addr: PLIC_END_ADDRESS }, '{ idx: UART_IDX, start_addr: UART_START_ADDRESS, end_addr: UART_END_ADDRESS }, '{ idx: GPIO_IDX, start_addr: GPIO_START_ADDRESS, end_addr: GPIO_END_ADDRESS }, '{ idx: I2C_IDX, start_addr: I2C_START_ADDRESS, end_addr: I2C_END_ADDRESS }, - '{ idx: EXT_PERIPH_IDX, start_addr: EXT_PERIPH_START_ADDRESS, end_addr: EXT_PERIPH_END_ADDRESS } + '{ idx: RV_TIMER_IDX, start_addr: RV_TIMER_START_ADDRESS, end_addr: RV_TIMER_END_ADDRESS } }; localparam int unsigned PERIPHERALS_PORT_SEL_WIDTH = PERIPHERALS > 1 ? $clog2(PERIPHERALS) : 32'd1; // Interrupts localparam PLIC_NINT = 64; - localparam PLIC_USED_NINT = 62; + localparam PLIC_USED_NINT = 49; localparam NEXT_INT = PLIC_NINT - PLIC_USED_NINT; % for pad in pad_list: diff --git a/hw/core-v-mini-mcu/memory_subsystem.sv b/hw/core-v-mini-mcu/memory_subsystem.sv index 6e8155fb6..1f4ec01ba 100644 --- a/hw/core-v-mini-mcu/memory_subsystem.sv +++ b/hw/core-v-mini-mcu/memory_subsystem.sv @@ -2,6 +2,8 @@ // Solderpad Hardware License, Version 2.1, see LICENSE.md for details. // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +/* verilator lint_off UNUSED */ + module memory_subsystem import obi_pkg::*; #( diff --git a/hw/core-v-mini-mcu/peripheral_subsystem.sv b/hw/core-v-mini-mcu/peripheral_subsystem.sv index 376dec197..d81cd3808 100644 --- a/hw/core-v-mini-mcu/peripheral_subsystem.sv +++ b/hw/core-v-mini-mcu/peripheral_subsystem.sv @@ -28,6 +28,7 @@ module peripheral_subsystem input logic [31:0] cio_gpio_i, output logic [31:0] cio_gpio_o, output logic [31:0] cio_gpio_en_o, + output logic [ 7:0] cio_gpio_intr_o, // I2C Interface input logic cio_scl_i, @@ -37,16 +38,9 @@ module peripheral_subsystem output logic cio_sda_o, output logic cio_sda_en_o, - //External peripheral(s) - output reg_req_t ext_peripheral_slave_req_o, - input reg_rsp_t ext_peripheral_slave_resp_i, - - // Always-on domain peripherals' interrupts - input logic dma_intr_i, - input logic spi_flash_intr_error_i, - input logic spi_flash_intr_event_i, - input logic spi_intr_error_i, - input logic spi_intr_event_i + //RV TIMER + output logic rv_timer_2_intr_o, + output logic rv_timer_3_intr_o ); import core_v_mini_mcu_pkg::*; @@ -71,6 +65,9 @@ module peripheral_subsystem tlul_pkg::tl_h2d_t i2c_tl_h2d; tlul_pkg::tl_d2h_t i2c_tl_d2h; + tlul_pkg::tl_h2d_t rv_timer_tl_h2d; + tlul_pkg::tl_d2h_t rv_timer_tl_d2h; + logic [rv_plic_reg_pkg::NumTarget-1:0] irq_plic; logic [rv_plic_reg_pkg::NumSrc-1:0] intr_vector; logic [$clog2(rv_plic_reg_pkg::NumSrc)-1:0] irq_id[rv_plic_reg_pkg::NumTarget]; @@ -87,22 +84,22 @@ module peripheral_subsystem logic [31:0] gpio_intr; - logic intr_fmt_watermark; - logic intr_rx_watermark; - logic intr_fmt_overflow; - logic intr_rx_overflow; - logic intr_nak; - logic intr_scl_interference; - logic intr_sda_interference; - logic intr_stretch_timeout; - logic intr_sda_unstable; - logic intr_trans_complete; - logic intr_tx_empty; - logic intr_tx_nonempty; - logic intr_tx_overflow; - logic intr_acq_overflow; - logic intr_ack_stop; - logic intr_host_timeout; + logic i2c_intr_fmt_watermark; + logic i2c_intr_rx_watermark; + logic i2c_intr_fmt_overflow; + logic i2c_intr_rx_overflow; + logic i2c_intr_nak; + logic i2c_intr_scl_interference; + logic i2c_intr_sda_interference; + logic i2c_intr_stretch_timeout; + logic i2c_intr_sda_unstable; + logic i2c_intr_trans_complete; + logic i2c_intr_tx_empty; + logic i2c_intr_tx_nonempty; + logic i2c_intr_tx_overflow; + logic i2c_intr_acq_overflow; + logic i2c_intr_ack_stop; + logic i2c_intr_host_timeout; // this avoids lint errors assign unused_irq_id = irq_id; @@ -117,28 +114,23 @@ module peripheral_subsystem assign intr_vector[6] = uart_intr_rx_break_err; assign intr_vector[7] = uart_intr_rx_timeout; assign intr_vector[8] = uart_intr_rx_parity_err; - assign intr_vector[40:9] = gpio_intr; - assign intr_vector[41] = intr_fmt_watermark; - assign intr_vector[42] = intr_rx_watermark; - assign intr_vector[43] = intr_fmt_overflow; - assign intr_vector[44] = intr_rx_overflow; - assign intr_vector[45] = intr_nak; - assign intr_vector[46] = intr_scl_interference; - assign intr_vector[47] = intr_sda_interference; - assign intr_vector[48] = intr_stretch_timeout; - assign intr_vector[49] = intr_sda_unstable; - assign intr_vector[50] = intr_trans_complete; - assign intr_vector[51] = intr_tx_empty; - assign intr_vector[52] = intr_tx_nonempty; - assign intr_vector[53] = intr_tx_overflow; - assign intr_vector[54] = intr_acq_overflow; - assign intr_vector[55] = intr_ack_stop; - assign intr_vector[56] = intr_host_timeout; - assign intr_vector[57] = dma_intr_i; - assign intr_vector[58] = spi_flash_intr_error_i; - assign intr_vector[59] = spi_flash_intr_event_i; - assign intr_vector[60] = spi_intr_error_i; - assign intr_vector[61] = spi_intr_event_i; + assign intr_vector[32:9] = gpio_intr[31:8]; + assign intr_vector[33] = i2c_intr_fmt_watermark; + assign intr_vector[34] = i2c_intr_rx_watermark; + assign intr_vector[35] = i2c_intr_fmt_overflow; + assign intr_vector[36] = i2c_intr_rx_overflow; + assign intr_vector[37] = i2c_intr_nak; + assign intr_vector[38] = i2c_intr_scl_interference; + assign intr_vector[39] = i2c_intr_sda_interference; + assign intr_vector[40] = i2c_intr_stretch_timeout; + assign intr_vector[41] = i2c_intr_sda_unstable; + assign intr_vector[42] = i2c_intr_trans_complete; + assign intr_vector[43] = i2c_intr_tx_empty; + assign intr_vector[44] = i2c_intr_tx_nonempty; + assign intr_vector[45] = i2c_intr_tx_overflow; + assign intr_vector[46] = i2c_intr_acq_overflow; + assign intr_vector[47] = i2c_intr_ack_stop; + assign intr_vector[48] = i2c_intr_host_timeout; // External interrupts assignement for (genvar i = 0; i < NEXT_INT; i++) begin @@ -148,9 +140,6 @@ module peripheral_subsystem //Address Decoder logic [PERIPHERALS_PORT_SEL_WIDTH-1:0] peripheral_select; - assign ext_peripheral_slave_req_o = peripheral_slv_req[core_v_mini_mcu_pkg::EXT_PERIPH_IDX]; - assign peripheral_slv_rsp[core_v_mini_mcu_pkg::EXT_PERIPH_IDX] = ext_peripheral_slave_resp_i; - periph_to_reg #( .req_t(reg_pkg::reg_req_t), .rsp_t(reg_pkg::reg_rsp_t), @@ -293,6 +282,8 @@ module peripheral_subsystem .intr_gpio_o(gpio_intr) ); + assign cio_gpio_intr_o = gpio_intr[7:0]; + reg_to_tlul #( .req_t(reg_pkg::reg_req_t), .rsp_t(reg_pkg::reg_rsp_t), @@ -321,22 +312,48 @@ module peripheral_subsystem .cio_sda_i, .cio_sda_o, .cio_sda_en_o, - .intr_fmt_watermark_o(intr_fmt_watermark), - .intr_rx_watermark_o(intr_rx_watermark), - .intr_fmt_overflow_o(intr_fmt_overflow), - .intr_rx_overflow_o(intr_rx_overflow), - .intr_nak_o(intr_nak), - .intr_scl_interference_o(intr_scl_interference), - .intr_sda_interference_o(intr_sda_interference), - .intr_stretch_timeout_o(intr_stretch_timeout), - .intr_sda_unstable_o(intr_sda_unstable), - .intr_trans_complete_o(intr_trans_complete), - .intr_tx_empty_o(intr_tx_empty), - .intr_tx_nonempty_o(intr_tx_nonempty), - .intr_tx_overflow_o(intr_tx_overflow), - .intr_acq_overflow_o(intr_acq_overflow), - .intr_ack_stop_o(intr_ack_stop), - .intr_host_timeout_o(intr_host_timeout) + .intr_fmt_watermark_o(i2c_intr_fmt_watermark), + .intr_rx_watermark_o(i2c_intr_rx_watermark), + .intr_fmt_overflow_o(i2c_intr_fmt_overflow), + .intr_rx_overflow_o(i2c_intr_rx_overflow), + .intr_nak_o(i2c_intr_nak), + .intr_scl_interference_o(i2c_intr_scl_interference), + .intr_sda_interference_o(i2c_intr_sda_interference), + .intr_stretch_timeout_o(i2c_intr_stretch_timeout), + .intr_sda_unstable_o(i2c_intr_sda_unstable), + .intr_trans_complete_o(i2c_intr_trans_complete), + .intr_tx_empty_o(i2c_intr_tx_empty), + .intr_tx_nonempty_o(i2c_intr_tx_nonempty), + .intr_tx_overflow_o(i2c_intr_tx_overflow), + .intr_acq_overflow_o(i2c_intr_acq_overflow), + .intr_ack_stop_o(i2c_intr_ack_stop), + .intr_host_timeout_o(i2c_intr_host_timeout) + ); + + reg_to_tlul #( + .req_t(reg_pkg::reg_req_t), + .rsp_t(reg_pkg::reg_rsp_t), + .tl_h2d_t(tlul_pkg::tl_h2d_t), + .tl_d2h_t(tlul_pkg::tl_d2h_t), + .tl_a_user_t(tlul_pkg::tl_a_user_t), + .tl_a_op_e(tlul_pkg::tl_a_op_e), + .TL_A_USER_DEFAULT(tlul_pkg::TL_A_USER_DEFAULT), + .PutFullData(tlul_pkg::PutFullData), + .Get(tlul_pkg::Get) + ) rv_timer_reg_to_tlul_i ( + .tl_o(rv_timer_tl_h2d), + .tl_i(rv_timer_tl_d2h), + .reg_req_i(peripheral_slv_req[core_v_mini_mcu_pkg::RV_TIMER_IDX]), + .reg_rsp_o(peripheral_slv_rsp[core_v_mini_mcu_pkg::RV_TIMER_IDX]) + ); + + rv_timer rv_timer_2_3_i ( + .clk_i, + .rst_ni, + .tl_i(rv_timer_tl_h2d), + .tl_o(rv_timer_tl_d2h), + .intr_timer_expired_0_0_o(rv_timer_2_intr_o), + .intr_timer_expired_1_0_o(rv_timer_3_intr_o) ); endmodule : peripheral_subsystem diff --git a/hw/core-v-mini-mcu/spi_subsystem.sv b/hw/core-v-mini-mcu/spi_subsystem.sv index 4bbf64f75..110694b30 100644 --- a/hw/core-v-mini-mcu/spi_subsystem.sv +++ b/hw/core-v-mini-mcu/spi_subsystem.sv @@ -6,20 +6,19 @@ module spi_subsystem import obi_pkg::*; import reg_pkg::*; ( - input logic clk_i, input logic rst_ni, input logic use_spimemio_i, - //memory mapped spi + // Memory mapped SPI input obi_req_t spimemio_req_i, output obi_resp_t spimemio_resp_o, - //yosys spi configuration + // Yosys SPI configuration input reg_req_t yo_reg_req_i, output reg_rsp_t yo_reg_rsp_o, - //opentitan spi configuration + // OpenTitan SPI configuration input reg_req_t ot_reg_req_i, output reg_rsp_t ot_reg_rsp_o, @@ -39,7 +38,6 @@ module spi_subsystem // SPI - DMA interface output logic spi_flash_rx_valid_o, output logic spi_flash_tx_ready_o - ); // OpenTitan SPI Interface @@ -64,7 +62,7 @@ module spi_subsystem logic [ 3:0] yo_spi_sd_en; logic [ 3:0] yo_spi_sd_in; - //Multiplexer + // Multiplexer always_comb begin if (!use_spimemio_i) begin spi_flash_sck_o = ot_spi_sck; @@ -95,7 +93,7 @@ module spi_subsystem end end - //YosysHQ SPI + // YosysHQ SPI assign yo_spi_sck_en = 1'b1; assign yo_spi_csb_en = 2'b01; assign yo_spi_csb[1] = 1'b1; @@ -158,5 +156,4 @@ module spi_subsystem `endif - endmodule // spi_subsystem diff --git a/hw/ip/boot_rom/boot_rom.dump b/hw/ip/boot_rom/boot_rom.dump index 2c44a68df..0287e2b9a 100644 --- a/hw/ip/boot_rom/boot_rom.dump +++ b/hw/ip/boot_rom/boot_rom.dump @@ -5,10 +5,10 @@ boot_rom.elf: file format elf32-littleriscv Disassembly of section .text: 00000000 : - 0: 200305b7 lui a1,0x20030 - 4: 0045c503 lbu a0,4(a1) # 20030004 <_end+0x2002ff1a> + 0: 200405b7 lui a1,0x20040 + 4: 0005c503 lbu a0,0(a1) # 20040000 <_end+0x2003ff16> 8: c119 beqz a0,e - a: 4588 lw a0,8(a1) + a: 41c8 lw a0,4(a1) c: 9502 jalr a0 0000000e : diff --git a/hw/ip/boot_rom/boot_rom.h b/hw/ip/boot_rom/boot_rom.h index 6ca68ba9c..d1aff15e3 100644 --- a/hw/ip/boot_rom/boot_rom.h +++ b/hw/ip/boot_rom/boot_rom.h @@ -3,9 +3,9 @@ const int reset_vec_size = 59; uint32_t reset_vec[reset_vec_size] = { - 0x200305b7, - 0x0045c503, - 0x4588c119, + 0x200405b7, + 0x0005c503, + 0x41c8c119, 0x05b79502, 0xc5032000, 0xe5110085, diff --git a/hw/ip/boot_rom/boot_rom.sv b/hw/ip/boot_rom/boot_rom.sv index fc363eec0..1268c41a7 100644 --- a/hw/ip/boot_rom/boot_rom.sv +++ b/hw/ip/boot_rom/boot_rom.sv @@ -82,9 +82,9 @@ module boot_rom 32'he5110085, 32'hc5032000, 32'h05b79502, - 32'h4588c119, - 32'h0045c503, - 32'h200305b7 + 32'h41c8c119, + 32'h0005c503, + 32'h200405b7 }; logic [$clog2(core_v_mini_mcu_pkg::BOOTROM_SIZE)-1-2:0] word_addr; diff --git a/hw/ip/fast_intr_ctrl/data/fast_intr_ctrl.hjson b/hw/ip/fast_intr_ctrl/data/fast_intr_ctrl.hjson new file mode 100644 index 000000000..7101b9bf1 --- /dev/null +++ b/hw/ip/fast_intr_ctrl/data/fast_intr_ctrl.hjson @@ -0,0 +1,32 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +{ name: "fast_intr_ctrl", + clock_primary: "clk_i", + bus_interfaces: [ + { protocol: "reg_iface", direction: "device" } + ], + regwidth: "32", + registers: [ + { name: "FAST_INTR_PENDING", + desc: "Pending fast interrupt", + resval: "0x00000000" + swaccess: "ro", + hwaccess: "hrw", + fields: [ + { bits: "15:0", name: "FAST_INTR_PENDING", desc: "Pending Fast Interrupt Reg" } + ] + } + + { name: "FAST_INTR_CLEAR", + desc: "Clear fast interrupt", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "15:0", name: "FAST_INTR_CLEAR", desc: "Clear Fast Interrupt" } + ] + } + + ] +} diff --git a/hw/ip/fast_intr_ctrl/fast_intr_ctrl.core b/hw/ip/fast_intr_ctrl/fast_intr_ctrl.core new file mode 100644 index 000000000..fabd39e3d --- /dev/null +++ b/hw/ip/fast_intr_ctrl/fast_intr_ctrl.core @@ -0,0 +1,24 @@ +CAPI=2: + +name: "x-heep:ip:fast_intr_ctrl" +description: "x-heep fast intr ctrl" + +# Copyright 2022 EPFL +# Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +filesets: + files_rtl: + depend: + - lowrisc:prim:all + - pulp-platform.org::register_interface + files: + - rtl/fast_intr_ctrl_reg_pkg.sv + - rtl/fast_intr_ctrl_reg_top.sv + - rtl/fast_intr_ctrl.sv + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_rtl diff --git a/hw/ip/fast_intr_ctrl/fast_intr_ctrl.sh b/hw/ip/fast_intr_ctrl/fast_intr_ctrl.sh new file mode 100644 index 000000000..5f776465a --- /dev/null +++ b/hw/ip/fast_intr_ctrl/fast_intr_ctrl.sh @@ -0,0 +1,5 @@ + +echo "Generating RTL" +../../vendor/pulp_platform_register_interface/vendor/lowrisc_opentitan/util/regtool.py -r -t rtl ./data/fast_intr_ctrl.hjson +echo "Generating SW" +../../vendor/pulp_platform_register_interface/vendor/lowrisc_opentitan/util/regtool.py --cdefines -o ../../../sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl_regs.h ./data/fast_intr_ctrl.hjson diff --git a/hw/ip/fast_intr_ctrl/fast_intr_ctrl.vlt b/hw/ip/fast_intr_ctrl/fast_intr_ctrl.vlt new file mode 100644 index 000000000..c77d02fbe --- /dev/null +++ b/hw/ip/fast_intr_ctrl/fast_intr_ctrl.vlt @@ -0,0 +1,9 @@ +// Copyright 2022 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +`verilator_config + +lint_off -rule WIDTH -file "*/fast_intr_ctrl_reg_top.sv" -match "Operator ASSIGNW expects *" +lint_off -rule UNUSED -file "*/fast_intr_ctrl.sv" -match "Bits of signal are not used: 'reg2hw'*" +lint_off -rule UNUSED -file "*/fast_intr_ctrl.sv" -match "Bits of signal are not used: 'reg2hw'*" diff --git a/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl.sv b/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl.sv new file mode 100644 index 000000000..b74606cff --- /dev/null +++ b/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl.sv @@ -0,0 +1,74 @@ +// Copyright 2022 OpenHW Group +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +`include "common_cells/assertions.svh" + +module fast_intr_ctrl #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + // Bus Interface + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + input logic [14:0] fast_intr_i, + output logic [14:0] fast_intr_o +); + + import fast_intr_ctrl_reg_pkg::*; + + fast_intr_ctrl_reg2hw_t reg2hw; + fast_intr_ctrl_hw2reg_t hw2reg; + + logic [14:0] fast_intr_pending_de; + logic [14:0] fast_intr_clear_de; + + fast_intr_ctrl_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_rsp_t) + ) fast_intr_ctrl_reg_top_i ( + .clk_i, + .rst_ni, + .reg_req_i, + .reg_rsp_o, + .reg2hw, + .hw2reg, + .devmode_i(1'b1) + ); + + for (genvar i = 0; i < 15; i++) begin : gen_fast_interrupt + + always_comb begin + if (reg2hw.fast_intr_clear.q[i]) begin + fast_intr_pending_de[i] = 1'b1; + hw2reg.fast_intr_pending.d[i] = 1'b0; + fast_intr_clear_de[i] = 1'b1; + hw2reg.fast_intr_clear.d[i] = 1'b0; + end else begin + if (fast_intr_i[i]) begin + fast_intr_pending_de[i] = 1'b1; + hw2reg.fast_intr_pending.d[i] = 1'b1; + fast_intr_clear_de[i] = 1'b0; + hw2reg.fast_intr_clear.d[i] = 1'b0; + end else begin + fast_intr_pending_de[i] = 1'b0; + hw2reg.fast_intr_pending.d[i] = 1'b0; + fast_intr_clear_de[i] = 1'b0; + hw2reg.fast_intr_clear.d[i] = 1'b0; + end + end + end + + end + + assign hw2reg.fast_intr_pending.d[15] = 1'b0; + assign hw2reg.fast_intr_clear.d[15] = 1'b0; + assign fast_intr_o = reg2hw.fast_intr_pending.q[14:0]; + assign hw2reg.fast_intr_pending.de = |fast_intr_pending_de; + assign hw2reg.fast_intr_clear.de = |fast_intr_clear_de; + +endmodule : fast_intr_ctrl diff --git a/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl_reg_pkg.sv b/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl_reg_pkg.sv new file mode 100644 index 000000000..c8f1d2233 --- /dev/null +++ b/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl_reg_pkg.sv @@ -0,0 +1,59 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package fast_intr_ctrl_reg_pkg; + + // Address widths within the block + parameter int BlockAw = 3; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed {logic [15:0] q;} fast_intr_ctrl_reg2hw_fast_intr_pending_reg_t; + + typedef struct packed {logic [15:0] q;} fast_intr_ctrl_reg2hw_fast_intr_clear_reg_t; + + typedef struct packed { + logic [15:0] d; + logic de; + } fast_intr_ctrl_hw2reg_fast_intr_pending_reg_t; + + typedef struct packed { + logic [15:0] d; + logic de; + } fast_intr_ctrl_hw2reg_fast_intr_clear_reg_t; + + // Register -> HW type + typedef struct packed { + fast_intr_ctrl_reg2hw_fast_intr_pending_reg_t fast_intr_pending; // [31:16] + fast_intr_ctrl_reg2hw_fast_intr_clear_reg_t fast_intr_clear; // [15:0] + } fast_intr_ctrl_reg2hw_t; + + // HW -> register type + typedef struct packed { + fast_intr_ctrl_hw2reg_fast_intr_pending_reg_t fast_intr_pending; // [33:17] + fast_intr_ctrl_hw2reg_fast_intr_clear_reg_t fast_intr_clear; // [16:0] + } fast_intr_ctrl_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] FAST_INTR_CTRL_FAST_INTR_PENDING_OFFSET = 3'h0; + parameter logic [BlockAw-1:0] FAST_INTR_CTRL_FAST_INTR_CLEAR_OFFSET = 3'h4; + + // Register index + typedef enum int { + FAST_INTR_CTRL_FAST_INTR_PENDING, + FAST_INTR_CTRL_FAST_INTR_CLEAR + } fast_intr_ctrl_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] FAST_INTR_CTRL_PERMIT[2] = '{ + 4'b0011, // index[0] FAST_INTR_CTRL_FAST_INTR_PENDING + 4'b0011 // index[1] FAST_INTR_CTRL_FAST_INTR_CLEAR + }; + +endpackage + diff --git a/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl_reg_top.sv b/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl_reg_top.sv new file mode 100644 index 000000000..b99e60fad --- /dev/null +++ b/hw/ip/fast_intr_ctrl/rtl/fast_intr_ctrl_reg_top.sv @@ -0,0 +1,181 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module fast_intr_ctrl_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 3 +) ( + input clk_i, + input rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output fast_intr_ctrl_reg_pkg::fast_intr_ctrl_reg2hw_t reg2hw, // Write + input fast_intr_ctrl_reg_pkg::fast_intr_ctrl_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import fast_intr_ctrl_reg_pkg::*; + + localparam int DW = 32; + localparam int DBW = DW / 8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [ AW-1:0] reg_addr; + logic [ DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [ DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic [15:0] fast_intr_pending_qs; + logic [15:0] fast_intr_clear_qs; + logic [15:0] fast_intr_clear_wd; + logic fast_intr_clear_we; + + // Register instances + // R[fast_intr_pending]: V(False) + + prim_subreg #( + .DW (16), + .SWACCESS("RO"), + .RESVAL (16'h0) + ) u_fast_intr_pending ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .we(1'b0), + .wd('0), + + // from internal hardware + .de(hw2reg.fast_intr_pending.de), + .d (hw2reg.fast_intr_pending.d), + + // to internal hardware + .qe(), + .q (reg2hw.fast_intr_pending.q), + + // to register interface (read) + .qs(fast_intr_pending_qs) + ); + + + // R[fast_intr_clear]: V(False) + + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_fast_intr_clear ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(fast_intr_clear_we), + .wd(fast_intr_clear_wd), + + // from internal hardware + .de(hw2reg.fast_intr_clear.de), + .d (hw2reg.fast_intr_clear.d), + + // to internal hardware + .qe(), + .q (reg2hw.fast_intr_clear.q), + + // to register interface (read) + .qs(fast_intr_clear_qs) + ); + + + + + logic [1:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[0] = (reg_addr == FAST_INTR_CTRL_FAST_INTR_PENDING_OFFSET); + addr_hit[1] = (reg_addr == FAST_INTR_CTRL_FAST_INTR_CLEAR_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[0] & (|(FAST_INTR_CTRL_PERMIT[0] & ~reg_be))) | + (addr_hit[1] & (|(FAST_INTR_CTRL_PERMIT[1] & ~reg_be))))); + end + + assign fast_intr_clear_we = addr_hit[1] & reg_we & !reg_error; + assign fast_intr_clear_wd = reg_wdata[15:0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[15:0] = fast_intr_pending_qs; + end + + addr_hit[1]: begin + reg_rdata_next[15:0] = fast_intr_clear_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule diff --git a/hw/ip/power_manager/data/power_manager.hjson b/hw/ip/power_manager/data/power_manager.hjson deleted file mode 100644 index d78f2aff0..000000000 --- a/hw/ip/power_manager/data/power_manager.hjson +++ /dev/null @@ -1,460 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -{ name: "power_manager", - clock_primary: "clk_i", - bus_interfaces: [ - { protocol: "reg_iface", direction: "device" } - ], - regwidth: "32", - registers: [ - { name: "POWER_GATE_CORE", - desc: "Used to power gate the core", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "0", name: "POWER_GATE_CORE", desc: "Power Gate Core Reg" } - ] - } - - { name: "WAKEUP_STATE", - desc: "Wake-up state of the system", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "0", name: "WAKEUP_STATE", desc: "Wake-up state Reg" } - ] - } - - { name: "RESTORE_ADDRESS", - desc: "Restore xddress value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "RESTORE_XDDRESS", desc: "Restore xddress Reg" } - ] - } - { name: "CORE_REG_X1", - desc: "Core reg x1 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X1", desc: "Core reg x1 Reg" } - ] - } - { name: "CORE_REG_X2", - desc: "Core reg x2 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X2", desc: "Core reg x2 Reg" } - ] - } - { name: "CORE_REG_X3", - desc: "Core reg x3 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X3", desc: "Core reg x3 Reg" } - ] - } - { name: "CORE_REG_X4", - desc: "Core reg x4 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X4", desc: "Core reg x4 Reg" } - ] - } - { name: "CORE_REG_X5", - desc: "Core reg x5 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X5", desc: "Core reg x5 Reg" } - ] - } - { name: "CORE_REG_X6", - desc: "Core reg x6 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X6", desc: "Core reg x6 Reg" } - ] - } - { name: "CORE_REG_X7", - desc: "Core reg x7 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X7", desc: "Core reg x7 Reg" } - ] - } - { name: "CORE_REG_X8", - desc: "Core reg x8 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X8", desc: "Core reg x8 Reg" } - ] - } - { name: "CORE_REG_X9", - desc: "Core reg x9 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X9", desc: "Core reg x9 Reg" } - ] - } - { name: "CORE_REG_X10", - desc: "Core reg x10 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X10", desc: "Core reg x10 Reg" } - ] - } - { name: "CORE_REG_X11", - desc: "Core reg x11 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X11", desc: "Core reg x11 Reg" } - ] - } - { name: "CORE_REG_X12", - desc: "Core reg x12 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X12", desc: "Core reg x12 Reg" } - ] - } - { name: "CORE_REG_X13", - desc: "Core reg x13 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X13", desc: "Core reg x13 Reg" } - ] - } - { name: "CORE_REG_X14", - desc: "Core reg x14 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X14", desc: "Core reg x14 Reg" } - ] - } - { name: "CORE_REG_X15", - desc: "Core reg x15 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X15", desc: "Core reg x15 Reg" } - ] - } - { name: "CORE_REG_X16", - desc: "Core reg x16 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X16", desc: "Core reg x16 Reg" } - ] - } - { name: "CORE_REG_X17", - desc: "Core reg x17 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X17", desc: "Core reg x17 Reg" } - ] - } - { name: "CORE_REG_X18", - desc: "Core reg x18 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X18", desc: "Core reg x18Reg" } - ] - } - { name: "CORE_REG_X19", - desc: "Core reg x19 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X19", desc: "Core reg x19 Reg" } - ] - } - { name: "CORE_REG_X20", - desc: "Core reg x20 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X20", desc: "Core reg x20 Reg" } - ] - } - { name: "CORE_REG_X21", - desc: "Core reg x21 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X21", desc: "Core reg x21 Reg" } - ] - } - { name: "CORE_REG_X22", - desc: "Core reg x22 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X22", desc: "Core reg x22 Reg" } - ] - } - { name: "CORE_REG_X23", - desc: "Core reg x23 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X23", desc: "Core reg x23 Reg" } - ] - } - { name: "CORE_REG_X24", - desc: "Core reg x24 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X24", desc: "Core reg x24 Reg" } - ] - } - { name: "CORE_REG_X25", - desc: "Core reg x25 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X25", desc: "Core reg x25 Reg" } - ] - } - { name: "CORE_REG_X26", - desc: "Core reg x26 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X26", desc: "Core reg x26 Reg" } - ] - } - { name: "CORE_REG_X27", - desc: "Core reg x27 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X27", desc: "Core reg x27 Reg" } - ] - } - { name: "CORE_REG_X28", - desc: "Core reg x28 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X28", desc: "Core reg x28 Reg" } - ] - } - { name: "CORE_REG_X29", - desc: "Core reg x29 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X29", desc: "Core reg x29 Reg" } - ] - } - { name: "CORE_REG_X30", - desc: "Core reg x30 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X30", desc: "Core reg x30 Reg" } - ] - } - { name: "CORE_REG_X31", - desc: "Core reg x31 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_REG_X31", desc: "Core reg x31 Reg" } - ] - } - { name: "CORE_CSR_C0", - desc: "Core csr c0 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_CSR_C0", desc: "Core reg c0 Reg" } - ] - } - { name: "CORE_CSR_C1", - desc: "Core csr c1 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_CSR_C1", desc: "Core reg c1 Reg" } - ] - } - { name: "CORE_CSR_C2", - desc: "Core csr c2 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_CSR_C2", desc: "Core reg c2 Reg" } - ] - } - { name: "CORE_CSR_C3", - desc: "Core csr c3 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_CSR_C3", desc: "Core reg c3 Reg" } - ] - } - { name: "CORE_CSR_C4", - desc: "Core csr c4 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_CSR_C4", desc: "Core reg c4 Reg" } - ] - } - { name: "CORE_CSR_C5", - desc: "Core csr c5 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_CSR_C5", desc: "Core reg c5 Reg" } - ] - } - { name: "CORE_CSR_C6", - desc: "Core csr c6 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_CSR_C6", desc: "Core reg c6 Reg" } - ] - } - { name: "CORE_CSR_C7", - desc: "Core csr c7 value", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "31:0", name: "CORE_CSR_C7", desc: "Core reg c7 Reg" } - ] - } - - { name: "EN_WAIT_FOR_INTR", - desc: "Enable wait for interrupt", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "0", name: "EN_WAIT_FOR_INTR", desc: "Enable wait for interrupt" } - ] - } - { name: "INTR_STATE", - desc: "Interrupt state", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hrw", - fields: [ - { bits: "0", name: "INTR_STATE", desc: "Interrupt state Reg" } - ] - } - { name: "CPU_RESET_ASSERT_COUNTER", - desc: "Counter before resetting the CPU", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hrw", - fields: [ - { bits: "31:0", name: "CPU_RESET_ASSERT_COUNTER", desc: "CPU counter before resetting" } - ] - } - { name: "CPU_RESET_DEASSERT_COUNTER", - desc: "Counter before unreset the CPU", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hrw", - fields: [ - { bits: "31:0", name: "CPU_RESET_DEASSERT_COUNTER", desc: "CPU counter before unresetting" } - ] - } - { name: "CPU_SWITCH_OFF_COUNTER", - desc: "Counter before switching off the CPU", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hrw", - fields: [ - { bits: "31:0", name: "CPU_SWITCH_OFF_COUNTER", desc: "CPU counter before switching off" } - ] - } - { name: "CPU_SWITCH_ON_COUNTER", - desc: "Counter before switching on the CPU", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hrw", - fields: [ - { bits: "31:0", name: "CPU_SWITCH_ON_COUNTER", desc: "CPU counter before switching on" } - ] - } - { name: "CPU_COUNTERS_STOP", - desc: "Bits to stop the counters keeping the done_o signal high", - resval: "0x00000000" - swaccess: "rw", - hwaccess: "hro", - fields: [ - { bits: "0", name: "CPU_RESET_ASSERT_STOP_BIT_COUNTER", desc: "Stop the CPU_RESET_ASSERT_COUNTER counter" } - { bits: "1", name: "CPU_RESET_DEASSERT_STOP_BIT_COUNTER", desc: "Stop the CPU_RESET_DEASSERT_COUNTER counter" } - { bits: "2", name: "CPU_SWITCH_OFF_STOP_BIT_COUNTER", desc: "Stop the CPU_SWITCH_OFF_COUNTER counter" } - { bits: "3", name: "CPU_SWITCH_ON_STOP_BIT_COUNTER", desc: "Stop the CPU_SWITCH_ON_COUNTER counter" } - ] - } - - ] -} diff --git a/hw/ip/power_manager/data/power_manager.hjson.tpl b/hw/ip/power_manager/data/power_manager.hjson.tpl new file mode 100644 index 000000000..a203a025c --- /dev/null +++ b/hw/ip/power_manager/data/power_manager.hjson.tpl @@ -0,0 +1,403 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +{ name: "power_manager", + clock_primary: "clk_i", + bus_interfaces: [ + { protocol: "reg_iface", direction: "device" } + ], + regwidth: "32", + registers: [ + { name: "WAKEUP_STATE", + desc: "Wake-up state of the system", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "WAKEUP_STATE", desc: "Wake-up state Reg" } + ] + } + + { name: "RESTORE_ADDRESS", + desc: "Restore xddress value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "RESTORE_XDDRESS", desc: "Restore xddress Reg" } + ] + } + + { name: "POWER_GATE_CORE", + desc: "Used to power gate core", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "POWER_GATE_CORE", desc: "Power Gate Core Reg" } + ] + } + + { name: "POWER_GATE_PERIPH", + desc: "Used to power gate peripheral_subsystem", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "POWER_GATE_PERIPH", desc: "Power Gate Periph Reg" } + ] + } + +% for bank in range(ram_numbanks): + { name: "POWER_GATE_RAM_BLOCK_${bank}", + desc: "Used to power gate ram block ${bank}", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "POWER_GATE_RAM_BLOCK_${bank}", desc: "Power Gate Ram Block ${bank} Reg" } + ] + } + +% endfor +% for i in range(31): + { name: "CORE_REG_X${i+1}", + desc: "Core reg x${i+1} value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_REG_X${i+1}", desc: "Core reg x${i+1} Reg" } + ] + } + +% endfor + { name: "CORE_CSR_MSTATUS", + desc: "Core csr mstatus value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MSTATUS", desc: "Core reg mstatus Reg" } + ] + } + + { name: "CORE_CSR_MIE", + desc: "Core csr mie value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MIE", desc: "Core reg mie Reg" } + ] + } + + { name: "CORE_CSR_MSCRATCH", + desc: "Core csr mscratch value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MSCRATCH", desc: "Core reg mscratch Reg" } + ] + } + + { name: "CORE_CSR_MEPC", + desc: "Core csr mepc value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MEPC", desc: "Core reg mepc Reg" } + ] + } + + { name: "CORE_CSR_MCAUSE", + desc: "Core csr mcause value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MCAUSE", desc: "Core reg mcause Reg" } + ] + } + + { name: "CORE_CSR_MTVAL", + desc: "Core csr mtval value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MTVAL", desc: "Core reg mtval Reg" } + ] + } + + { name: "CORE_CSR_MTVEC", + desc: "Core csr mtvec value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MTVEC", desc: "Core reg mtvec Reg" } + ] + } + + { name: "CORE_CSR_DCSR", + desc: "Core csr dcsr value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_DCSR", desc: "Core reg dcsr Reg" } + ] + } + + { name: "CORE_CSR_MCYCLE", + desc: "Core csr mcycle value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MCYCLE", desc: "Core reg mcycle Reg" } + ] + } + + { name: "CORE_CSR_MINSTRET", + desc: "Core csr minstret value", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "CORE_CSR_MINSTRET", desc: "Core reg minstret Reg" } + ] + } + + { name: "EN_WAIT_FOR_INTR", + desc: "Enable wait for interrupt", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "31:0", name: "EN_WAIT_FOR_INTR", desc: "Enable wait for interrupt" } + ] + } + + { name: "INTR_STATE", + desc: "Interrupt state", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "INTR_STATE", desc: "Interrupt state Reg" } + ] + } + + { name: "CPU_RESET_ASSERT_COUNTER", + desc: "Counter before resetting the CPU domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "CPU_RESET_ASSERT_COUNTER", desc: "CPU counter before resetting" } + ] + } + + { name: "CPU_RESET_DEASSERT_COUNTER", + desc: "Counter before unreset the CPU domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "CPU_RESET_DEASSERT_COUNTER", desc: "CPU counter before unresetting" } + ] + } + + { name: "CPU_SWITCH_OFF_COUNTER", + desc: "Counter before switching off the CPU domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "CPU_SWITCH_OFF_COUNTER", desc: "CPU counter before switching off" } + ] + } + + { name: "CPU_SWITCH_ON_COUNTER", + desc: "Counter before switching on the CPU domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "CPU_SWITCH_ON_COUNTER", desc: "CPU counter before switching on" } + ] + } + + { name: "CPU_ISO_OFF_COUNTER", + desc: "Counter before setting off the isolation of the CPU domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "CPU_ISO_OFF_COUNTER", desc: "CPU counter before setting off isolation" } + ] + } + + { name: "CPU_ISO_ON_COUNTER", + desc: "Counter before setting on the isolation of the CPU domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "CPU_ISO_ON_COUNTER", desc: "CPU counter before setting on isolation" } + ] + } + + { name: "CPU_COUNTERS_STOP", + desc: "Bits to stop the counters keeping the done_o signal high", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "CPU_RESET_ASSERT_STOP_BIT_COUNTER", desc: "Stop the CPU_RESET_ASSERT_COUNTER counter" } + { bits: "1", name: "CPU_RESET_DEASSERT_STOP_BIT_COUNTER", desc: "Stop the CPU_RESET_DEASSERT_COUNTER counter" } + { bits: "2", name: "CPU_SWITCH_OFF_STOP_BIT_COUNTER", desc: "Stop the CPU_SWITCH_OFF_COUNTER counter" } + { bits: "3", name: "CPU_SWITCH_ON_STOP_BIT_COUNTER", desc: "Stop the CPU_SWITCH_ON_COUNTER counter" } + { bits: "4", name: "CPU_ISO_OFF_STOP_BIT_COUNTER", desc: "Stop the CPU_ISO_OFF_COUNTER counter" } + { bits: "5", name: "CPU_ISO_ON_STOP_BIT_COUNTER", desc: "Stop the CPU_ISO_ON_COUNTER counter" } + ] + } + + { name: "PERIPH_RESET_ASSERT_COUNTER", + desc: "Counter before resetting the PERIPH domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "PERIPH_RESET_ASSERT_COUNTER", desc: "PERIPH counter before resetting" } + ] + } + + { name: "PERIPH_RESET_DEASSERT_COUNTER", + desc: "Counter before unreset the PERIPH domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "PERIPH_RESET_DEASSERT_COUNTER", desc: "PERIPH counter before unresetting" } + ] + } + + { name: "PERIPH_SWITCH_OFF_COUNTER", + desc: "Counter before switching off the PERIPH domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "PERIPH_SWITCH_OFF_COUNTER", desc: "PERIPH counter before switching off" } + ] + } + + { name: "PERIPH_SWITCH_ON_COUNTER", + desc: "Counter before switching on the PERIPH domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "PERIPH_SWITCH_ON_COUNTER", desc: "PERIPH counter before switching on" } + ] + } + + { name: "PERIPH_ISO_OFF_COUNTER", + desc: "Counter before setting off the isolation of the PERIPH domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "PERIPH_ISO_OFF_COUNTER", desc: "PERIPH counter before setting off isolation" } + ] + } + + { name: "PERIPH_ISO_ON_COUNTER", + desc: "Counter before setting on the isolation of the PERIPH domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "PERIPH_ISO_ON_COUNTER", desc: "PERIPH counter before setting on isolation" } + ] + } + + { name: "PERIPH_COUNTERS_STOP", + desc: "Bits to stop the counters keeping the done_o signal high", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "PERIPH_RESET_ASSERT_STOP_BIT_COUNTER", desc: "Stop the PERIPH_RESET_ASSERT_COUNTER counter" } + { bits: "1", name: "PERIPH_RESET_DEASSERT_STOP_BIT_COUNTER", desc: "Stop the PERIPH_RESET_DEASSERT_COUNTER counter" } + { bits: "2", name: "PERIPH_SWITCH_OFF_STOP_BIT_COUNTER", desc: "Stop the PERIPH_SWITCH_OFF_COUNTER counter" } + { bits: "3", name: "PERIPH_SWITCH_ON_STOP_BIT_COUNTER", desc: "Stop the PERIPH_SWITCH_ON_COUNTER counter" } + { bits: "4", name: "PERIPH_ISO_OFF_STOP_BIT_COUNTER", desc: "Stop the PERIPH_ISO_OFF_COUNTER counter" } + { bits: "5", name: "PERIPH_ISO_ON_STOP_BIT_COUNTER", desc: "Stop the PERIPH_ISO_ON_COUNTER counter" } + ] + } + +% for bank in range(ram_numbanks): + { name: "RAM_${bank}_SWITCH_OFF_COUNTER", + desc: "Counter before switching off the RAM_${bank} domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "RAM_${bank}_SWITCH_OFF_COUNTER", desc: "RAM_${bank} counter before switching off" } + ] + } + + { name: "RAM_${bank}_SWITCH_ON_COUNTER", + desc: "Counter before switching on the RAM_${bank} domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "RAM_${bank}_SWITCH_ON_COUNTER", desc: "RAM_${bank} counter before switching on" } + ] + } + + { name: "RAM_${bank}_ISO_OFF_COUNTER", + desc: "Counter before setting off the isolation of the RAM_${bank} domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "RAM_${bank}_ISO_OFF_COUNTER", desc: "RAM_${bank} counter before setting off isolation" } + ] + } + + { name: "RAM_${bank}_ISO_ON_COUNTER", + desc: "Counter before setting on the isolation of the RAM_${bank} domain", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "RAM_${bank}_ISO_ON_COUNTER", desc: "RAM_${bank} counter before setting on isolation" } + ] + } + + { name: "RAM_${bank}_COUNTERS_STOP", + desc: "Bits to stop the counters keeping the done_o signal high", + resval: "0x00000000" + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "RAM_${bank}_RESET_ASSERT_STOP_BIT_COUNTER", desc: "Stop the RAM_${bank}_RESET_ASSERT_COUNTER counter" } + { bits: "1", name: "RAM_${bank}_RESET_DEASSERT_STOP_BIT_COUNTER", desc: "Stop the RAM_${bank}_RESET_DEASSERT_COUNTER counter" } + { bits: "2", name: "RAM_${bank}_SWITCH_OFF_STOP_BIT_COUNTER", desc: "Stop the RAM_${bank}_SWITCH_OFF_COUNTER counter" } + { bits: "3", name: "RAM_${bank}_SWITCH_ON_STOP_BIT_COUNTER", desc: "Stop the RAM_${bank}_SWITCH_ON_COUNTER counter" } + { bits: "4", name: "RAM_${bank}_ISO_OFF_STOP_BIT_COUNTER", desc: "Stop the RAM_${bank}_ISO_OFF_COUNTER counter" } + { bits: "5", name: "RAM_${bank}_ISO_ON_STOP_BIT_COUNTER", desc: "Stop the RAM_${bank}_ISO_ON_COUNTER counter" } + ] + } + +% endfor + ] +} diff --git a/hw/ip/power_manager/data/power_manager.sv.tpl b/hw/ip/power_manager/data/power_manager.sv.tpl new file mode 100644 index 000000000..317c9a89e --- /dev/null +++ b/hw/ip/power_manager/data/power_manager.sv.tpl @@ -0,0 +1,500 @@ +// Copyright 2022 OpenHW Group +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +`include "common_cells/assertions.svh" + +module power_manager #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + // Bus Interface + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + // Status signal + input logic core_sleep_i, + + // Input interrupt array + input logic [31:0] intr_i, + + // External interrupts + input logic [core_v_mini_mcu_pkg::NEXT_INT-1:0] ext_irq_i, + + // Power gating signals + output logic cpu_subsystem_powergate_switch_o, + output logic cpu_subsystem_powergate_iso_o, + output logic peripheral_subsystem_powergate_switch_o, + output logic peripheral_subsystem_powergate_iso_o, + output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_switch_o, + output logic [core_v_mini_mcu_pkg::NUM_BANKS-1:0] memory_subsystem_banks_powergate_iso_o, + output logic cpu_subsystem_rst_no, + output logic peripheral_subsystem_rst_no +); + + import power_manager_reg_pkg::*; + + power_manager_reg2hw_t reg2hw; + power_manager_hw2reg_t hw2reg; + + logic start_on_sequence; + + assign hw2reg.intr_state.d = { + 1'b0, + ext_irq_i, + intr_i[29:22], // gpio + intr_i[21], // spi_flash + intr_i[20], // spi + intr_i[19], // dma + intr_i[18], // rv_timer_3 + intr_i[17], // rv_timer_2 + intr_i[16], // rv_timer_1 + intr_i[11], // plic + intr_i[7] // rv_timer_0 + }; + + assign hw2reg.intr_state.de = 1'b1; + + power_manager_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_rsp_t) + ) power_manager_reg_top_i ( + .clk_i, + .rst_ni, + .reg_req_i, + .reg_rsp_o, + .reg2hw, + .hw2reg, + .devmode_i(1'b1) + ); + + // -------------------------------------------------------------------------------------- + // CPU_SUBSYSTEM DOMAIN + // -------------------------------------------------------------------------------------- + + logic cpu_reset_counter_start_switch_off, cpu_reset_counter_expired_switch_off; + logic cpu_reset_counter_start_switch_on, cpu_reset_counter_expired_switch_on; + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_cpu_reset_assert_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.cpu_counters_stop.cpu_reset_assert_stop_bit_counter.q), + .start_i(cpu_reset_counter_start_switch_off), + .done_o(cpu_reset_counter_expired_switch_off), + .hw2reg_d_o(hw2reg.cpu_reset_assert_counter.d), + .hw2reg_de_o(hw2reg.cpu_reset_assert_counter.de), + .hw2reg_q_i(reg2hw.cpu_reset_assert_counter.q) + ); + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_cpu_reset_deassert_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.cpu_counters_stop.cpu_reset_deassert_stop_bit_counter.q), + .start_i(cpu_reset_counter_start_switch_on), + .done_o(cpu_reset_counter_expired_switch_on), + .hw2reg_d_o(hw2reg.cpu_reset_deassert_counter.d), + .hw2reg_de_o(hw2reg.cpu_reset_deassert_counter.de), + .hw2reg_q_i(reg2hw.cpu_reset_deassert_counter.q) + ); + + always_comb begin : power_manager_start_on_sequence_gen + if ((reg2hw.en_wait_for_intr.q & reg2hw.intr_state.q) == 32'b0) begin + start_on_sequence = 1'b0; + end else begin + start_on_sequence = 1'b1; + end + end + + power_manager_counter_sequence #( + .ONOFF_AT_RESET(0) + ) power_manager_counter_sequence_cpu_reset_i ( + .clk_i, + .rst_ni, + + // trigger to start the sequence + .start_off_sequence_i(reg2hw.power_gate_core.q && core_sleep_i), + .start_on_sequence_i (start_on_sequence), + + // counter to switch on and off signals + .counter_expired_switch_off_i(cpu_reset_counter_expired_switch_off), + .counter_expired_switch_on_i (cpu_reset_counter_expired_switch_on), + + .counter_start_switch_off_o(cpu_reset_counter_start_switch_off), + .counter_start_switch_on_o (cpu_reset_counter_start_switch_on), + + // switch on and off signal, 1 means on + .switch_onoff_signal_o(cpu_subsystem_rst_no) + ); + + logic cpu_powergate_counter_start_switch_off, cpu_powergate_counter_expired_switch_off; + logic cpu_powergate_counter_start_switch_on, cpu_powergate_counter_expired_switch_on; + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_cpu_powergate_switch_off_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.cpu_counters_stop.cpu_switch_off_stop_bit_counter.q), + .start_i(cpu_powergate_counter_start_switch_off), + .done_o(cpu_powergate_counter_expired_switch_off), + .hw2reg_d_o(hw2reg.cpu_switch_off_counter.d), + .hw2reg_de_o(hw2reg.cpu_switch_off_counter.de), + .hw2reg_q_i(reg2hw.cpu_switch_off_counter.q) + ); + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_cpu_powergate_switch_on_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.cpu_counters_stop.cpu_switch_on_stop_bit_counter.q), + .start_i(cpu_powergate_counter_start_switch_on), + .done_o(cpu_powergate_counter_expired_switch_on), + .hw2reg_d_o(hw2reg.cpu_switch_on_counter.d), + .hw2reg_de_o(hw2reg.cpu_switch_on_counter.de), + .hw2reg_q_i(reg2hw.cpu_switch_on_counter.q) + ); + + power_manager_counter_sequence power_manager_counter_sequence_cpu_switch_i ( + .clk_i, + .rst_ni, + + // trigger to start the sequence + .start_off_sequence_i(reg2hw.power_gate_core.q && core_sleep_i), + .start_on_sequence_i (start_on_sequence), + + // counter to switch on and off signals + .counter_expired_switch_off_i(cpu_powergate_counter_expired_switch_off), + .counter_expired_switch_on_i (cpu_powergate_counter_expired_switch_on), + + .counter_start_switch_off_o(cpu_powergate_counter_start_switch_off), + .counter_start_switch_on_o (cpu_powergate_counter_start_switch_on), + + // switch on and off signal, 1 means on + .switch_onoff_signal_o(cpu_subsystem_powergate_switch_o) + ); + + logic cpu_powergate_counter_start_iso_off, cpu_powergate_counter_expired_iso_off; + logic cpu_powergate_counter_start_iso_on, cpu_powergate_counter_expired_iso_on; + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_cpu_powergate_iso_off_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.cpu_counters_stop.cpu_iso_off_stop_bit_counter.q), + .start_i(cpu_powergate_counter_start_iso_off), + .done_o(cpu_powergate_counter_expired_iso_off), + .hw2reg_d_o(hw2reg.cpu_iso_off_counter.d), + .hw2reg_de_o(hw2reg.cpu_iso_off_counter.de), + .hw2reg_q_i(reg2hw.cpu_iso_off_counter.q) + ); + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_cpu_powergate_iso_on_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.cpu_counters_stop.cpu_iso_on_stop_bit_counter.q), + .start_i(cpu_powergate_counter_start_iso_on), + .done_o(cpu_powergate_counter_expired_iso_on), + .hw2reg_d_o(hw2reg.cpu_iso_on_counter.d), + .hw2reg_de_o(hw2reg.cpu_iso_on_counter.de), + .hw2reg_q_i(reg2hw.cpu_iso_on_counter.q) + ); + + power_manager_counter_sequence power_manager_counter_sequence_cpu_iso_i ( + .clk_i, + .rst_ni, + + // trigger to start the sequence + .start_off_sequence_i(reg2hw.power_gate_core.q && core_sleep_i), + .start_on_sequence_i (start_on_sequence), + + // counter to switch on and off signals + .counter_expired_switch_off_i(cpu_powergate_counter_expired_iso_off), + .counter_expired_switch_on_i (cpu_powergate_counter_expired_iso_on), + + .counter_start_switch_off_o(cpu_powergate_counter_start_iso_off), + .counter_start_switch_on_o (cpu_powergate_counter_start_iso_on), + + // switch on and off signal, 1 means on + .switch_onoff_signal_o(cpu_subsystem_powergate_iso_o) + ); + + // -------------------------------------------------------------------------------------- + // PERIPHERAL_SUBSYSTEM DOMAIN + // -------------------------------------------------------------------------------------- + + logic periph_reset_counter_start_switch_off, periph_reset_counter_expired_switch_off; + logic periph_reset_counter_start_switch_on, periph_reset_counter_expired_switch_on; + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_periph_reset_assert_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.periph_counters_stop.periph_reset_assert_stop_bit_counter.q), + .start_i(periph_reset_counter_start_switch_off), + .done_o(periph_reset_counter_expired_switch_off), + .hw2reg_d_o(hw2reg.periph_reset_assert_counter.d), + .hw2reg_de_o(hw2reg.periph_reset_assert_counter.de), + .hw2reg_q_i(reg2hw.periph_reset_assert_counter.q) + ); + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_periph_reset_deassert_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.periph_counters_stop.periph_reset_deassert_stop_bit_counter.q), + .start_i(periph_reset_counter_start_switch_on), + .done_o(periph_reset_counter_expired_switch_on), + .hw2reg_d_o(hw2reg.periph_reset_deassert_counter.d), + .hw2reg_de_o(hw2reg.periph_reset_deassert_counter.de), + .hw2reg_q_i(reg2hw.periph_reset_deassert_counter.q) + ); + + power_manager_counter_sequence #( + .ONOFF_AT_RESET(0) + ) power_manager_counter_sequence_periph_reset_i ( + .clk_i, + .rst_ni, + + // trigger to start the sequence + .start_off_sequence_i(reg2hw.power_gate_periph.q), + .start_on_sequence_i (~reg2hw.power_gate_periph.q), + + // counter to switch on and off signals + .counter_expired_switch_off_i(periph_reset_counter_expired_switch_off), + .counter_expired_switch_on_i (periph_reset_counter_expired_switch_on), + + .counter_start_switch_off_o(periph_reset_counter_start_switch_off), + .counter_start_switch_on_o (periph_reset_counter_start_switch_on), + + // switch on and off signal, 1 means on + .switch_onoff_signal_o(peripheral_subsystem_rst_no) + ); + + logic periph_powergate_counter_start_switch_off, periph_powergate_counter_expired_switch_off; + logic periph_powergate_counter_start_switch_on, periph_powergate_counter_expired_switch_on; + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_periph_powergate_switch_off_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.periph_counters_stop.periph_switch_off_stop_bit_counter.q), + .start_i(periph_powergate_counter_start_switch_off), + .done_o(periph_powergate_counter_expired_switch_off), + .hw2reg_d_o(hw2reg.periph_switch_off_counter.d), + .hw2reg_de_o(hw2reg.periph_switch_off_counter.de), + .hw2reg_q_i(reg2hw.periph_switch_off_counter.q) + ); + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_periph_powergate_switch_on_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.periph_counters_stop.periph_switch_on_stop_bit_counter.q), + .start_i(periph_powergate_counter_start_switch_on), + .done_o(periph_powergate_counter_expired_switch_on), + .hw2reg_d_o(hw2reg.periph_switch_on_counter.d), + .hw2reg_de_o(hw2reg.periph_switch_on_counter.de), + .hw2reg_q_i(reg2hw.periph_switch_on_counter.q) + ); + + power_manager_counter_sequence power_manager_counter_sequence_periph_switch_i ( + .clk_i, + .rst_ni, + + // trigger to start the sequence + .start_off_sequence_i(reg2hw.power_gate_periph.q), + .start_on_sequence_i (~reg2hw.power_gate_periph.q), + + // counter to switch on and off signals + .counter_expired_switch_off_i(periph_powergate_counter_expired_switch_off), + .counter_expired_switch_on_i (periph_powergate_counter_expired_switch_on), + + .counter_start_switch_off_o(periph_powergate_counter_start_switch_off), + .counter_start_switch_on_o (periph_powergate_counter_start_switch_on), + + // switch on and off signal, 1 means on + .switch_onoff_signal_o(peripheral_subsystem_powergate_switch_o) + ); + + logic periph_powergate_counter_start_iso_off, periph_powergate_counter_expired_iso_off; + logic periph_powergate_counter_start_iso_on, periph_powergate_counter_expired_iso_on; + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_periph_powergate_iso_off_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.periph_counters_stop.periph_iso_off_stop_bit_counter.q), + .start_i(periph_powergate_counter_start_iso_off), + .done_o(periph_powergate_counter_expired_iso_off), + .hw2reg_d_o(hw2reg.periph_iso_off_counter.d), + .hw2reg_de_o(hw2reg.periph_iso_off_counter.de), + .hw2reg_q_i(reg2hw.periph_iso_off_counter.q) + ); + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_periph_powergate_iso_on_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.periph_counters_stop.periph_iso_on_stop_bit_counter.q), + .start_i(periph_powergate_counter_start_iso_on), + .done_o(periph_powergate_counter_expired_iso_on), + .hw2reg_d_o(hw2reg.periph_iso_on_counter.d), + .hw2reg_de_o(hw2reg.periph_iso_on_counter.de), + .hw2reg_q_i(reg2hw.periph_iso_on_counter.q) + ); + + power_manager_counter_sequence power_manager_counter_sequence_periph_iso_i ( + .clk_i, + .rst_ni, + + // trigger to start the sequence + .start_off_sequence_i(reg2hw.power_gate_periph.q), + .start_on_sequence_i (~reg2hw.power_gate_periph.q), + + // counter to switch on and off signals + .counter_expired_switch_off_i(periph_powergate_counter_expired_iso_off), + .counter_expired_switch_on_i (periph_powergate_counter_expired_iso_on), + + .counter_start_switch_off_o(periph_powergate_counter_start_iso_off), + .counter_start_switch_on_o (periph_powergate_counter_start_iso_on), + + // switch on and off signal, 1 means on + .switch_onoff_signal_o(peripheral_subsystem_powergate_iso_o) + ); + +% for bank in range(ram_numbanks): + // -------------------------------------------------------------------------------------- + // RAM_${bank} DOMAIN + // -------------------------------------------------------------------------------------- + logic ram_${bank}_powergate_counter_start_switch_off, ram_${bank}_powergate_counter_expired_switch_off; + logic ram_${bank}_powergate_counter_start_switch_on, ram_${bank}_powergate_counter_expired_switch_on; + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_ram_${bank}_powergate_switch_off_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.ram_${bank}_counters_stop.ram_${bank}_switch_off_stop_bit_counter.q), + .start_i(ram_${bank}_powergate_counter_start_switch_off), + .done_o(ram_${bank}_powergate_counter_expired_switch_off), + .hw2reg_d_o(hw2reg.ram_${bank}_switch_off_counter.d), + .hw2reg_de_o(hw2reg.ram_${bank}_switch_off_counter.de), + .hw2reg_q_i(reg2hw.ram_${bank}_switch_off_counter.q) + ); + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_ram_${bank}_powergate_switch_on_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.ram_${bank}_counters_stop.ram_${bank}_switch_on_stop_bit_counter.q), + .start_i(ram_${bank}_powergate_counter_start_switch_on), + .done_o(ram_${bank}_powergate_counter_expired_switch_on), + .hw2reg_d_o(hw2reg.ram_${bank}_switch_on_counter.d), + .hw2reg_de_o(hw2reg.ram_${bank}_switch_on_counter.de), + .hw2reg_q_i(reg2hw.ram_${bank}_switch_on_counter.q) + ); + + power_manager_counter_sequence power_manager_counter_sequence_ram_${bank}_switch_i ( + .clk_i, + .rst_ni, + + // trigger to start the sequence + .start_off_sequence_i(reg2hw.power_gate_ram_block_${bank}.q), + .start_on_sequence_i (~reg2hw.power_gate_ram_block_${bank}.q), + + // counter to switch on and off signals + .counter_expired_switch_off_i(ram_${bank}_powergate_counter_expired_switch_off), + .counter_expired_switch_on_i (ram_${bank}_powergate_counter_expired_switch_on), + + .counter_start_switch_off_o(ram_${bank}_powergate_counter_start_switch_off), + .counter_start_switch_on_o (ram_${bank}_powergate_counter_start_switch_on), + + // switch on and off signal, 1 means on + .switch_onoff_signal_o(memory_subsystem_banks_powergate_switch_o[${bank}]) + ); + + logic ram_${bank}_powergate_counter_start_iso_off, ram_${bank}_powergate_counter_expired_iso_off; + logic ram_${bank}_powergate_counter_start_iso_on, ram_${bank}_powergate_counter_expired_iso_on; + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_ram_${bank}_powergate_iso_off_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.ram_${bank}_counters_stop.ram_${bank}_iso_off_stop_bit_counter.q), + .start_i(ram_${bank}_powergate_counter_start_iso_off), + .done_o(ram_${bank}_powergate_counter_expired_iso_off), + .hw2reg_d_o(hw2reg.ram_${bank}_iso_off_counter.d), + .hw2reg_de_o(hw2reg.ram_${bank}_iso_off_counter.de), + .hw2reg_q_i(reg2hw.ram_${bank}_iso_off_counter.q) + ); + + reg_to_counter #( + .DW(32), + .ExpireValue('0) + ) reg_to_counter_ram_${bank}_powergate_iso_on_i ( + .clk_i, + .rst_ni, + .stop_i(reg2hw.ram_${bank}_counters_stop.ram_${bank}_iso_on_stop_bit_counter.q), + .start_i(ram_${bank}_powergate_counter_start_iso_on), + .done_o(ram_${bank}_powergate_counter_expired_iso_on), + .hw2reg_d_o(hw2reg.ram_${bank}_iso_on_counter.d), + .hw2reg_de_o(hw2reg.ram_${bank}_iso_on_counter.de), + .hw2reg_q_i(reg2hw.ram_${bank}_iso_on_counter.q) + ); + + power_manager_counter_sequence power_manager_counter_sequence_ram_${bank}_iso_i ( + .clk_i, + .rst_ni, + + // trigger to start the sequence + .start_off_sequence_i(reg2hw.power_gate_ram_block_${bank}.q), + .start_on_sequence_i (~reg2hw.power_gate_ram_block_${bank}.q), + + // counter to switch on and off signals + .counter_expired_switch_off_i(ram_${bank}_powergate_counter_expired_iso_off), + .counter_expired_switch_on_i (ram_${bank}_powergate_counter_expired_iso_on), + + .counter_start_switch_off_o(ram_${bank}_powergate_counter_start_iso_off), + .counter_start_switch_on_o (ram_${bank}_powergate_counter_start_iso_on), + + // switch on and off signal, 1 means on + .switch_onoff_signal_o(memory_subsystem_banks_powergate_iso_o[${bank}]) + ); + +% endfor + +endmodule : power_manager diff --git a/hw/ip/power_manager/power_manager.vlt b/hw/ip/power_manager/power_manager.vlt index 8addf6ab2..4925e9f90 100644 --- a/hw/ip/power_manager/power_manager.vlt +++ b/hw/ip/power_manager/power_manager.vlt @@ -7,3 +7,4 @@ lint_off -rule WIDTH -file "*/power_manager_reg_top.sv" -match "Operator ASSIGNW expects *" lint_off -rule UNUSED -file "*/power_manager.sv" -match "Bits of signal are not used: 'reg2hw'*" lint_off -rule UNUSED -file "*/power_manager.sv" -match "Bits of signal are not used: 'reg2hw'*" +lint_off -rule UNUSED -file "*/power_manager.sv" -match "Bits of signal are not used: 'intr_i'[31:30,15:12,10:8,6:0]*" diff --git a/hw/ip/power_manager/rtl/power_manager.sv b/hw/ip/power_manager/rtl/power_manager.sv deleted file mode 100644 index 7a313fb61..000000000 --- a/hw/ip/power_manager/rtl/power_manager.sv +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2022 OpenHW Group -// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 - -`include "common_cells/assertions.svh" - -module power_manager #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic -) ( - input logic clk_i, - input logic rst_ni, - - // Bus Interface - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - - // Power gate signal - input logic rv_timer_irq_i, - input logic core_sleep_i, - output logic cpu_subsystem_powergate_switch_o, - output logic cpu_subsystem_rst_no -); - - import power_manager_reg_pkg::*; - - power_manager_reg2hw_t reg2hw; - power_manager_hw2reg_t hw2reg; - - assign hw2reg.intr_state.d = rv_timer_irq_i; - assign hw2reg.intr_state.de = 1'b1; - - - power_manager_reg_top #( - .reg_req_t(reg_req_t), - .reg_rsp_t(reg_rsp_t) - ) power_manager_reg_top_i ( - .clk_i, - .rst_ni, - .reg_req_i, - .reg_rsp_o, - .reg2hw, - .hw2reg, - .devmode_i(1'b1) - ); - - - logic cpu_reset_counter_start_switch_off, cpu_reset_counter_expired_switch_off; - logic cpu_reset_counter_start_switch_on, cpu_reset_counter_expired_switch_on; - - reg_to_counter #( - .DW(32), - .ExpireValue('0) - ) reg_to_counter_cpu_reset_assert_i ( - .clk_i, - .rst_ni, - - .stop_i (reg2hw.cpu_counters_stop.cpu_reset_assert_stop_bit_counter.q), - .start_i(cpu_reset_counter_start_switch_off), - .done_o (cpu_reset_counter_expired_switch_off), - - .hw2reg_d_o (hw2reg.cpu_reset_assert_counter.d), - .hw2reg_de_o(hw2reg.cpu_reset_assert_counter.de), - - .hw2reg_q_i(reg2hw.cpu_reset_assert_counter.q) - - ); - - reg_to_counter #( - .DW(32), - .ExpireValue('0) - ) reg_to_counter_cpu_reset_deassert_i ( - .clk_i, - .rst_ni, - - .stop_i (reg2hw.cpu_counters_stop.cpu_reset_deassert_stop_bit_counter.q), - .start_i(cpu_reset_counter_start_switch_on), - .done_o (cpu_reset_counter_expired_switch_on), - - .hw2reg_d_o (hw2reg.cpu_reset_deassert_counter.d), - .hw2reg_de_o(hw2reg.cpu_reset_deassert_counter.de), - - .hw2reg_q_i(reg2hw.cpu_reset_deassert_counter.q) - - ); - - power_manager_counter_sequence #( - .ONOFF_AT_RESET(0) - ) power_manager_counter_sequence_cpu_reset_i ( - .clk_i, - .rst_ni, - - // trigger to start the sequence - .start_off_sequence_i(reg2hw.power_gate_core.q && core_sleep_i), - .start_on_sequence_i (reg2hw.en_wait_for_intr.q && reg2hw.intr_state.q), - - // counter to switch on and off signals - .counter_expired_switch_off_i(cpu_reset_counter_expired_switch_off), - .counter_expired_switch_on_i (cpu_reset_counter_expired_switch_on), - - .counter_start_switch_off_o(cpu_reset_counter_start_switch_off), - .counter_start_switch_on_o (cpu_reset_counter_start_switch_on), - - // switch on and off signal, 1 means on - .switch_onoff_signal_o(cpu_subsystem_rst_no) - ); - - - logic cpu_powergate_counter_start_switch_off, cpu_powergate_counter_expired_switch_off; - logic cpu_powergate_counter_start_switch_on, cpu_powergate_counter_expired_switch_on; - - reg_to_counter #( - .DW(32), - .ExpireValue('0) - ) reg_to_counter_cpu_powergate_switch_off_i ( - .clk_i, - .rst_ni, - - .stop_i (reg2hw.cpu_counters_stop.cpu_switch_off_stop_bit_counter.q), - .start_i(cpu_powergate_counter_start_switch_off), - .done_o (cpu_powergate_counter_expired_switch_off), - - .hw2reg_d_o (hw2reg.cpu_switch_off_counter.d), - .hw2reg_de_o(hw2reg.cpu_switch_off_counter.de), - - .hw2reg_q_i(reg2hw.cpu_switch_off_counter.q) - - ); - - reg_to_counter #( - .DW(32), - .ExpireValue('0) - ) reg_to_counter_cpu_powergate_switch_on_i ( - .clk_i, - .rst_ni, - - .stop_i (reg2hw.cpu_counters_stop.cpu_switch_on_stop_bit_counter.q), - .start_i(cpu_powergate_counter_start_switch_on), - .done_o (cpu_powergate_counter_expired_switch_on), - - .hw2reg_d_o (hw2reg.cpu_switch_on_counter.d), - .hw2reg_de_o(hw2reg.cpu_switch_on_counter.de), - - .hw2reg_q_i(reg2hw.cpu_switch_on_counter.q) - - ); - - power_manager_counter_sequence power_manager_counter_sequence_cpu_powergate_i ( - .clk_i, - .rst_ni, - - // trigger to start the sequence - .start_off_sequence_i(reg2hw.power_gate_core.q && core_sleep_i), - .start_on_sequence_i (reg2hw.en_wait_for_intr.q && reg2hw.intr_state.q), - - // counter to switch on and off signals - .counter_expired_switch_off_i(cpu_powergate_counter_expired_switch_off), - .counter_expired_switch_on_i (cpu_powergate_counter_expired_switch_on), - - .counter_start_switch_off_o(cpu_powergate_counter_start_switch_off), - .counter_start_switch_on_o (cpu_powergate_counter_start_switch_on), - - // switch on and off signal, 1 means on - .switch_onoff_signal_o(cpu_subsystem_powergate_switch_o) - ); - - -endmodule : power_manager diff --git a/hw/ip/power_manager/rtl/power_manager_reg_pkg.sv b/hw/ip/power_manager/rtl/power_manager_reg_pkg.sv deleted file mode 100644 index 7a483e660..000000000 --- a/hw/ip/power_manager/rtl/power_manager_reg_pkg.sv +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure - -package power_manager_reg_pkg; - - // Address widths within the block - parameter int BlockAw = 8; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed {logic q;} power_manager_reg2hw_power_gate_core_reg_t; - - typedef struct packed {logic q;} power_manager_reg2hw_wakeup_state_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_restore_address_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x1_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x2_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x3_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x4_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x5_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x6_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x7_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x8_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x9_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x10_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x11_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x12_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x13_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x14_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x15_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x16_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x17_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x18_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x19_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x20_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x21_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x22_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x23_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x24_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x25_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x26_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x27_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x28_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x29_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x30_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_reg_x31_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_csr_c0_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_csr_c1_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_csr_c2_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_csr_c3_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_csr_c4_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_csr_c5_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_csr_c6_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_core_csr_c7_reg_t; - - typedef struct packed {logic q;} power_manager_reg2hw_en_wait_for_intr_reg_t; - - typedef struct packed {logic q;} power_manager_reg2hw_intr_state_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_cpu_reset_assert_counter_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_cpu_reset_deassert_counter_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_cpu_switch_off_counter_reg_t; - - typedef struct packed {logic [31:0] q;} power_manager_reg2hw_cpu_switch_on_counter_reg_t; - - typedef struct packed { - struct packed {logic q;} cpu_reset_assert_stop_bit_counter; - struct packed {logic q;} cpu_reset_deassert_stop_bit_counter; - struct packed {logic q;} cpu_switch_off_stop_bit_counter; - struct packed {logic q;} cpu_switch_on_stop_bit_counter; - } power_manager_reg2hw_cpu_counters_stop_reg_t; - - typedef struct packed { - logic d; - logic de; - } power_manager_hw2reg_intr_state_reg_t; - - typedef struct packed { - logic [31:0] d; - logic de; - } power_manager_hw2reg_cpu_reset_assert_counter_reg_t; - - typedef struct packed { - logic [31:0] d; - logic de; - } power_manager_hw2reg_cpu_reset_deassert_counter_reg_t; - - typedef struct packed { - logic [31:0] d; - logic de; - } power_manager_hw2reg_cpu_switch_off_counter_reg_t; - - typedef struct packed { - logic [31:0] d; - logic de; - } power_manager_hw2reg_cpu_switch_on_counter_reg_t; - - // Register -> HW type - typedef struct packed { - power_manager_reg2hw_power_gate_core_reg_t power_gate_core; // [1415:1415] - power_manager_reg2hw_wakeup_state_reg_t wakeup_state; // [1414:1414] - power_manager_reg2hw_restore_address_reg_t restore_address; // [1413:1382] - power_manager_reg2hw_core_reg_x1_reg_t core_reg_x1; // [1381:1350] - power_manager_reg2hw_core_reg_x2_reg_t core_reg_x2; // [1349:1318] - power_manager_reg2hw_core_reg_x3_reg_t core_reg_x3; // [1317:1286] - power_manager_reg2hw_core_reg_x4_reg_t core_reg_x4; // [1285:1254] - power_manager_reg2hw_core_reg_x5_reg_t core_reg_x5; // [1253:1222] - power_manager_reg2hw_core_reg_x6_reg_t core_reg_x6; // [1221:1190] - power_manager_reg2hw_core_reg_x7_reg_t core_reg_x7; // [1189:1158] - power_manager_reg2hw_core_reg_x8_reg_t core_reg_x8; // [1157:1126] - power_manager_reg2hw_core_reg_x9_reg_t core_reg_x9; // [1125:1094] - power_manager_reg2hw_core_reg_x10_reg_t core_reg_x10; // [1093:1062] - power_manager_reg2hw_core_reg_x11_reg_t core_reg_x11; // [1061:1030] - power_manager_reg2hw_core_reg_x12_reg_t core_reg_x12; // [1029:998] - power_manager_reg2hw_core_reg_x13_reg_t core_reg_x13; // [997:966] - power_manager_reg2hw_core_reg_x14_reg_t core_reg_x14; // [965:934] - power_manager_reg2hw_core_reg_x15_reg_t core_reg_x15; // [933:902] - power_manager_reg2hw_core_reg_x16_reg_t core_reg_x16; // [901:870] - power_manager_reg2hw_core_reg_x17_reg_t core_reg_x17; // [869:838] - power_manager_reg2hw_core_reg_x18_reg_t core_reg_x18; // [837:806] - power_manager_reg2hw_core_reg_x19_reg_t core_reg_x19; // [805:774] - power_manager_reg2hw_core_reg_x20_reg_t core_reg_x20; // [773:742] - power_manager_reg2hw_core_reg_x21_reg_t core_reg_x21; // [741:710] - power_manager_reg2hw_core_reg_x22_reg_t core_reg_x22; // [709:678] - power_manager_reg2hw_core_reg_x23_reg_t core_reg_x23; // [677:646] - power_manager_reg2hw_core_reg_x24_reg_t core_reg_x24; // [645:614] - power_manager_reg2hw_core_reg_x25_reg_t core_reg_x25; // [613:582] - power_manager_reg2hw_core_reg_x26_reg_t core_reg_x26; // [581:550] - power_manager_reg2hw_core_reg_x27_reg_t core_reg_x27; // [549:518] - power_manager_reg2hw_core_reg_x28_reg_t core_reg_x28; // [517:486] - power_manager_reg2hw_core_reg_x29_reg_t core_reg_x29; // [485:454] - power_manager_reg2hw_core_reg_x30_reg_t core_reg_x30; // [453:422] - power_manager_reg2hw_core_reg_x31_reg_t core_reg_x31; // [421:390] - power_manager_reg2hw_core_csr_c0_reg_t core_csr_c0; // [389:358] - power_manager_reg2hw_core_csr_c1_reg_t core_csr_c1; // [357:326] - power_manager_reg2hw_core_csr_c2_reg_t core_csr_c2; // [325:294] - power_manager_reg2hw_core_csr_c3_reg_t core_csr_c3; // [293:262] - power_manager_reg2hw_core_csr_c4_reg_t core_csr_c4; // [261:230] - power_manager_reg2hw_core_csr_c5_reg_t core_csr_c5; // [229:198] - power_manager_reg2hw_core_csr_c6_reg_t core_csr_c6; // [197:166] - power_manager_reg2hw_core_csr_c7_reg_t core_csr_c7; // [165:134] - power_manager_reg2hw_en_wait_for_intr_reg_t en_wait_for_intr; // [133:133] - power_manager_reg2hw_intr_state_reg_t intr_state; // [132:132] - power_manager_reg2hw_cpu_reset_assert_counter_reg_t cpu_reset_assert_counter; // [131:100] - power_manager_reg2hw_cpu_reset_deassert_counter_reg_t cpu_reset_deassert_counter; // [99:68] - power_manager_reg2hw_cpu_switch_off_counter_reg_t cpu_switch_off_counter; // [67:36] - power_manager_reg2hw_cpu_switch_on_counter_reg_t cpu_switch_on_counter; // [35:4] - power_manager_reg2hw_cpu_counters_stop_reg_t cpu_counters_stop; // [3:0] - } power_manager_reg2hw_t; - - // HW -> register type - typedef struct packed { - power_manager_hw2reg_intr_state_reg_t intr_state; // [133:132] - power_manager_hw2reg_cpu_reset_assert_counter_reg_t cpu_reset_assert_counter; // [131:99] - power_manager_hw2reg_cpu_reset_deassert_counter_reg_t cpu_reset_deassert_counter; // [98:66] - power_manager_hw2reg_cpu_switch_off_counter_reg_t cpu_switch_off_counter; // [65:33] - power_manager_hw2reg_cpu_switch_on_counter_reg_t cpu_switch_on_counter; // [32:0] - } power_manager_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] POWER_MANAGER_POWER_GATE_CORE_OFFSET = 8'h0; - parameter logic [BlockAw-1:0] POWER_MANAGER_WAKEUP_STATE_OFFSET = 8'h4; - parameter logic [BlockAw-1:0] POWER_MANAGER_RESTORE_ADDRESS_OFFSET = 8'h8; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X1_OFFSET = 8'hc; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X2_OFFSET = 8'h10; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X3_OFFSET = 8'h14; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X4_OFFSET = 8'h18; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X5_OFFSET = 8'h1c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X6_OFFSET = 8'h20; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X7_OFFSET = 8'h24; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X8_OFFSET = 8'h28; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X9_OFFSET = 8'h2c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X10_OFFSET = 8'h30; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X11_OFFSET = 8'h34; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X12_OFFSET = 8'h38; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X13_OFFSET = 8'h3c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X14_OFFSET = 8'h40; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X15_OFFSET = 8'h44; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X16_OFFSET = 8'h48; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X17_OFFSET = 8'h4c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X18_OFFSET = 8'h50; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X19_OFFSET = 8'h54; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X20_OFFSET = 8'h58; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X21_OFFSET = 8'h5c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X22_OFFSET = 8'h60; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X23_OFFSET = 8'h64; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X24_OFFSET = 8'h68; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X25_OFFSET = 8'h6c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X26_OFFSET = 8'h70; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X27_OFFSET = 8'h74; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X28_OFFSET = 8'h78; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X29_OFFSET = 8'h7c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X30_OFFSET = 8'h80; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_REG_X31_OFFSET = 8'h84; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_CSR_C0_OFFSET = 8'h88; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_CSR_C1_OFFSET = 8'h8c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_CSR_C2_OFFSET = 8'h90; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_CSR_C3_OFFSET = 8'h94; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_CSR_C4_OFFSET = 8'h98; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_CSR_C5_OFFSET = 8'h9c; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_CSR_C6_OFFSET = 8'ha0; - parameter logic [BlockAw-1:0] POWER_MANAGER_CORE_CSR_C7_OFFSET = 8'ha4; - parameter logic [BlockAw-1:0] POWER_MANAGER_EN_WAIT_FOR_INTR_OFFSET = 8'ha8; - parameter logic [BlockAw-1:0] POWER_MANAGER_INTR_STATE_OFFSET = 8'hac; - parameter logic [BlockAw-1:0] POWER_MANAGER_CPU_RESET_ASSERT_COUNTER_OFFSET = 8'hb0; - parameter logic [BlockAw-1:0] POWER_MANAGER_CPU_RESET_DEASSERT_COUNTER_OFFSET = 8'hb4; - parameter logic [BlockAw-1:0] POWER_MANAGER_CPU_SWITCH_OFF_COUNTER_OFFSET = 8'hb8; - parameter logic [BlockAw-1:0] POWER_MANAGER_CPU_SWITCH_ON_COUNTER_OFFSET = 8'hbc; - parameter logic [BlockAw-1:0] POWER_MANAGER_CPU_COUNTERS_STOP_OFFSET = 8'hc0; - - // Register index - typedef enum int { - POWER_MANAGER_POWER_GATE_CORE, - POWER_MANAGER_WAKEUP_STATE, - POWER_MANAGER_RESTORE_ADDRESS, - POWER_MANAGER_CORE_REG_X1, - POWER_MANAGER_CORE_REG_X2, - POWER_MANAGER_CORE_REG_X3, - POWER_MANAGER_CORE_REG_X4, - POWER_MANAGER_CORE_REG_X5, - POWER_MANAGER_CORE_REG_X6, - POWER_MANAGER_CORE_REG_X7, - POWER_MANAGER_CORE_REG_X8, - POWER_MANAGER_CORE_REG_X9, - POWER_MANAGER_CORE_REG_X10, - POWER_MANAGER_CORE_REG_X11, - POWER_MANAGER_CORE_REG_X12, - POWER_MANAGER_CORE_REG_X13, - POWER_MANAGER_CORE_REG_X14, - POWER_MANAGER_CORE_REG_X15, - POWER_MANAGER_CORE_REG_X16, - POWER_MANAGER_CORE_REG_X17, - POWER_MANAGER_CORE_REG_X18, - POWER_MANAGER_CORE_REG_X19, - POWER_MANAGER_CORE_REG_X20, - POWER_MANAGER_CORE_REG_X21, - POWER_MANAGER_CORE_REG_X22, - POWER_MANAGER_CORE_REG_X23, - POWER_MANAGER_CORE_REG_X24, - POWER_MANAGER_CORE_REG_X25, - POWER_MANAGER_CORE_REG_X26, - POWER_MANAGER_CORE_REG_X27, - POWER_MANAGER_CORE_REG_X28, - POWER_MANAGER_CORE_REG_X29, - POWER_MANAGER_CORE_REG_X30, - POWER_MANAGER_CORE_REG_X31, - POWER_MANAGER_CORE_CSR_C0, - POWER_MANAGER_CORE_CSR_C1, - POWER_MANAGER_CORE_CSR_C2, - POWER_MANAGER_CORE_CSR_C3, - POWER_MANAGER_CORE_CSR_C4, - POWER_MANAGER_CORE_CSR_C5, - POWER_MANAGER_CORE_CSR_C6, - POWER_MANAGER_CORE_CSR_C7, - POWER_MANAGER_EN_WAIT_FOR_INTR, - POWER_MANAGER_INTR_STATE, - POWER_MANAGER_CPU_RESET_ASSERT_COUNTER, - POWER_MANAGER_CPU_RESET_DEASSERT_COUNTER, - POWER_MANAGER_CPU_SWITCH_OFF_COUNTER, - POWER_MANAGER_CPU_SWITCH_ON_COUNTER, - POWER_MANAGER_CPU_COUNTERS_STOP - } power_manager_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] POWER_MANAGER_PERMIT[49] = '{ - 4'b0001, // index[ 0] POWER_MANAGER_POWER_GATE_CORE - 4'b0001, // index[ 1] POWER_MANAGER_WAKEUP_STATE - 4'b1111, // index[ 2] POWER_MANAGER_RESTORE_ADDRESS - 4'b1111, // index[ 3] POWER_MANAGER_CORE_REG_X1 - 4'b1111, // index[ 4] POWER_MANAGER_CORE_REG_X2 - 4'b1111, // index[ 5] POWER_MANAGER_CORE_REG_X3 - 4'b1111, // index[ 6] POWER_MANAGER_CORE_REG_X4 - 4'b1111, // index[ 7] POWER_MANAGER_CORE_REG_X5 - 4'b1111, // index[ 8] POWER_MANAGER_CORE_REG_X6 - 4'b1111, // index[ 9] POWER_MANAGER_CORE_REG_X7 - 4'b1111, // index[10] POWER_MANAGER_CORE_REG_X8 - 4'b1111, // index[11] POWER_MANAGER_CORE_REG_X9 - 4'b1111, // index[12] POWER_MANAGER_CORE_REG_X10 - 4'b1111, // index[13] POWER_MANAGER_CORE_REG_X11 - 4'b1111, // index[14] POWER_MANAGER_CORE_REG_X12 - 4'b1111, // index[15] POWER_MANAGER_CORE_REG_X13 - 4'b1111, // index[16] POWER_MANAGER_CORE_REG_X14 - 4'b1111, // index[17] POWER_MANAGER_CORE_REG_X15 - 4'b1111, // index[18] POWER_MANAGER_CORE_REG_X16 - 4'b1111, // index[19] POWER_MANAGER_CORE_REG_X17 - 4'b1111, // index[20] POWER_MANAGER_CORE_REG_X18 - 4'b1111, // index[21] POWER_MANAGER_CORE_REG_X19 - 4'b1111, // index[22] POWER_MANAGER_CORE_REG_X20 - 4'b1111, // index[23] POWER_MANAGER_CORE_REG_X21 - 4'b1111, // index[24] POWER_MANAGER_CORE_REG_X22 - 4'b1111, // index[25] POWER_MANAGER_CORE_REG_X23 - 4'b1111, // index[26] POWER_MANAGER_CORE_REG_X24 - 4'b1111, // index[27] POWER_MANAGER_CORE_REG_X25 - 4'b1111, // index[28] POWER_MANAGER_CORE_REG_X26 - 4'b1111, // index[29] POWER_MANAGER_CORE_REG_X27 - 4'b1111, // index[30] POWER_MANAGER_CORE_REG_X28 - 4'b1111, // index[31] POWER_MANAGER_CORE_REG_X29 - 4'b1111, // index[32] POWER_MANAGER_CORE_REG_X30 - 4'b1111, // index[33] POWER_MANAGER_CORE_REG_X31 - 4'b1111, // index[34] POWER_MANAGER_CORE_CSR_C0 - 4'b1111, // index[35] POWER_MANAGER_CORE_CSR_C1 - 4'b1111, // index[36] POWER_MANAGER_CORE_CSR_C2 - 4'b1111, // index[37] POWER_MANAGER_CORE_CSR_C3 - 4'b1111, // index[38] POWER_MANAGER_CORE_CSR_C4 - 4'b1111, // index[39] POWER_MANAGER_CORE_CSR_C5 - 4'b1111, // index[40] POWER_MANAGER_CORE_CSR_C6 - 4'b1111, // index[41] POWER_MANAGER_CORE_CSR_C7 - 4'b0001, // index[42] POWER_MANAGER_EN_WAIT_FOR_INTR - 4'b0001, // index[43] POWER_MANAGER_INTR_STATE - 4'b1111, // index[44] POWER_MANAGER_CPU_RESET_ASSERT_COUNTER - 4'b1111, // index[45] POWER_MANAGER_CPU_RESET_DEASSERT_COUNTER - 4'b1111, // index[46] POWER_MANAGER_CPU_SWITCH_OFF_COUNTER - 4'b1111, // index[47] POWER_MANAGER_CPU_SWITCH_ON_COUNTER - 4'b0001 // index[48] POWER_MANAGER_CPU_COUNTERS_STOP - }; - -endpackage - diff --git a/hw/ip/power_manager/rtl/power_manager_reg_top.sv b/hw/ip/power_manager/rtl/power_manager_reg_top.sv deleted file mode 100644 index d116d7d48..000000000 --- a/hw/ip/power_manager/rtl/power_manager_reg_top.sv +++ /dev/null @@ -1,2120 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module power_manager_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 8 -) ( - input clk_i, - input rst_ni, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - // To HW - output power_manager_reg_pkg::power_manager_reg2hw_t reg2hw, // Write - input power_manager_reg_pkg::power_manager_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import power_manager_reg_pkg::*; - - localparam int DW = 32; - localparam int DBW = DW / 8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [ AW-1:0] reg_addr; - logic [ DW-1:0] reg_wdata; - logic [DBW-1:0] reg_be; - logic [ DW-1:0] reg_rdata; - logic reg_error; - - logic addrmiss, wr_err; - - logic [DW-1:0] reg_rdata_next; - - // Below register interface can be changed - reg_req_t reg_intf_req; - reg_rsp_t reg_intf_rsp; - - - assign reg_intf_req = reg_req_i; - assign reg_rsp_o = reg_intf_rsp; - - - assign reg_we = reg_intf_req.valid & reg_intf_req.write; - assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; - assign reg_addr = reg_intf_req.addr; - assign reg_wdata = reg_intf_req.wdata; - assign reg_be = reg_intf_req.wstrb; - assign reg_intf_rsp.rdata = reg_rdata; - assign reg_intf_rsp.error = reg_error; - assign reg_intf_rsp.ready = 1'b1; - - assign reg_rdata = reg_rdata_next; - assign reg_error = (devmode_i & addrmiss) | wr_err; - - - // Define SW related signals - // Format: __{wd|we|qs} - // or _{wd|we|qs} if field == 1 or 0 - logic power_gate_core_qs; - logic power_gate_core_wd; - logic power_gate_core_we; - logic wakeup_state_qs; - logic wakeup_state_wd; - logic wakeup_state_we; - logic [31:0] restore_address_qs; - logic [31:0] restore_address_wd; - logic restore_address_we; - logic [31:0] core_reg_x1_qs; - logic [31:0] core_reg_x1_wd; - logic core_reg_x1_we; - logic [31:0] core_reg_x2_qs; - logic [31:0] core_reg_x2_wd; - logic core_reg_x2_we; - logic [31:0] core_reg_x3_qs; - logic [31:0] core_reg_x3_wd; - logic core_reg_x3_we; - logic [31:0] core_reg_x4_qs; - logic [31:0] core_reg_x4_wd; - logic core_reg_x4_we; - logic [31:0] core_reg_x5_qs; - logic [31:0] core_reg_x5_wd; - logic core_reg_x5_we; - logic [31:0] core_reg_x6_qs; - logic [31:0] core_reg_x6_wd; - logic core_reg_x6_we; - logic [31:0] core_reg_x7_qs; - logic [31:0] core_reg_x7_wd; - logic core_reg_x7_we; - logic [31:0] core_reg_x8_qs; - logic [31:0] core_reg_x8_wd; - logic core_reg_x8_we; - logic [31:0] core_reg_x9_qs; - logic [31:0] core_reg_x9_wd; - logic core_reg_x9_we; - logic [31:0] core_reg_x10_qs; - logic [31:0] core_reg_x10_wd; - logic core_reg_x10_we; - logic [31:0] core_reg_x11_qs; - logic [31:0] core_reg_x11_wd; - logic core_reg_x11_we; - logic [31:0] core_reg_x12_qs; - logic [31:0] core_reg_x12_wd; - logic core_reg_x12_we; - logic [31:0] core_reg_x13_qs; - logic [31:0] core_reg_x13_wd; - logic core_reg_x13_we; - logic [31:0] core_reg_x14_qs; - logic [31:0] core_reg_x14_wd; - logic core_reg_x14_we; - logic [31:0] core_reg_x15_qs; - logic [31:0] core_reg_x15_wd; - logic core_reg_x15_we; - logic [31:0] core_reg_x16_qs; - logic [31:0] core_reg_x16_wd; - logic core_reg_x16_we; - logic [31:0] core_reg_x17_qs; - logic [31:0] core_reg_x17_wd; - logic core_reg_x17_we; - logic [31:0] core_reg_x18_qs; - logic [31:0] core_reg_x18_wd; - logic core_reg_x18_we; - logic [31:0] core_reg_x19_qs; - logic [31:0] core_reg_x19_wd; - logic core_reg_x19_we; - logic [31:0] core_reg_x20_qs; - logic [31:0] core_reg_x20_wd; - logic core_reg_x20_we; - logic [31:0] core_reg_x21_qs; - logic [31:0] core_reg_x21_wd; - logic core_reg_x21_we; - logic [31:0] core_reg_x22_qs; - logic [31:0] core_reg_x22_wd; - logic core_reg_x22_we; - logic [31:0] core_reg_x23_qs; - logic [31:0] core_reg_x23_wd; - logic core_reg_x23_we; - logic [31:0] core_reg_x24_qs; - logic [31:0] core_reg_x24_wd; - logic core_reg_x24_we; - logic [31:0] core_reg_x25_qs; - logic [31:0] core_reg_x25_wd; - logic core_reg_x25_we; - logic [31:0] core_reg_x26_qs; - logic [31:0] core_reg_x26_wd; - logic core_reg_x26_we; - logic [31:0] core_reg_x27_qs; - logic [31:0] core_reg_x27_wd; - logic core_reg_x27_we; - logic [31:0] core_reg_x28_qs; - logic [31:0] core_reg_x28_wd; - logic core_reg_x28_we; - logic [31:0] core_reg_x29_qs; - logic [31:0] core_reg_x29_wd; - logic core_reg_x29_we; - logic [31:0] core_reg_x30_qs; - logic [31:0] core_reg_x30_wd; - logic core_reg_x30_we; - logic [31:0] core_reg_x31_qs; - logic [31:0] core_reg_x31_wd; - logic core_reg_x31_we; - logic [31:0] core_csr_c0_qs; - logic [31:0] core_csr_c0_wd; - logic core_csr_c0_we; - logic [31:0] core_csr_c1_qs; - logic [31:0] core_csr_c1_wd; - logic core_csr_c1_we; - logic [31:0] core_csr_c2_qs; - logic [31:0] core_csr_c2_wd; - logic core_csr_c2_we; - logic [31:0] core_csr_c3_qs; - logic [31:0] core_csr_c3_wd; - logic core_csr_c3_we; - logic [31:0] core_csr_c4_qs; - logic [31:0] core_csr_c4_wd; - logic core_csr_c4_we; - logic [31:0] core_csr_c5_qs; - logic [31:0] core_csr_c5_wd; - logic core_csr_c5_we; - logic [31:0] core_csr_c6_qs; - logic [31:0] core_csr_c6_wd; - logic core_csr_c6_we; - logic [31:0] core_csr_c7_qs; - logic [31:0] core_csr_c7_wd; - logic core_csr_c7_we; - logic en_wait_for_intr_qs; - logic en_wait_for_intr_wd; - logic en_wait_for_intr_we; - logic intr_state_qs; - logic intr_state_wd; - logic intr_state_we; - logic [31:0] cpu_reset_assert_counter_qs; - logic [31:0] cpu_reset_assert_counter_wd; - logic cpu_reset_assert_counter_we; - logic [31:0] cpu_reset_deassert_counter_qs; - logic [31:0] cpu_reset_deassert_counter_wd; - logic cpu_reset_deassert_counter_we; - logic [31:0] cpu_switch_off_counter_qs; - logic [31:0] cpu_switch_off_counter_wd; - logic cpu_switch_off_counter_we; - logic [31:0] cpu_switch_on_counter_qs; - logic [31:0] cpu_switch_on_counter_wd; - logic cpu_switch_on_counter_we; - logic cpu_counters_stop_cpu_reset_assert_stop_bit_counter_qs; - logic cpu_counters_stop_cpu_reset_assert_stop_bit_counter_wd; - logic cpu_counters_stop_cpu_reset_assert_stop_bit_counter_we; - logic cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_qs; - logic cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_wd; - logic cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_we; - logic cpu_counters_stop_cpu_switch_off_stop_bit_counter_qs; - logic cpu_counters_stop_cpu_switch_off_stop_bit_counter_wd; - logic cpu_counters_stop_cpu_switch_off_stop_bit_counter_we; - logic cpu_counters_stop_cpu_switch_on_stop_bit_counter_qs; - logic cpu_counters_stop_cpu_switch_on_stop_bit_counter_wd; - logic cpu_counters_stop_cpu_switch_on_stop_bit_counter_we; - - // Register instances - // R[power_gate_core]: V(False) - - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_power_gate_core ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(power_gate_core_we), - .wd(power_gate_core_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.power_gate_core.q), - - // to register interface (read) - .qs(power_gate_core_qs) - ); - - - // R[wakeup_state]: V(False) - - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_wakeup_state ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(wakeup_state_we), - .wd(wakeup_state_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.wakeup_state.q), - - // to register interface (read) - .qs(wakeup_state_qs) - ); - - - // R[restore_address]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_restore_address ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(restore_address_we), - .wd(restore_address_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.restore_address.q), - - // to register interface (read) - .qs(restore_address_qs) - ); - - - // R[core_reg_x1]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x1 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x1_we), - .wd(core_reg_x1_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x1.q), - - // to register interface (read) - .qs(core_reg_x1_qs) - ); - - - // R[core_reg_x2]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x2 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x2_we), - .wd(core_reg_x2_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x2.q), - - // to register interface (read) - .qs(core_reg_x2_qs) - ); - - - // R[core_reg_x3]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x3 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x3_we), - .wd(core_reg_x3_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x3.q), - - // to register interface (read) - .qs(core_reg_x3_qs) - ); - - - // R[core_reg_x4]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x4 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x4_we), - .wd(core_reg_x4_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x4.q), - - // to register interface (read) - .qs(core_reg_x4_qs) - ); - - - // R[core_reg_x5]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x5 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x5_we), - .wd(core_reg_x5_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x5.q), - - // to register interface (read) - .qs(core_reg_x5_qs) - ); - - - // R[core_reg_x6]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x6 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x6_we), - .wd(core_reg_x6_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x6.q), - - // to register interface (read) - .qs(core_reg_x6_qs) - ); - - - // R[core_reg_x7]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x7 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x7_we), - .wd(core_reg_x7_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x7.q), - - // to register interface (read) - .qs(core_reg_x7_qs) - ); - - - // R[core_reg_x8]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x8 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x8_we), - .wd(core_reg_x8_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x8.q), - - // to register interface (read) - .qs(core_reg_x8_qs) - ); - - - // R[core_reg_x9]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x9 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x9_we), - .wd(core_reg_x9_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x9.q), - - // to register interface (read) - .qs(core_reg_x9_qs) - ); - - - // R[core_reg_x10]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x10 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x10_we), - .wd(core_reg_x10_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x10.q), - - // to register interface (read) - .qs(core_reg_x10_qs) - ); - - - // R[core_reg_x11]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x11 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x11_we), - .wd(core_reg_x11_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x11.q), - - // to register interface (read) - .qs(core_reg_x11_qs) - ); - - - // R[core_reg_x12]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x12 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x12_we), - .wd(core_reg_x12_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x12.q), - - // to register interface (read) - .qs(core_reg_x12_qs) - ); - - - // R[core_reg_x13]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x13 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x13_we), - .wd(core_reg_x13_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x13.q), - - // to register interface (read) - .qs(core_reg_x13_qs) - ); - - - // R[core_reg_x14]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x14 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x14_we), - .wd(core_reg_x14_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x14.q), - - // to register interface (read) - .qs(core_reg_x14_qs) - ); - - - // R[core_reg_x15]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x15 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x15_we), - .wd(core_reg_x15_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x15.q), - - // to register interface (read) - .qs(core_reg_x15_qs) - ); - - - // R[core_reg_x16]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x16 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x16_we), - .wd(core_reg_x16_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x16.q), - - // to register interface (read) - .qs(core_reg_x16_qs) - ); - - - // R[core_reg_x17]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x17 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x17_we), - .wd(core_reg_x17_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x17.q), - - // to register interface (read) - .qs(core_reg_x17_qs) - ); - - - // R[core_reg_x18]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x18 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x18_we), - .wd(core_reg_x18_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x18.q), - - // to register interface (read) - .qs(core_reg_x18_qs) - ); - - - // R[core_reg_x19]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x19 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x19_we), - .wd(core_reg_x19_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x19.q), - - // to register interface (read) - .qs(core_reg_x19_qs) - ); - - - // R[core_reg_x20]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x20 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x20_we), - .wd(core_reg_x20_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x20.q), - - // to register interface (read) - .qs(core_reg_x20_qs) - ); - - - // R[core_reg_x21]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x21 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x21_we), - .wd(core_reg_x21_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x21.q), - - // to register interface (read) - .qs(core_reg_x21_qs) - ); - - - // R[core_reg_x22]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x22 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x22_we), - .wd(core_reg_x22_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x22.q), - - // to register interface (read) - .qs(core_reg_x22_qs) - ); - - - // R[core_reg_x23]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x23 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x23_we), - .wd(core_reg_x23_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x23.q), - - // to register interface (read) - .qs(core_reg_x23_qs) - ); - - - // R[core_reg_x24]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x24 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x24_we), - .wd(core_reg_x24_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x24.q), - - // to register interface (read) - .qs(core_reg_x24_qs) - ); - - - // R[core_reg_x25]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x25 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x25_we), - .wd(core_reg_x25_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x25.q), - - // to register interface (read) - .qs(core_reg_x25_qs) - ); - - - // R[core_reg_x26]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x26 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x26_we), - .wd(core_reg_x26_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x26.q), - - // to register interface (read) - .qs(core_reg_x26_qs) - ); - - - // R[core_reg_x27]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x27 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x27_we), - .wd(core_reg_x27_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x27.q), - - // to register interface (read) - .qs(core_reg_x27_qs) - ); - - - // R[core_reg_x28]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x28 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x28_we), - .wd(core_reg_x28_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x28.q), - - // to register interface (read) - .qs(core_reg_x28_qs) - ); - - - // R[core_reg_x29]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x29 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x29_we), - .wd(core_reg_x29_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x29.q), - - // to register interface (read) - .qs(core_reg_x29_qs) - ); - - - // R[core_reg_x30]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x30 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x30_we), - .wd(core_reg_x30_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x30.q), - - // to register interface (read) - .qs(core_reg_x30_qs) - ); - - - // R[core_reg_x31]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_reg_x31 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_reg_x31_we), - .wd(core_reg_x31_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_reg_x31.q), - - // to register interface (read) - .qs(core_reg_x31_qs) - ); - - - // R[core_csr_c0]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_csr_c0 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_csr_c0_we), - .wd(core_csr_c0_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_csr_c0.q), - - // to register interface (read) - .qs(core_csr_c0_qs) - ); - - - // R[core_csr_c1]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_csr_c1 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_csr_c1_we), - .wd(core_csr_c1_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_csr_c1.q), - - // to register interface (read) - .qs(core_csr_c1_qs) - ); - - - // R[core_csr_c2]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_csr_c2 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_csr_c2_we), - .wd(core_csr_c2_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_csr_c2.q), - - // to register interface (read) - .qs(core_csr_c2_qs) - ); - - - // R[core_csr_c3]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_csr_c3 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_csr_c3_we), - .wd(core_csr_c3_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_csr_c3.q), - - // to register interface (read) - .qs(core_csr_c3_qs) - ); - - - // R[core_csr_c4]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_csr_c4 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_csr_c4_we), - .wd(core_csr_c4_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_csr_c4.q), - - // to register interface (read) - .qs(core_csr_c4_qs) - ); - - - // R[core_csr_c5]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_csr_c5 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_csr_c5_we), - .wd(core_csr_c5_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_csr_c5.q), - - // to register interface (read) - .qs(core_csr_c5_qs) - ); - - - // R[core_csr_c6]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_csr_c6 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_csr_c6_we), - .wd(core_csr_c6_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_csr_c6.q), - - // to register interface (read) - .qs(core_csr_c6_qs) - ); - - - // R[core_csr_c7]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_core_csr_c7 ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(core_csr_c7_we), - .wd(core_csr_c7_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.core_csr_c7.q), - - // to register interface (read) - .qs(core_csr_c7_qs) - ); - - - // R[en_wait_for_intr]: V(False) - - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_en_wait_for_intr ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(en_wait_for_intr_we), - .wd(en_wait_for_intr_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.en_wait_for_intr.q), - - // to register interface (read) - .qs(en_wait_for_intr_qs) - ); - - - // R[intr_state]: V(False) - - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_intr_state ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(intr_state_we), - .wd(intr_state_wd), - - // from internal hardware - .de(hw2reg.intr_state.de), - .d (hw2reg.intr_state.d), - - // to internal hardware - .qe(), - .q (reg2hw.intr_state.q), - - // to register interface (read) - .qs(intr_state_qs) - ); - - - // R[cpu_reset_assert_counter]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_cpu_reset_assert_counter ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(cpu_reset_assert_counter_we), - .wd(cpu_reset_assert_counter_wd), - - // from internal hardware - .de(hw2reg.cpu_reset_assert_counter.de), - .d (hw2reg.cpu_reset_assert_counter.d), - - // to internal hardware - .qe(), - .q (reg2hw.cpu_reset_assert_counter.q), - - // to register interface (read) - .qs(cpu_reset_assert_counter_qs) - ); - - - // R[cpu_reset_deassert_counter]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_cpu_reset_deassert_counter ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(cpu_reset_deassert_counter_we), - .wd(cpu_reset_deassert_counter_wd), - - // from internal hardware - .de(hw2reg.cpu_reset_deassert_counter.de), - .d (hw2reg.cpu_reset_deassert_counter.d), - - // to internal hardware - .qe(), - .q (reg2hw.cpu_reset_deassert_counter.q), - - // to register interface (read) - .qs(cpu_reset_deassert_counter_qs) - ); - - - // R[cpu_switch_off_counter]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_cpu_switch_off_counter ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(cpu_switch_off_counter_we), - .wd(cpu_switch_off_counter_wd), - - // from internal hardware - .de(hw2reg.cpu_switch_off_counter.de), - .d (hw2reg.cpu_switch_off_counter.d), - - // to internal hardware - .qe(), - .q (reg2hw.cpu_switch_off_counter.q), - - // to register interface (read) - .qs(cpu_switch_off_counter_qs) - ); - - - // R[cpu_switch_on_counter]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_cpu_switch_on_counter ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(cpu_switch_on_counter_we), - .wd(cpu_switch_on_counter_wd), - - // from internal hardware - .de(hw2reg.cpu_switch_on_counter.de), - .d (hw2reg.cpu_switch_on_counter.d), - - // to internal hardware - .qe(), - .q (reg2hw.cpu_switch_on_counter.q), - - // to register interface (read) - .qs(cpu_switch_on_counter_qs) - ); - - - // R[cpu_counters_stop]: V(False) - - // F[cpu_reset_assert_stop_bit_counter]: 0:0 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_cpu_counters_stop_cpu_reset_assert_stop_bit_counter ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(cpu_counters_stop_cpu_reset_assert_stop_bit_counter_we), - .wd(cpu_counters_stop_cpu_reset_assert_stop_bit_counter_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.cpu_counters_stop.cpu_reset_assert_stop_bit_counter.q), - - // to register interface (read) - .qs(cpu_counters_stop_cpu_reset_assert_stop_bit_counter_qs) - ); - - - // F[cpu_reset_deassert_stop_bit_counter]: 1:1 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_cpu_counters_stop_cpu_reset_deassert_stop_bit_counter ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_we), - .wd(cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.cpu_counters_stop.cpu_reset_deassert_stop_bit_counter.q), - - // to register interface (read) - .qs(cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_qs) - ); - - - // F[cpu_switch_off_stop_bit_counter]: 2:2 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_cpu_counters_stop_cpu_switch_off_stop_bit_counter ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(cpu_counters_stop_cpu_switch_off_stop_bit_counter_we), - .wd(cpu_counters_stop_cpu_switch_off_stop_bit_counter_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.cpu_counters_stop.cpu_switch_off_stop_bit_counter.q), - - // to register interface (read) - .qs(cpu_counters_stop_cpu_switch_off_stop_bit_counter_qs) - ); - - - // F[cpu_switch_on_stop_bit_counter]: 3:3 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_cpu_counters_stop_cpu_switch_on_stop_bit_counter ( - .clk_i (clk_i), - .rst_ni(rst_ni), - - // from register interface - .we(cpu_counters_stop_cpu_switch_on_stop_bit_counter_we), - .wd(cpu_counters_stop_cpu_switch_on_stop_bit_counter_wd), - - // from internal hardware - .de(1'b0), - .d ('0), - - // to internal hardware - .qe(), - .q (reg2hw.cpu_counters_stop.cpu_switch_on_stop_bit_counter.q), - - // to register interface (read) - .qs(cpu_counters_stop_cpu_switch_on_stop_bit_counter_qs) - ); - - - - - logic [48:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[0] = (reg_addr == POWER_MANAGER_POWER_GATE_CORE_OFFSET); - addr_hit[1] = (reg_addr == POWER_MANAGER_WAKEUP_STATE_OFFSET); - addr_hit[2] = (reg_addr == POWER_MANAGER_RESTORE_ADDRESS_OFFSET); - addr_hit[3] = (reg_addr == POWER_MANAGER_CORE_REG_X1_OFFSET); - addr_hit[4] = (reg_addr == POWER_MANAGER_CORE_REG_X2_OFFSET); - addr_hit[5] = (reg_addr == POWER_MANAGER_CORE_REG_X3_OFFSET); - addr_hit[6] = (reg_addr == POWER_MANAGER_CORE_REG_X4_OFFSET); - addr_hit[7] = (reg_addr == POWER_MANAGER_CORE_REG_X5_OFFSET); - addr_hit[8] = (reg_addr == POWER_MANAGER_CORE_REG_X6_OFFSET); - addr_hit[9] = (reg_addr == POWER_MANAGER_CORE_REG_X7_OFFSET); - addr_hit[10] = (reg_addr == POWER_MANAGER_CORE_REG_X8_OFFSET); - addr_hit[11] = (reg_addr == POWER_MANAGER_CORE_REG_X9_OFFSET); - addr_hit[12] = (reg_addr == POWER_MANAGER_CORE_REG_X10_OFFSET); - addr_hit[13] = (reg_addr == POWER_MANAGER_CORE_REG_X11_OFFSET); - addr_hit[14] = (reg_addr == POWER_MANAGER_CORE_REG_X12_OFFSET); - addr_hit[15] = (reg_addr == POWER_MANAGER_CORE_REG_X13_OFFSET); - addr_hit[16] = (reg_addr == POWER_MANAGER_CORE_REG_X14_OFFSET); - addr_hit[17] = (reg_addr == POWER_MANAGER_CORE_REG_X15_OFFSET); - addr_hit[18] = (reg_addr == POWER_MANAGER_CORE_REG_X16_OFFSET); - addr_hit[19] = (reg_addr == POWER_MANAGER_CORE_REG_X17_OFFSET); - addr_hit[20] = (reg_addr == POWER_MANAGER_CORE_REG_X18_OFFSET); - addr_hit[21] = (reg_addr == POWER_MANAGER_CORE_REG_X19_OFFSET); - addr_hit[22] = (reg_addr == POWER_MANAGER_CORE_REG_X20_OFFSET); - addr_hit[23] = (reg_addr == POWER_MANAGER_CORE_REG_X21_OFFSET); - addr_hit[24] = (reg_addr == POWER_MANAGER_CORE_REG_X22_OFFSET); - addr_hit[25] = (reg_addr == POWER_MANAGER_CORE_REG_X23_OFFSET); - addr_hit[26] = (reg_addr == POWER_MANAGER_CORE_REG_X24_OFFSET); - addr_hit[27] = (reg_addr == POWER_MANAGER_CORE_REG_X25_OFFSET); - addr_hit[28] = (reg_addr == POWER_MANAGER_CORE_REG_X26_OFFSET); - addr_hit[29] = (reg_addr == POWER_MANAGER_CORE_REG_X27_OFFSET); - addr_hit[30] = (reg_addr == POWER_MANAGER_CORE_REG_X28_OFFSET); - addr_hit[31] = (reg_addr == POWER_MANAGER_CORE_REG_X29_OFFSET); - addr_hit[32] = (reg_addr == POWER_MANAGER_CORE_REG_X30_OFFSET); - addr_hit[33] = (reg_addr == POWER_MANAGER_CORE_REG_X31_OFFSET); - addr_hit[34] = (reg_addr == POWER_MANAGER_CORE_CSR_C0_OFFSET); - addr_hit[35] = (reg_addr == POWER_MANAGER_CORE_CSR_C1_OFFSET); - addr_hit[36] = (reg_addr == POWER_MANAGER_CORE_CSR_C2_OFFSET); - addr_hit[37] = (reg_addr == POWER_MANAGER_CORE_CSR_C3_OFFSET); - addr_hit[38] = (reg_addr == POWER_MANAGER_CORE_CSR_C4_OFFSET); - addr_hit[39] = (reg_addr == POWER_MANAGER_CORE_CSR_C5_OFFSET); - addr_hit[40] = (reg_addr == POWER_MANAGER_CORE_CSR_C6_OFFSET); - addr_hit[41] = (reg_addr == POWER_MANAGER_CORE_CSR_C7_OFFSET); - addr_hit[42] = (reg_addr == POWER_MANAGER_EN_WAIT_FOR_INTR_OFFSET); - addr_hit[43] = (reg_addr == POWER_MANAGER_INTR_STATE_OFFSET); - addr_hit[44] = (reg_addr == POWER_MANAGER_CPU_RESET_ASSERT_COUNTER_OFFSET); - addr_hit[45] = (reg_addr == POWER_MANAGER_CPU_RESET_DEASSERT_COUNTER_OFFSET); - addr_hit[46] = (reg_addr == POWER_MANAGER_CPU_SWITCH_OFF_COUNTER_OFFSET); - addr_hit[47] = (reg_addr == POWER_MANAGER_CPU_SWITCH_ON_COUNTER_OFFSET); - addr_hit[48] = (reg_addr == POWER_MANAGER_CPU_COUNTERS_STOP_OFFSET); - end - - assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0; - - // Check sub-word write is permitted - always_comb begin - wr_err = (reg_we & - ((addr_hit[ 0] & (|(POWER_MANAGER_PERMIT[ 0] & ~reg_be))) | - (addr_hit[ 1] & (|(POWER_MANAGER_PERMIT[ 1] & ~reg_be))) | - (addr_hit[ 2] & (|(POWER_MANAGER_PERMIT[ 2] & ~reg_be))) | - (addr_hit[ 3] & (|(POWER_MANAGER_PERMIT[ 3] & ~reg_be))) | - (addr_hit[ 4] & (|(POWER_MANAGER_PERMIT[ 4] & ~reg_be))) | - (addr_hit[ 5] & (|(POWER_MANAGER_PERMIT[ 5] & ~reg_be))) | - (addr_hit[ 6] & (|(POWER_MANAGER_PERMIT[ 6] & ~reg_be))) | - (addr_hit[ 7] & (|(POWER_MANAGER_PERMIT[ 7] & ~reg_be))) | - (addr_hit[ 8] & (|(POWER_MANAGER_PERMIT[ 8] & ~reg_be))) | - (addr_hit[ 9] & (|(POWER_MANAGER_PERMIT[ 9] & ~reg_be))) | - (addr_hit[10] & (|(POWER_MANAGER_PERMIT[10] & ~reg_be))) | - (addr_hit[11] & (|(POWER_MANAGER_PERMIT[11] & ~reg_be))) | - (addr_hit[12] & (|(POWER_MANAGER_PERMIT[12] & ~reg_be))) | - (addr_hit[13] & (|(POWER_MANAGER_PERMIT[13] & ~reg_be))) | - (addr_hit[14] & (|(POWER_MANAGER_PERMIT[14] & ~reg_be))) | - (addr_hit[15] & (|(POWER_MANAGER_PERMIT[15] & ~reg_be))) | - (addr_hit[16] & (|(POWER_MANAGER_PERMIT[16] & ~reg_be))) | - (addr_hit[17] & (|(POWER_MANAGER_PERMIT[17] & ~reg_be))) | - (addr_hit[18] & (|(POWER_MANAGER_PERMIT[18] & ~reg_be))) | - (addr_hit[19] & (|(POWER_MANAGER_PERMIT[19] & ~reg_be))) | - (addr_hit[20] & (|(POWER_MANAGER_PERMIT[20] & ~reg_be))) | - (addr_hit[21] & (|(POWER_MANAGER_PERMIT[21] & ~reg_be))) | - (addr_hit[22] & (|(POWER_MANAGER_PERMIT[22] & ~reg_be))) | - (addr_hit[23] & (|(POWER_MANAGER_PERMIT[23] & ~reg_be))) | - (addr_hit[24] & (|(POWER_MANAGER_PERMIT[24] & ~reg_be))) | - (addr_hit[25] & (|(POWER_MANAGER_PERMIT[25] & ~reg_be))) | - (addr_hit[26] & (|(POWER_MANAGER_PERMIT[26] & ~reg_be))) | - (addr_hit[27] & (|(POWER_MANAGER_PERMIT[27] & ~reg_be))) | - (addr_hit[28] & (|(POWER_MANAGER_PERMIT[28] & ~reg_be))) | - (addr_hit[29] & (|(POWER_MANAGER_PERMIT[29] & ~reg_be))) | - (addr_hit[30] & (|(POWER_MANAGER_PERMIT[30] & ~reg_be))) | - (addr_hit[31] & (|(POWER_MANAGER_PERMIT[31] & ~reg_be))) | - (addr_hit[32] & (|(POWER_MANAGER_PERMIT[32] & ~reg_be))) | - (addr_hit[33] & (|(POWER_MANAGER_PERMIT[33] & ~reg_be))) | - (addr_hit[34] & (|(POWER_MANAGER_PERMIT[34] & ~reg_be))) | - (addr_hit[35] & (|(POWER_MANAGER_PERMIT[35] & ~reg_be))) | - (addr_hit[36] & (|(POWER_MANAGER_PERMIT[36] & ~reg_be))) | - (addr_hit[37] & (|(POWER_MANAGER_PERMIT[37] & ~reg_be))) | - (addr_hit[38] & (|(POWER_MANAGER_PERMIT[38] & ~reg_be))) | - (addr_hit[39] & (|(POWER_MANAGER_PERMIT[39] & ~reg_be))) | - (addr_hit[40] & (|(POWER_MANAGER_PERMIT[40] & ~reg_be))) | - (addr_hit[41] & (|(POWER_MANAGER_PERMIT[41] & ~reg_be))) | - (addr_hit[42] & (|(POWER_MANAGER_PERMIT[42] & ~reg_be))) | - (addr_hit[43] & (|(POWER_MANAGER_PERMIT[43] & ~reg_be))) | - (addr_hit[44] & (|(POWER_MANAGER_PERMIT[44] & ~reg_be))) | - (addr_hit[45] & (|(POWER_MANAGER_PERMIT[45] & ~reg_be))) | - (addr_hit[46] & (|(POWER_MANAGER_PERMIT[46] & ~reg_be))) | - (addr_hit[47] & (|(POWER_MANAGER_PERMIT[47] & ~reg_be))) | - (addr_hit[48] & (|(POWER_MANAGER_PERMIT[48] & ~reg_be))))); - end - - assign power_gate_core_we = addr_hit[0] & reg_we & !reg_error; - assign power_gate_core_wd = reg_wdata[0]; - - assign wakeup_state_we = addr_hit[1] & reg_we & !reg_error; - assign wakeup_state_wd = reg_wdata[0]; - - assign restore_address_we = addr_hit[2] & reg_we & !reg_error; - assign restore_address_wd = reg_wdata[31:0]; - - assign core_reg_x1_we = addr_hit[3] & reg_we & !reg_error; - assign core_reg_x1_wd = reg_wdata[31:0]; - - assign core_reg_x2_we = addr_hit[4] & reg_we & !reg_error; - assign core_reg_x2_wd = reg_wdata[31:0]; - - assign core_reg_x3_we = addr_hit[5] & reg_we & !reg_error; - assign core_reg_x3_wd = reg_wdata[31:0]; - - assign core_reg_x4_we = addr_hit[6] & reg_we & !reg_error; - assign core_reg_x4_wd = reg_wdata[31:0]; - - assign core_reg_x5_we = addr_hit[7] & reg_we & !reg_error; - assign core_reg_x5_wd = reg_wdata[31:0]; - - assign core_reg_x6_we = addr_hit[8] & reg_we & !reg_error; - assign core_reg_x6_wd = reg_wdata[31:0]; - - assign core_reg_x7_we = addr_hit[9] & reg_we & !reg_error; - assign core_reg_x7_wd = reg_wdata[31:0]; - - assign core_reg_x8_we = addr_hit[10] & reg_we & !reg_error; - assign core_reg_x8_wd = reg_wdata[31:0]; - - assign core_reg_x9_we = addr_hit[11] & reg_we & !reg_error; - assign core_reg_x9_wd = reg_wdata[31:0]; - - assign core_reg_x10_we = addr_hit[12] & reg_we & !reg_error; - assign core_reg_x10_wd = reg_wdata[31:0]; - - assign core_reg_x11_we = addr_hit[13] & reg_we & !reg_error; - assign core_reg_x11_wd = reg_wdata[31:0]; - - assign core_reg_x12_we = addr_hit[14] & reg_we & !reg_error; - assign core_reg_x12_wd = reg_wdata[31:0]; - - assign core_reg_x13_we = addr_hit[15] & reg_we & !reg_error; - assign core_reg_x13_wd = reg_wdata[31:0]; - - assign core_reg_x14_we = addr_hit[16] & reg_we & !reg_error; - assign core_reg_x14_wd = reg_wdata[31:0]; - - assign core_reg_x15_we = addr_hit[17] & reg_we & !reg_error; - assign core_reg_x15_wd = reg_wdata[31:0]; - - assign core_reg_x16_we = addr_hit[18] & reg_we & !reg_error; - assign core_reg_x16_wd = reg_wdata[31:0]; - - assign core_reg_x17_we = addr_hit[19] & reg_we & !reg_error; - assign core_reg_x17_wd = reg_wdata[31:0]; - - assign core_reg_x18_we = addr_hit[20] & reg_we & !reg_error; - assign core_reg_x18_wd = reg_wdata[31:0]; - - assign core_reg_x19_we = addr_hit[21] & reg_we & !reg_error; - assign core_reg_x19_wd = reg_wdata[31:0]; - - assign core_reg_x20_we = addr_hit[22] & reg_we & !reg_error; - assign core_reg_x20_wd = reg_wdata[31:0]; - - assign core_reg_x21_we = addr_hit[23] & reg_we & !reg_error; - assign core_reg_x21_wd = reg_wdata[31:0]; - - assign core_reg_x22_we = addr_hit[24] & reg_we & !reg_error; - assign core_reg_x22_wd = reg_wdata[31:0]; - - assign core_reg_x23_we = addr_hit[25] & reg_we & !reg_error; - assign core_reg_x23_wd = reg_wdata[31:0]; - - assign core_reg_x24_we = addr_hit[26] & reg_we & !reg_error; - assign core_reg_x24_wd = reg_wdata[31:0]; - - assign core_reg_x25_we = addr_hit[27] & reg_we & !reg_error; - assign core_reg_x25_wd = reg_wdata[31:0]; - - assign core_reg_x26_we = addr_hit[28] & reg_we & !reg_error; - assign core_reg_x26_wd = reg_wdata[31:0]; - - assign core_reg_x27_we = addr_hit[29] & reg_we & !reg_error; - assign core_reg_x27_wd = reg_wdata[31:0]; - - assign core_reg_x28_we = addr_hit[30] & reg_we & !reg_error; - assign core_reg_x28_wd = reg_wdata[31:0]; - - assign core_reg_x29_we = addr_hit[31] & reg_we & !reg_error; - assign core_reg_x29_wd = reg_wdata[31:0]; - - assign core_reg_x30_we = addr_hit[32] & reg_we & !reg_error; - assign core_reg_x30_wd = reg_wdata[31:0]; - - assign core_reg_x31_we = addr_hit[33] & reg_we & !reg_error; - assign core_reg_x31_wd = reg_wdata[31:0]; - - assign core_csr_c0_we = addr_hit[34] & reg_we & !reg_error; - assign core_csr_c0_wd = reg_wdata[31:0]; - - assign core_csr_c1_we = addr_hit[35] & reg_we & !reg_error; - assign core_csr_c1_wd = reg_wdata[31:0]; - - assign core_csr_c2_we = addr_hit[36] & reg_we & !reg_error; - assign core_csr_c2_wd = reg_wdata[31:0]; - - assign core_csr_c3_we = addr_hit[37] & reg_we & !reg_error; - assign core_csr_c3_wd = reg_wdata[31:0]; - - assign core_csr_c4_we = addr_hit[38] & reg_we & !reg_error; - assign core_csr_c4_wd = reg_wdata[31:0]; - - assign core_csr_c5_we = addr_hit[39] & reg_we & !reg_error; - assign core_csr_c5_wd = reg_wdata[31:0]; - - assign core_csr_c6_we = addr_hit[40] & reg_we & !reg_error; - assign core_csr_c6_wd = reg_wdata[31:0]; - - assign core_csr_c7_we = addr_hit[41] & reg_we & !reg_error; - assign core_csr_c7_wd = reg_wdata[31:0]; - - assign en_wait_for_intr_we = addr_hit[42] & reg_we & !reg_error; - assign en_wait_for_intr_wd = reg_wdata[0]; - - assign intr_state_we = addr_hit[43] & reg_we & !reg_error; - assign intr_state_wd = reg_wdata[0]; - - assign cpu_reset_assert_counter_we = addr_hit[44] & reg_we & !reg_error; - assign cpu_reset_assert_counter_wd = reg_wdata[31:0]; - - assign cpu_reset_deassert_counter_we = addr_hit[45] & reg_we & !reg_error; - assign cpu_reset_deassert_counter_wd = reg_wdata[31:0]; - - assign cpu_switch_off_counter_we = addr_hit[46] & reg_we & !reg_error; - assign cpu_switch_off_counter_wd = reg_wdata[31:0]; - - assign cpu_switch_on_counter_we = addr_hit[47] & reg_we & !reg_error; - assign cpu_switch_on_counter_wd = reg_wdata[31:0]; - - assign cpu_counters_stop_cpu_reset_assert_stop_bit_counter_we = addr_hit[48] & reg_we & !reg_error; - assign cpu_counters_stop_cpu_reset_assert_stop_bit_counter_wd = reg_wdata[0]; - - assign cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_we = addr_hit[48] & reg_we & !reg_error; - assign cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_wd = reg_wdata[1]; - - assign cpu_counters_stop_cpu_switch_off_stop_bit_counter_we = addr_hit[48] & reg_we & !reg_error; - assign cpu_counters_stop_cpu_switch_off_stop_bit_counter_wd = reg_wdata[2]; - - assign cpu_counters_stop_cpu_switch_on_stop_bit_counter_we = addr_hit[48] & reg_we & !reg_error; - assign cpu_counters_stop_cpu_switch_on_stop_bit_counter_wd = reg_wdata[3]; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[0] = power_gate_core_qs; - end - - addr_hit[1]: begin - reg_rdata_next[0] = wakeup_state_qs; - end - - addr_hit[2]: begin - reg_rdata_next[31:0] = restore_address_qs; - end - - addr_hit[3]: begin - reg_rdata_next[31:0] = core_reg_x1_qs; - end - - addr_hit[4]: begin - reg_rdata_next[31:0] = core_reg_x2_qs; - end - - addr_hit[5]: begin - reg_rdata_next[31:0] = core_reg_x3_qs; - end - - addr_hit[6]: begin - reg_rdata_next[31:0] = core_reg_x4_qs; - end - - addr_hit[7]: begin - reg_rdata_next[31:0] = core_reg_x5_qs; - end - - addr_hit[8]: begin - reg_rdata_next[31:0] = core_reg_x6_qs; - end - - addr_hit[9]: begin - reg_rdata_next[31:0] = core_reg_x7_qs; - end - - addr_hit[10]: begin - reg_rdata_next[31:0] = core_reg_x8_qs; - end - - addr_hit[11]: begin - reg_rdata_next[31:0] = core_reg_x9_qs; - end - - addr_hit[12]: begin - reg_rdata_next[31:0] = core_reg_x10_qs; - end - - addr_hit[13]: begin - reg_rdata_next[31:0] = core_reg_x11_qs; - end - - addr_hit[14]: begin - reg_rdata_next[31:0] = core_reg_x12_qs; - end - - addr_hit[15]: begin - reg_rdata_next[31:0] = core_reg_x13_qs; - end - - addr_hit[16]: begin - reg_rdata_next[31:0] = core_reg_x14_qs; - end - - addr_hit[17]: begin - reg_rdata_next[31:0] = core_reg_x15_qs; - end - - addr_hit[18]: begin - reg_rdata_next[31:0] = core_reg_x16_qs; - end - - addr_hit[19]: begin - reg_rdata_next[31:0] = core_reg_x17_qs; - end - - addr_hit[20]: begin - reg_rdata_next[31:0] = core_reg_x18_qs; - end - - addr_hit[21]: begin - reg_rdata_next[31:0] = core_reg_x19_qs; - end - - addr_hit[22]: begin - reg_rdata_next[31:0] = core_reg_x20_qs; - end - - addr_hit[23]: begin - reg_rdata_next[31:0] = core_reg_x21_qs; - end - - addr_hit[24]: begin - reg_rdata_next[31:0] = core_reg_x22_qs; - end - - addr_hit[25]: begin - reg_rdata_next[31:0] = core_reg_x23_qs; - end - - addr_hit[26]: begin - reg_rdata_next[31:0] = core_reg_x24_qs; - end - - addr_hit[27]: begin - reg_rdata_next[31:0] = core_reg_x25_qs; - end - - addr_hit[28]: begin - reg_rdata_next[31:0] = core_reg_x26_qs; - end - - addr_hit[29]: begin - reg_rdata_next[31:0] = core_reg_x27_qs; - end - - addr_hit[30]: begin - reg_rdata_next[31:0] = core_reg_x28_qs; - end - - addr_hit[31]: begin - reg_rdata_next[31:0] = core_reg_x29_qs; - end - - addr_hit[32]: begin - reg_rdata_next[31:0] = core_reg_x30_qs; - end - - addr_hit[33]: begin - reg_rdata_next[31:0] = core_reg_x31_qs; - end - - addr_hit[34]: begin - reg_rdata_next[31:0] = core_csr_c0_qs; - end - - addr_hit[35]: begin - reg_rdata_next[31:0] = core_csr_c1_qs; - end - - addr_hit[36]: begin - reg_rdata_next[31:0] = core_csr_c2_qs; - end - - addr_hit[37]: begin - reg_rdata_next[31:0] = core_csr_c3_qs; - end - - addr_hit[38]: begin - reg_rdata_next[31:0] = core_csr_c4_qs; - end - - addr_hit[39]: begin - reg_rdata_next[31:0] = core_csr_c5_qs; - end - - addr_hit[40]: begin - reg_rdata_next[31:0] = core_csr_c6_qs; - end - - addr_hit[41]: begin - reg_rdata_next[31:0] = core_csr_c7_qs; - end - - addr_hit[42]: begin - reg_rdata_next[0] = en_wait_for_intr_qs; - end - - addr_hit[43]: begin - reg_rdata_next[0] = intr_state_qs; - end - - addr_hit[44]: begin - reg_rdata_next[31:0] = cpu_reset_assert_counter_qs; - end - - addr_hit[45]: begin - reg_rdata_next[31:0] = cpu_reset_deassert_counter_qs; - end - - addr_hit[46]: begin - reg_rdata_next[31:0] = cpu_switch_off_counter_qs; - end - - addr_hit[47]: begin - reg_rdata_next[31:0] = cpu_switch_on_counter_qs; - end - - addr_hit[48]: begin - reg_rdata_next[0] = cpu_counters_stop_cpu_reset_assert_stop_bit_counter_qs; - reg_rdata_next[1] = cpu_counters_stop_cpu_reset_deassert_stop_bit_counter_qs; - reg_rdata_next[2] = cpu_counters_stop_cpu_switch_off_stop_bit_counter_qs; - reg_rdata_next[3] = cpu_counters_stop_cpu_switch_on_stop_bit_counter_qs; - end - - default: begin - reg_rdata_next = '1; - end - endcase - end - - // Unused signal tieoff - - // wdata / byte enable are not always fully used - // add a blanket unused statement to handle lint waivers - logic unused_wdata; - logic unused_be; - assign unused_wdata = ^reg_wdata; - assign unused_be = ^reg_be; - - // Assertions for Register Interface - `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) - -endmodule diff --git a/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/data/rv_timer.hjson b/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/data/rv_timer.hjson index 8a41a6863..b00f10a57 100644 --- a/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/data/rv_timer.hjson +++ b/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/data/rv_timer.hjson @@ -15,12 +15,15 @@ { name: "timer_expired_0_0", desc: "raised if the timer 0_0 expired (mtimecmp >= mtime)" }, + { name: "timer_expired_1_0", + desc: "raised if the timer 1_0 expired (mtimecmp >= mtime)" + }, ], param_list: [ { name: "N_HARTS", desc: "Number of harts", type: "int", - default: "1" + default: "2" }, { name: "N_TIMERS", desc: "Number of timers per Hart", @@ -39,10 +42,7 @@ swaccess: "rw", hwaccess: "hro", fields: [ - { bits: "0", name: "active", - desc: "If 1, timer operates", - tags: [// prevent timer from being enabled - "excl:CsrNonInitTests:CsrExclWrite"] } + { bits: "0", name: "active", desc: "If 1, timer operates" } ], } }, @@ -110,9 +110,7 @@ swaccess: "rw1c", hwaccess: "hrw", fields: [ - { bits: "0", name: "IS", desc: "Interrupt status for timer", - tags: [// intr_state csr is affected by writes to other csrs - skip write-check - "excl:CsrNonInitTests:CsrExclWriteCheck"] } + { bits: "0", name: "IS", desc: "Interrupt status for timer" } ], } }, @@ -126,9 +124,89 @@ hwext: "true", hwqe: "true", fields: [ - { bits: "0", name: "T", desc: "Interrupt test for timer", - tags: [// intr_test csr is WO which - it reads back 0s - "excl:CsrNonInitTests:CsrExclWrite"] } + { bits: "0", name: "T", desc: "Interrupt test for timer" } + ] + } + }, + { skipto: "0x200" }, + { name: "CFG1", + desc: "Configuration for Hart 1", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "11:0", name: "prescale", desc: "Prescaler to generate tick" }, + { bits: "23:16", name: "step", resval: "0x1", desc: "Incremental value for each tick" }, + ], + }, + { name: "TIMER_V_LOWER1", + desc: "Timer value Lower", + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "v", desc: "Timer value [31:0]" }, + ], + }, + { name: "TIMER_V_UPPER1", + desc: "Timer value Upper", + swaccess: "rw", + hwaccess: "hrw", + fields: [ + { bits: "31:0", name: "v", desc: "Timer value [63:32]" }, + ], + }, + { name: "COMPARE_LOWER1_0", + desc: "Timer value Lower", + swaccess: "rw", + hwaccess: "hro", + hwqe: "true", + fields: [ + { bits: "31:0", name: "v", resval: "0xffffffff", desc: "Timer compare value [31:0]" }, + ], + }, + { name: "COMPARE_UPPER1_0", + desc: "Timer value Upper", + swaccess: "rw", + hwaccess: "hro", + hwqe: "true", + fields: [ + { bits: "31:0", name: "v", resval: "0xffffffff", desc: "Timer compare value [63:32]" }, + ], + }, + { multireg: { + name: "INTR_ENABLE1", + desc: "Interrupt Enable", + count: "N_TIMERS", + cname: "TIMER", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", name: "IE", desc: "Interrupt Enable for timer" } + ] + } + }, + { multireg: { + name: "INTR_STATE1", + desc: "Interrupt Status", + count: "N_TIMERS", + cname: "TIMER", + swaccess: "rw1c", + hwaccess: "hrw", + fields: [ + { bits: "0", name: "IS", desc: "Interrupt status for timer" } + ], + } + }, + { multireg: { + name: "INTR_TEST1", + desc: "Interrupt test register", + count: "N_TIMERS", + cname: "TIMER", + swaccess: "wo", + hwaccess: "hro", + hwext: "true", + hwqe: "true", + fields: [ + { bits: "0", name: "T", desc: "Interrupt test for timer" } ] } }, diff --git a/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer.sv b/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer.sv index 0ce0bf3f5..9aba20330 100644 --- a/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer.sv +++ b/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer.sv @@ -1,8 +1,6 @@ // Copyright lowRISC contributors. // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -// - `include "prim_assert.sv" @@ -13,10 +11,11 @@ module rv_timer ( input tlul_pkg::tl_h2d_t tl_i, output tlul_pkg::tl_d2h_t tl_o, - output logic intr_timer_expired_0_0_o + output logic intr_timer_expired_0_0_o, + output logic intr_timer_expired_1_0_o ); - localparam int N_HARTS = 1; + localparam int N_HARTS = 2; localparam int N_TIMERS = 1; import rv_timer_reg_pkg::*; @@ -53,25 +52,49 @@ module rv_timer ( // Once reggen supports nested multireg, the following can be automated. For the moment, it must // be connected manually. assign active[0] = reg2hw.ctrl[0].q; - assign prescaler = '{reg2hw.cfg0.prescale.q}; - assign step = '{reg2hw.cfg0.step.q}; + assign active[1] = reg2hw.ctrl[1].q; + + assign prescaler[0] = reg2hw.cfg0.prescale.q; + assign prescaler[1] = reg2hw.cfg1.prescale.q; + + assign step[0] = reg2hw.cfg0.step.q; + assign step[1] = reg2hw.cfg1.step.q; assign hw2reg.timer_v_upper0.de = tick[0]; assign hw2reg.timer_v_lower0.de = tick[0]; + assign hw2reg.timer_v_upper1.de = tick[1]; + assign hw2reg.timer_v_lower1.de = tick[1]; + assign hw2reg.timer_v_upper0.d = mtime_d[0][63:32]; assign hw2reg.timer_v_lower0.d = mtime_d[0][31: 0]; + + assign hw2reg.timer_v_upper1.d = mtime_d[1][63:32]; + assign hw2reg.timer_v_lower1.d = mtime_d[1][31: 0]; + assign mtime[0] = {reg2hw.timer_v_upper0.q, reg2hw.timer_v_lower0.q}; - assign mtimecmp = '{'{{reg2hw.compare_upper0_0.q,reg2hw.compare_lower0_0.q}}}; + assign mtime[1] = {reg2hw.timer_v_upper1.q, reg2hw.timer_v_lower1.q}; + + assign mtimecmp[0][0] = {reg2hw.compare_upper0_0.q,reg2hw.compare_lower0_0.q}; + assign mtimecmp[1][0] = {reg2hw.compare_upper1_0.q,reg2hw.compare_lower1_0.q}; + assign mtimecmp_update[0][0] = reg2hw.compare_upper0_0.qe | reg2hw.compare_lower0_0.qe; + assign mtimecmp_update[1][0] = reg2hw.compare_upper0_0.qe | reg2hw.compare_lower0_0.qe; assign intr_timer_expired_0_0_o = intr_out[0]; - assign intr_timer_en = reg2hw.intr_enable0[0].q; - assign intr_timer_state_q = reg2hw.intr_state0[0].q; - assign intr_timer_test_q = reg2hw.intr_test0[0].q; - assign intr_timer_test_qe = reg2hw.intr_test0[0].qe; - assign hw2reg.intr_state0[0].de = intr_timer_state_de | mtimecmp_update[0][0]; - assign hw2reg.intr_state0[0].d = intr_timer_state_d & ~mtimecmp_update[0][0]; - + assign intr_timer_en[0] = reg2hw.intr_enable0[0].q; + assign intr_timer_state_q[0] = reg2hw.intr_state0[0].q; + assign intr_timer_test_q[0] = reg2hw.intr_test0[0].q; + assign intr_timer_test_qe[0] = reg2hw.intr_test0[0].qe; + assign intr_timer_expired_1_0_o = intr_out[1]; + assign intr_timer_en[1] = reg2hw.intr_enable1[0].q; + assign intr_timer_state_q[1] = reg2hw.intr_state1[0].q; + assign intr_timer_test_q[1] = reg2hw.intr_test1[0].q; + assign intr_timer_test_qe[1] = reg2hw.intr_test1[0].qe; + + assign hw2reg.intr_state0[0].de = intr_timer_state_de[0] | mtimecmp_update[0][0]; + assign hw2reg.intr_state0[0].d = intr_timer_state_d[0] & ~mtimecmp_update[0][0]; + assign hw2reg.intr_state1[0].de = intr_timer_state_de[1] | mtimecmp_update[1][0]; + assign hw2reg.intr_state1[0].d = intr_timer_state_d[1] & ~mtimecmp_update[1][0]; for (genvar h = 0 ; h < N_HARTS ; h++) begin : gen_harts prim_intr_hw #( @@ -79,14 +102,14 @@ module rv_timer ( ) u_intr_hw ( .clk_i, .rst_ni, - .event_intr_i (intr_timer_set), + .event_intr_i (intr_timer_set[h]), - .reg2hw_intr_enable_q_i (intr_timer_en[h*N_TIMERS+:N_TIMERS]), - .reg2hw_intr_test_q_i (intr_timer_test_q[h*N_TIMERS+:N_TIMERS]), - .reg2hw_intr_test_qe_i (intr_timer_test_qe[h]), - .reg2hw_intr_state_q_i (intr_timer_state_q[h*N_TIMERS+:N_TIMERS]), - .hw2reg_intr_state_de_o (intr_timer_state_de), - .hw2reg_intr_state_d_o (intr_timer_state_d[h*N_TIMERS+:N_TIMERS]), + .reg2hw_intr_enable_q_i(intr_timer_en[h*N_TIMERS+:N_TIMERS]), + .reg2hw_intr_test_q_i(intr_timer_test_q[h*N_TIMERS+:N_TIMERS]), + .reg2hw_intr_test_qe_i(intr_timer_test_qe[h]), + .reg2hw_intr_state_q_i(intr_timer_state_q[h*N_TIMERS+:N_TIMERS]), + .hw2reg_intr_state_de_o(intr_timer_state_de[h]), + .hw2reg_intr_state_d_o(intr_timer_state_d[h*N_TIMERS+:N_TIMERS]), .intr_o (intr_out[h*N_TIMERS+:N_TIMERS]) ); @@ -96,18 +119,14 @@ module rv_timer ( ) u_core ( .clk_i, .rst_ni, - - .active (active[h]), - .prescaler (prescaler[h]), - .step (step[h]), - - .tick (tick[h]), - - .mtime_d (mtime_d[h]), - .mtime (mtime[h]), - .mtimecmp (mtimecmp[h]), - - .intr (intr_timer_set[h*N_TIMERS+:N_TIMERS]) + .active(active[h]), + .prescaler(prescaler[h]), + .step(step[h]), + .tick(tick[h]), + .mtime_d(mtime_d[h]), + .mtime(mtime[h]), + .mtimecmp(mtimecmp[h]), + .intr(intr_timer_set[h*N_TIMERS+:N_TIMERS]) ); end : gen_harts @@ -115,15 +134,12 @@ module rv_timer ( rv_timer_reg_top u_reg ( .clk_i, .rst_ni, - .tl_i, .tl_o, - .reg2hw, .hw2reg, - - .intg_err_o (), - .devmode_i (1'b1) + .intg_err_o(), + .devmode_i(1'b1) ); //////////////// diff --git a/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv b/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv index 2b04665b2..5723d2818 100644 --- a/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv +++ b/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv @@ -7,11 +7,11 @@ package rv_timer_reg_pkg; // Param list - parameter int N_HARTS = 1; + parameter int N_HARTS = 2; parameter int N_TIMERS = 1; // Address widths within the block - parameter int BlockAw = 9; + parameter int BlockAw = 10; //////////////////////////// // Typedefs for registers // @@ -61,6 +61,46 @@ package rv_timer_reg_pkg; logic qe; } rv_timer_reg2hw_intr_test0_mreg_t; + typedef struct packed { + struct packed { + logic [11:0] q; + } prescale; + struct packed { + logic [7:0] q; + } step; + } rv_timer_reg2hw_cfg1_reg_t; + + typedef struct packed { + logic [31:0] q; + } rv_timer_reg2hw_timer_v_lower1_reg_t; + + typedef struct packed { + logic [31:0] q; + } rv_timer_reg2hw_timer_v_upper1_reg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } rv_timer_reg2hw_compare_lower1_0_reg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } rv_timer_reg2hw_compare_upper1_0_reg_t; + + typedef struct packed { + logic q; + } rv_timer_reg2hw_intr_enable1_mreg_t; + + typedef struct packed { + logic q; + } rv_timer_reg2hw_intr_state1_mreg_t; + + typedef struct packed { + logic q; + logic qe; + } rv_timer_reg2hw_intr_test1_mreg_t; + typedef struct packed { logic [31:0] d; logic de; @@ -76,39 +116,74 @@ package rv_timer_reg_pkg; logic de; } rv_timer_hw2reg_intr_state0_mreg_t; + typedef struct packed { + logic [31:0] d; + logic de; + } rv_timer_hw2reg_timer_v_lower1_reg_t; + + typedef struct packed { + logic [31:0] d; + logic de; + } rv_timer_hw2reg_timer_v_upper1_reg_t; + + typedef struct packed { + logic d; + logic de; + } rv_timer_hw2reg_intr_state1_mreg_t; + // Register -> HW type typedef struct packed { - rv_timer_reg2hw_ctrl_mreg_t [0:0] ctrl; // [154:154] - rv_timer_reg2hw_cfg0_reg_t cfg0; // [153:134] - rv_timer_reg2hw_timer_v_lower0_reg_t timer_v_lower0; // [133:102] - rv_timer_reg2hw_timer_v_upper0_reg_t timer_v_upper0; // [101:70] - rv_timer_reg2hw_compare_lower0_0_reg_t compare_lower0_0; // [69:37] - rv_timer_reg2hw_compare_upper0_0_reg_t compare_upper0_0; // [36:4] - rv_timer_reg2hw_intr_enable0_mreg_t [0:0] intr_enable0; // [3:3] - rv_timer_reg2hw_intr_state0_mreg_t [0:0] intr_state0; // [2:2] - rv_timer_reg2hw_intr_test0_mreg_t [0:0] intr_test0; // [1:0] + rv_timer_reg2hw_ctrl_mreg_t [1:0] ctrl; // [309:308] + rv_timer_reg2hw_cfg0_reg_t cfg0; // [307:288] + rv_timer_reg2hw_timer_v_lower0_reg_t timer_v_lower0; // [287:256] + rv_timer_reg2hw_timer_v_upper0_reg_t timer_v_upper0; // [255:224] + rv_timer_reg2hw_compare_lower0_0_reg_t compare_lower0_0; // [223:191] + rv_timer_reg2hw_compare_upper0_0_reg_t compare_upper0_0; // [190:158] + rv_timer_reg2hw_intr_enable0_mreg_t [0:0] intr_enable0; // [157:157] + rv_timer_reg2hw_intr_state0_mreg_t [0:0] intr_state0; // [156:156] + rv_timer_reg2hw_intr_test0_mreg_t [0:0] intr_test0; // [155:154] + rv_timer_reg2hw_cfg1_reg_t cfg1; // [153:134] + rv_timer_reg2hw_timer_v_lower1_reg_t timer_v_lower1; // [133:102] + rv_timer_reg2hw_timer_v_upper1_reg_t timer_v_upper1; // [101:70] + rv_timer_reg2hw_compare_lower1_0_reg_t compare_lower1_0; // [69:37] + rv_timer_reg2hw_compare_upper1_0_reg_t compare_upper1_0; // [36:4] + rv_timer_reg2hw_intr_enable1_mreg_t [0:0] intr_enable1; // [3:3] + rv_timer_reg2hw_intr_state1_mreg_t [0:0] intr_state1; // [2:2] + rv_timer_reg2hw_intr_test1_mreg_t [0:0] intr_test1; // [1:0] } rv_timer_reg2hw_t; // HW -> register type typedef struct packed { - rv_timer_hw2reg_timer_v_lower0_reg_t timer_v_lower0; // [67:35] - rv_timer_hw2reg_timer_v_upper0_reg_t timer_v_upper0; // [34:2] - rv_timer_hw2reg_intr_state0_mreg_t [0:0] intr_state0; // [1:0] + rv_timer_hw2reg_timer_v_lower0_reg_t timer_v_lower0; // [135:103] + rv_timer_hw2reg_timer_v_upper0_reg_t timer_v_upper0; // [102:70] + rv_timer_hw2reg_intr_state0_mreg_t [0:0] intr_state0; // [69:68] + rv_timer_hw2reg_timer_v_lower1_reg_t timer_v_lower1; // [67:35] + rv_timer_hw2reg_timer_v_upper1_reg_t timer_v_upper1; // [34:2] + rv_timer_hw2reg_intr_state1_mreg_t [0:0] intr_state1; // [1:0] } rv_timer_hw2reg_t; // Register offsets - parameter logic [BlockAw-1:0] RV_TIMER_CTRL_OFFSET = 9'h 0; - parameter logic [BlockAw-1:0] RV_TIMER_CFG0_OFFSET = 9'h 100; - parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_LOWER0_OFFSET = 9'h 104; - parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_UPPER0_OFFSET = 9'h 108; - parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_LOWER0_0_OFFSET = 9'h 10c; - parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_UPPER0_0_OFFSET = 9'h 110; - parameter logic [BlockAw-1:0] RV_TIMER_INTR_ENABLE0_OFFSET = 9'h 114; - parameter logic [BlockAw-1:0] RV_TIMER_INTR_STATE0_OFFSET = 9'h 118; - parameter logic [BlockAw-1:0] RV_TIMER_INTR_TEST0_OFFSET = 9'h 11c; + parameter logic [BlockAw-1:0] RV_TIMER_CTRL_OFFSET = 10'h 0; + parameter logic [BlockAw-1:0] RV_TIMER_CFG0_OFFSET = 10'h 100; + parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_LOWER0_OFFSET = 10'h 104; + parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_UPPER0_OFFSET = 10'h 108; + parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_LOWER0_0_OFFSET = 10'h 10c; + parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_UPPER0_0_OFFSET = 10'h 110; + parameter logic [BlockAw-1:0] RV_TIMER_INTR_ENABLE0_OFFSET = 10'h 114; + parameter logic [BlockAw-1:0] RV_TIMER_INTR_STATE0_OFFSET = 10'h 118; + parameter logic [BlockAw-1:0] RV_TIMER_INTR_TEST0_OFFSET = 10'h 11c; + parameter logic [BlockAw-1:0] RV_TIMER_CFG1_OFFSET = 10'h 200; + parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_LOWER1_OFFSET = 10'h 204; + parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_UPPER1_OFFSET = 10'h 208; + parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_LOWER1_0_OFFSET = 10'h 20c; + parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_UPPER1_0_OFFSET = 10'h 210; + parameter logic [BlockAw-1:0] RV_TIMER_INTR_ENABLE1_OFFSET = 10'h 214; + parameter logic [BlockAw-1:0] RV_TIMER_INTR_STATE1_OFFSET = 10'h 218; + parameter logic [BlockAw-1:0] RV_TIMER_INTR_TEST1_OFFSET = 10'h 21c; // Reset values for hwext registers and their fields parameter logic [0:0] RV_TIMER_INTR_TEST0_RESVAL = 1'h 0; + parameter logic [0:0] RV_TIMER_INTR_TEST1_RESVAL = 1'h 0; // Register index typedef enum int { @@ -120,20 +195,36 @@ package rv_timer_reg_pkg; RV_TIMER_COMPARE_UPPER0_0, RV_TIMER_INTR_ENABLE0, RV_TIMER_INTR_STATE0, - RV_TIMER_INTR_TEST0 + RV_TIMER_INTR_TEST0, + RV_TIMER_CFG1, + RV_TIMER_TIMER_V_LOWER1, + RV_TIMER_TIMER_V_UPPER1, + RV_TIMER_COMPARE_LOWER1_0, + RV_TIMER_COMPARE_UPPER1_0, + RV_TIMER_INTR_ENABLE1, + RV_TIMER_INTR_STATE1, + RV_TIMER_INTR_TEST1 } rv_timer_id_e; // Register width information to check illegal writes - parameter logic [3:0] RV_TIMER_PERMIT [9] = '{ - 4'b 0001, // index[0] RV_TIMER_CTRL - 4'b 0111, // index[1] RV_TIMER_CFG0 - 4'b 1111, // index[2] RV_TIMER_TIMER_V_LOWER0 - 4'b 1111, // index[3] RV_TIMER_TIMER_V_UPPER0 - 4'b 1111, // index[4] RV_TIMER_COMPARE_LOWER0_0 - 4'b 1111, // index[5] RV_TIMER_COMPARE_UPPER0_0 - 4'b 0001, // index[6] RV_TIMER_INTR_ENABLE0 - 4'b 0001, // index[7] RV_TIMER_INTR_STATE0 - 4'b 0001 // index[8] RV_TIMER_INTR_TEST0 + parameter logic [3:0] RV_TIMER_PERMIT [17] = '{ + 4'b 0001, // index[ 0] RV_TIMER_CTRL + 4'b 0111, // index[ 1] RV_TIMER_CFG0 + 4'b 1111, // index[ 2] RV_TIMER_TIMER_V_LOWER0 + 4'b 1111, // index[ 3] RV_TIMER_TIMER_V_UPPER0 + 4'b 1111, // index[ 4] RV_TIMER_COMPARE_LOWER0_0 + 4'b 1111, // index[ 5] RV_TIMER_COMPARE_UPPER0_0 + 4'b 0001, // index[ 6] RV_TIMER_INTR_ENABLE0 + 4'b 0001, // index[ 7] RV_TIMER_INTR_STATE0 + 4'b 0001, // index[ 8] RV_TIMER_INTR_TEST0 + 4'b 0111, // index[ 9] RV_TIMER_CFG1 + 4'b 1111, // index[10] RV_TIMER_TIMER_V_LOWER1 + 4'b 1111, // index[11] RV_TIMER_TIMER_V_UPPER1 + 4'b 1111, // index[12] RV_TIMER_COMPARE_LOWER1_0 + 4'b 1111, // index[13] RV_TIMER_COMPARE_UPPER1_0 + 4'b 0001, // index[14] RV_TIMER_INTR_ENABLE1 + 4'b 0001, // index[15] RV_TIMER_INTR_STATE1 + 4'b 0001 // index[16] RV_TIMER_INTR_TEST1 }; endpackage diff --git a/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer_reg_top.sv b/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer_reg_top.sv index 9521e9089..413282d82 100644 --- a/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer_reg_top.sv +++ b/hw/vendor/lowrisc_opentitan/hw/ip/rv_timer/rtl/rv_timer_reg_top.sv @@ -25,7 +25,7 @@ module rv_timer_reg_top ( import rv_timer_reg_pkg::* ; - localparam int AW = 9; + localparam int AW = 10; localparam int DW = 32; localparam int DBW = DW/8; // Byte Width @@ -76,9 +76,12 @@ module rv_timer_reg_top ( // Define SW related signals // Format: __{wd|we|qs} // or _{wd|we|qs} if field == 1 or 0 - logic ctrl_qs; - logic ctrl_wd; - logic ctrl_we; + logic ctrl_active_0_qs; + logic ctrl_active_0_wd; + logic ctrl_active_0_we; + logic ctrl_active_1_qs; + logic ctrl_active_1_wd; + logic ctrl_active_1_we; logic [11:0] cfg0_prescale_qs; logic [11:0] cfg0_prescale_wd; logic cfg0_prescale_we; @@ -105,23 +108,50 @@ module rv_timer_reg_top ( logic intr_state0_we; logic intr_test0_wd; logic intr_test0_we; + logic [11:0] cfg1_prescale_qs; + logic [11:0] cfg1_prescale_wd; + logic cfg1_prescale_we; + logic [7:0] cfg1_step_qs; + logic [7:0] cfg1_step_wd; + logic cfg1_step_we; + logic [31:0] timer_v_lower1_qs; + logic [31:0] timer_v_lower1_wd; + logic timer_v_lower1_we; + logic [31:0] timer_v_upper1_qs; + logic [31:0] timer_v_upper1_wd; + logic timer_v_upper1_we; + logic [31:0] compare_lower1_0_qs; + logic [31:0] compare_lower1_0_wd; + logic compare_lower1_0_we; + logic [31:0] compare_upper1_0_qs; + logic [31:0] compare_upper1_0_wd; + logic compare_upper1_0_we; + logic intr_enable1_qs; + logic intr_enable1_wd; + logic intr_enable1_we; + logic intr_state1_qs; + logic intr_state1_wd; + logic intr_state1_we; + logic intr_test1_wd; + logic intr_test1_we; // Register instances // Subregister 0 of Multireg ctrl // R[ctrl]: V(False) + // F[active_0]: 0:0 prim_subreg #( .DW (1), .SWACCESS("RW"), .RESVAL (1'h0) - ) u_ctrl ( + ) u_ctrl_active_0 ( .clk_i (clk_i ), .rst_ni (rst_ni ), // from register interface - .we (ctrl_we), - .wd (ctrl_wd), + .we (ctrl_active_0_we), + .wd (ctrl_active_0_wd), // from internal hardware .de (1'b0), @@ -132,10 +162,37 @@ module rv_timer_reg_top ( .q (reg2hw.ctrl[0].q ), // to register interface (read) - .qs (ctrl_qs) + .qs (ctrl_active_0_qs) ); + // F[active_1]: 1:1 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_ctrl_active_1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (ctrl_active_1_we), + .wd (ctrl_active_1_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.ctrl[1].q ), + + // to register interface (read) + .qs (ctrl_active_1_qs) + ); + + + // R[cfg0]: V(False) // F[prescale]: 11:0 @@ -374,20 +431,266 @@ module rv_timer_reg_top ( ); + // R[cfg1]: V(False) + + // F[prescale]: 11:0 + prim_subreg #( + .DW (12), + .SWACCESS("RW"), + .RESVAL (12'h0) + ) u_cfg1_prescale ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (cfg1_prescale_we), + .wd (cfg1_prescale_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.cfg1.prescale.q ), + + // to register interface (read) + .qs (cfg1_prescale_qs) + ); + + + // F[step]: 23:16 + prim_subreg #( + .DW (8), + .SWACCESS("RW"), + .RESVAL (8'h1) + ) u_cfg1_step ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (cfg1_step_we), + .wd (cfg1_step_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.cfg1.step.q ), + + // to register interface (read) + .qs (cfg1_step_qs) + ); + + + // R[timer_v_lower1]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_timer_v_lower1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (timer_v_lower1_we), + .wd (timer_v_lower1_wd), + + // from internal hardware + .de (hw2reg.timer_v_lower1.de), + .d (hw2reg.timer_v_lower1.d ), + + // to internal hardware + .qe (), + .q (reg2hw.timer_v_lower1.q ), + + // to register interface (read) + .qs (timer_v_lower1_qs) + ); + + + // R[timer_v_upper1]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_timer_v_upper1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (timer_v_upper1_we), + .wd (timer_v_upper1_wd), + + // from internal hardware + .de (hw2reg.timer_v_upper1.de), + .d (hw2reg.timer_v_upper1.d ), + + // to internal hardware + .qe (), + .q (reg2hw.timer_v_upper1.q ), + + // to register interface (read) + .qs (timer_v_upper1_qs) + ); + + + // R[compare_lower1_0]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'hffffffff) + ) u_compare_lower1_0 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (compare_lower1_0_we), + .wd (compare_lower1_0_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.compare_lower1_0.qe), + .q (reg2hw.compare_lower1_0.q ), + + // to register interface (read) + .qs (compare_lower1_0_qs) + ); + + + // R[compare_upper1_0]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'hffffffff) + ) u_compare_upper1_0 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (compare_upper1_0_we), + .wd (compare_upper1_0_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.compare_upper1_0.qe), + .q (reg2hw.compare_upper1_0.q ), + + // to register interface (read) + .qs (compare_upper1_0_qs) + ); + + + + // Subregister 0 of Multireg intr_enable1 + // R[intr_enable1]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_intr_enable1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (intr_enable1_we), + .wd (intr_enable1_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.intr_enable1[0].q ), + + // to register interface (read) + .qs (intr_enable1_qs) + ); + + + + // Subregister 0 of Multireg intr_state1 + // R[intr_state1]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("W1C"), + .RESVAL (1'h0) + ) u_intr_state1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (intr_state1_we), + .wd (intr_state1_wd), + + // from internal hardware + .de (hw2reg.intr_state1[0].de), + .d (hw2reg.intr_state1[0].d ), + + // to internal hardware + .qe (), + .q (reg2hw.intr_state1[0].q ), + + // to register interface (read) + .qs (intr_state1_qs) + ); + + + + // Subregister 0 of Multireg intr_test1 + // R[intr_test1]: V(True) + + prim_subreg_ext #( + .DW (1) + ) u_intr_test1 ( + .re (1'b0), + .we (intr_test1_we), + .wd (intr_test1_wd), + .d ('0), + .qre (), + .qe (reg2hw.intr_test1[0].qe), + .q (reg2hw.intr_test1[0].q ), + .qs () + ); + + - logic [8:0] addr_hit; + logic [16:0] addr_hit; always_comb begin addr_hit = '0; - addr_hit[0] = (reg_addr == RV_TIMER_CTRL_OFFSET); - addr_hit[1] = (reg_addr == RV_TIMER_CFG0_OFFSET); - addr_hit[2] = (reg_addr == RV_TIMER_TIMER_V_LOWER0_OFFSET); - addr_hit[3] = (reg_addr == RV_TIMER_TIMER_V_UPPER0_OFFSET); - addr_hit[4] = (reg_addr == RV_TIMER_COMPARE_LOWER0_0_OFFSET); - addr_hit[5] = (reg_addr == RV_TIMER_COMPARE_UPPER0_0_OFFSET); - addr_hit[6] = (reg_addr == RV_TIMER_INTR_ENABLE0_OFFSET); - addr_hit[7] = (reg_addr == RV_TIMER_INTR_STATE0_OFFSET); - addr_hit[8] = (reg_addr == RV_TIMER_INTR_TEST0_OFFSET); + addr_hit[ 0] = (reg_addr == RV_TIMER_CTRL_OFFSET); + addr_hit[ 1] = (reg_addr == RV_TIMER_CFG0_OFFSET); + addr_hit[ 2] = (reg_addr == RV_TIMER_TIMER_V_LOWER0_OFFSET); + addr_hit[ 3] = (reg_addr == RV_TIMER_TIMER_V_UPPER0_OFFSET); + addr_hit[ 4] = (reg_addr == RV_TIMER_COMPARE_LOWER0_0_OFFSET); + addr_hit[ 5] = (reg_addr == RV_TIMER_COMPARE_UPPER0_0_OFFSET); + addr_hit[ 6] = (reg_addr == RV_TIMER_INTR_ENABLE0_OFFSET); + addr_hit[ 7] = (reg_addr == RV_TIMER_INTR_STATE0_OFFSET); + addr_hit[ 8] = (reg_addr == RV_TIMER_INTR_TEST0_OFFSET); + addr_hit[ 9] = (reg_addr == RV_TIMER_CFG1_OFFSET); + addr_hit[10] = (reg_addr == RV_TIMER_TIMER_V_LOWER1_OFFSET); + addr_hit[11] = (reg_addr == RV_TIMER_TIMER_V_UPPER1_OFFSET); + addr_hit[12] = (reg_addr == RV_TIMER_COMPARE_LOWER1_0_OFFSET); + addr_hit[13] = (reg_addr == RV_TIMER_COMPARE_UPPER1_0_OFFSET); + addr_hit[14] = (reg_addr == RV_TIMER_INTR_ENABLE1_OFFSET); + addr_hit[15] = (reg_addr == RV_TIMER_INTR_STATE1_OFFSET); + addr_hit[16] = (reg_addr == RV_TIMER_INTR_TEST1_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -395,19 +698,30 @@ module rv_timer_reg_top ( // Check sub-word write is permitted always_comb begin wr_err = (reg_we & - ((addr_hit[0] & (|(RV_TIMER_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(RV_TIMER_PERMIT[1] & ~reg_be))) | - (addr_hit[2] & (|(RV_TIMER_PERMIT[2] & ~reg_be))) | - (addr_hit[3] & (|(RV_TIMER_PERMIT[3] & ~reg_be))) | - (addr_hit[4] & (|(RV_TIMER_PERMIT[4] & ~reg_be))) | - (addr_hit[5] & (|(RV_TIMER_PERMIT[5] & ~reg_be))) | - (addr_hit[6] & (|(RV_TIMER_PERMIT[6] & ~reg_be))) | - (addr_hit[7] & (|(RV_TIMER_PERMIT[7] & ~reg_be))) | - (addr_hit[8] & (|(RV_TIMER_PERMIT[8] & ~reg_be))))); + ((addr_hit[ 0] & (|(RV_TIMER_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(RV_TIMER_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(RV_TIMER_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(RV_TIMER_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(RV_TIMER_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(RV_TIMER_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(RV_TIMER_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(RV_TIMER_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(RV_TIMER_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(RV_TIMER_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(RV_TIMER_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(RV_TIMER_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(RV_TIMER_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(RV_TIMER_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(RV_TIMER_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(RV_TIMER_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(RV_TIMER_PERMIT[16] & ~reg_be))))); end - assign ctrl_we = addr_hit[0] & reg_we & !reg_error; - assign ctrl_wd = reg_wdata[0]; + assign ctrl_active_0_we = addr_hit[0] & reg_we & !reg_error; + assign ctrl_active_0_wd = reg_wdata[0]; + + assign ctrl_active_1_we = addr_hit[0] & reg_we & !reg_error; + assign ctrl_active_1_wd = reg_wdata[1]; assign cfg0_prescale_we = addr_hit[1] & reg_we & !reg_error; assign cfg0_prescale_wd = reg_wdata[11:0]; @@ -436,12 +750,40 @@ module rv_timer_reg_top ( assign intr_test0_we = addr_hit[8] & reg_we & !reg_error; assign intr_test0_wd = reg_wdata[0]; + assign cfg1_prescale_we = addr_hit[9] & reg_we & !reg_error; + assign cfg1_prescale_wd = reg_wdata[11:0]; + + assign cfg1_step_we = addr_hit[9] & reg_we & !reg_error; + assign cfg1_step_wd = reg_wdata[23:16]; + + assign timer_v_lower1_we = addr_hit[10] & reg_we & !reg_error; + assign timer_v_lower1_wd = reg_wdata[31:0]; + + assign timer_v_upper1_we = addr_hit[11] & reg_we & !reg_error; + assign timer_v_upper1_wd = reg_wdata[31:0]; + + assign compare_lower1_0_we = addr_hit[12] & reg_we & !reg_error; + assign compare_lower1_0_wd = reg_wdata[31:0]; + + assign compare_upper1_0_we = addr_hit[13] & reg_we & !reg_error; + assign compare_upper1_0_wd = reg_wdata[31:0]; + + assign intr_enable1_we = addr_hit[14] & reg_we & !reg_error; + assign intr_enable1_wd = reg_wdata[0]; + + assign intr_state1_we = addr_hit[15] & reg_we & !reg_error; + assign intr_state1_wd = reg_wdata[0]; + + assign intr_test1_we = addr_hit[16] & reg_we & !reg_error; + assign intr_test1_wd = reg_wdata[0]; + // Read data return always_comb begin reg_rdata_next = '0; unique case (1'b1) addr_hit[0]: begin - reg_rdata_next[0] = ctrl_qs; + reg_rdata_next[0] = ctrl_active_0_qs; + reg_rdata_next[1] = ctrl_active_1_qs; end addr_hit[1]: begin @@ -477,6 +819,39 @@ module rv_timer_reg_top ( reg_rdata_next[0] = '0; end + addr_hit[9]: begin + reg_rdata_next[11:0] = cfg1_prescale_qs; + reg_rdata_next[23:16] = cfg1_step_qs; + end + + addr_hit[10]: begin + reg_rdata_next[31:0] = timer_v_lower1_qs; + end + + addr_hit[11]: begin + reg_rdata_next[31:0] = timer_v_upper1_qs; + end + + addr_hit[12]: begin + reg_rdata_next[31:0] = compare_lower1_0_qs; + end + + addr_hit[13]: begin + reg_rdata_next[31:0] = compare_upper1_0_qs; + end + + addr_hit[14]: begin + reg_rdata_next[0] = intr_enable1_qs; + end + + addr_hit[15]: begin + reg_rdata_next[0] = intr_state1_qs; + end + + addr_hit[16]: begin + reg_rdata_next[0] = '0; + end + default: begin reg_rdata_next = '1; end diff --git a/hw/vendor/patches/lowrisc_opentitan/rv_timer.patch b/hw/vendor/patches/lowrisc_opentitan/rv_timer.patch index 657947a6b..41345f01b 100644 --- a/hw/vendor/patches/lowrisc_opentitan/rv_timer.patch +++ b/hw/vendor/patches/lowrisc_opentitan/rv_timer.patch @@ -1,7 +1,516 @@ +diff --git a/hw/ip/rv_timer/data/rv_timer.hjson b/hw/ip/rv_timer/data/rv_timer.hjson +index 8a41a6863..b00f10a57 100644 +--- a/hw/ip/rv_timer/data/rv_timer.hjson ++++ b/hw/ip/rv_timer/data/rv_timer.hjson +@@ -15,12 +15,15 @@ + { name: "timer_expired_0_0", + desc: "raised if the timer 0_0 expired (mtimecmp >= mtime)" + }, ++ { name: "timer_expired_1_0", ++ desc: "raised if the timer 1_0 expired (mtimecmp >= mtime)" ++ }, + ], + param_list: [ + { name: "N_HARTS", + desc: "Number of harts", + type: "int", +- default: "1" ++ default: "2" + }, + { name: "N_TIMERS", + desc: "Number of timers per Hart", +@@ -39,10 +42,7 @@ + swaccess: "rw", + hwaccess: "hro", + fields: [ +- { bits: "0", name: "active", +- desc: "If 1, timer operates", +- tags: [// prevent timer from being enabled +- "excl:CsrNonInitTests:CsrExclWrite"] } ++ { bits: "0", name: "active", desc: "If 1, timer operates" } + ], + } + }, +@@ -110,9 +110,7 @@ + swaccess: "rw1c", + hwaccess: "hrw", + fields: [ +- { bits: "0", name: "IS", desc: "Interrupt status for timer", +- tags: [// intr_state csr is affected by writes to other csrs - skip write-check +- "excl:CsrNonInitTests:CsrExclWriteCheck"] } ++ { bits: "0", name: "IS", desc: "Interrupt status for timer" } + ], + } + }, +@@ -126,9 +124,89 @@ + hwext: "true", + hwqe: "true", + fields: [ +- { bits: "0", name: "T", desc: "Interrupt test for timer", +- tags: [// intr_test csr is WO which - it reads back 0s +- "excl:CsrNonInitTests:CsrExclWrite"] } ++ { bits: "0", name: "T", desc: "Interrupt test for timer" } ++ ] ++ } ++ }, ++ { skipto: "0x200" }, ++ { name: "CFG1", ++ desc: "Configuration for Hart 1", ++ swaccess: "rw", ++ hwaccess: "hro", ++ fields: [ ++ { bits: "11:0", name: "prescale", desc: "Prescaler to generate tick" }, ++ { bits: "23:16", name: "step", resval: "0x1", desc: "Incremental value for each tick" }, ++ ], ++ }, ++ { name: "TIMER_V_LOWER1", ++ desc: "Timer value Lower", ++ swaccess: "rw", ++ hwaccess: "hrw", ++ fields: [ ++ { bits: "31:0", name: "v", desc: "Timer value [31:0]" }, ++ ], ++ }, ++ { name: "TIMER_V_UPPER1", ++ desc: "Timer value Upper", ++ swaccess: "rw", ++ hwaccess: "hrw", ++ fields: [ ++ { bits: "31:0", name: "v", desc: "Timer value [63:32]" }, ++ ], ++ }, ++ { name: "COMPARE_LOWER1_0", ++ desc: "Timer value Lower", ++ swaccess: "rw", ++ hwaccess: "hro", ++ hwqe: "true", ++ fields: [ ++ { bits: "31:0", name: "v", resval: "0xffffffff", desc: "Timer compare value [31:0]" }, ++ ], ++ }, ++ { name: "COMPARE_UPPER1_0", ++ desc: "Timer value Upper", ++ swaccess: "rw", ++ hwaccess: "hro", ++ hwqe: "true", ++ fields: [ ++ { bits: "31:0", name: "v", resval: "0xffffffff", desc: "Timer compare value [63:32]" }, ++ ], ++ }, ++ { multireg: { ++ name: "INTR_ENABLE1", ++ desc: "Interrupt Enable", ++ count: "N_TIMERS", ++ cname: "TIMER", ++ swaccess: "rw", ++ hwaccess: "hro", ++ fields: [ ++ { bits: "0", name: "IE", desc: "Interrupt Enable for timer" } ++ ] ++ } ++ }, ++ { multireg: { ++ name: "INTR_STATE1", ++ desc: "Interrupt Status", ++ count: "N_TIMERS", ++ cname: "TIMER", ++ swaccess: "rw1c", ++ hwaccess: "hrw", ++ fields: [ ++ { bits: "0", name: "IS", desc: "Interrupt status for timer" } ++ ], ++ } ++ }, ++ { multireg: { ++ name: "INTR_TEST1", ++ desc: "Interrupt test register", ++ count: "N_TIMERS", ++ cname: "TIMER", ++ swaccess: "wo", ++ hwaccess: "hro", ++ hwext: "true", ++ hwqe: "true", ++ fields: [ ++ { bits: "0", name: "T", desc: "Interrupt test for timer" } + ] + } + }, +diff --git a/hw/ip/rv_timer/rtl/rv_timer.sv b/hw/ip/rv_timer/rtl/rv_timer.sv +index 0ce0bf3f5..9aba20330 100644 +--- a/hw/ip/rv_timer/rtl/rv_timer.sv ++++ b/hw/ip/rv_timer/rtl/rv_timer.sv +@@ -1,8 +1,6 @@ + // Copyright lowRISC contributors. + // Licensed under the Apache License, Version 2.0, see LICENSE for details. + // SPDX-License-Identifier: Apache-2.0 +-// +- + + `include "prim_assert.sv" + +@@ -13,10 +11,11 @@ module rv_timer ( + input tlul_pkg::tl_h2d_t tl_i, + output tlul_pkg::tl_d2h_t tl_o, + +- output logic intr_timer_expired_0_0_o ++ output logic intr_timer_expired_0_0_o, ++ output logic intr_timer_expired_1_0_o + ); + +- localparam int N_HARTS = 1; ++ localparam int N_HARTS = 2; + localparam int N_TIMERS = 1; + + import rv_timer_reg_pkg::*; +@@ -53,25 +52,49 @@ module rv_timer ( + // Once reggen supports nested multireg, the following can be automated. For the moment, it must + // be connected manually. + assign active[0] = reg2hw.ctrl[0].q; +- assign prescaler = '{reg2hw.cfg0.prescale.q}; +- assign step = '{reg2hw.cfg0.step.q}; ++ assign active[1] = reg2hw.ctrl[1].q; ++ ++ assign prescaler[0] = reg2hw.cfg0.prescale.q; ++ assign prescaler[1] = reg2hw.cfg1.prescale.q; ++ ++ assign step[0] = reg2hw.cfg0.step.q; ++ assign step[1] = reg2hw.cfg1.step.q; + + assign hw2reg.timer_v_upper0.de = tick[0]; + assign hw2reg.timer_v_lower0.de = tick[0]; ++ assign hw2reg.timer_v_upper1.de = tick[1]; ++ assign hw2reg.timer_v_lower1.de = tick[1]; ++ + assign hw2reg.timer_v_upper0.d = mtime_d[0][63:32]; + assign hw2reg.timer_v_lower0.d = mtime_d[0][31: 0]; ++ ++ assign hw2reg.timer_v_upper1.d = mtime_d[1][63:32]; ++ assign hw2reg.timer_v_lower1.d = mtime_d[1][31: 0]; ++ + assign mtime[0] = {reg2hw.timer_v_upper0.q, reg2hw.timer_v_lower0.q}; +- assign mtimecmp = '{'{{reg2hw.compare_upper0_0.q,reg2hw.compare_lower0_0.q}}}; ++ assign mtime[1] = {reg2hw.timer_v_upper1.q, reg2hw.timer_v_lower1.q}; ++ ++ assign mtimecmp[0][0] = {reg2hw.compare_upper0_0.q,reg2hw.compare_lower0_0.q}; ++ assign mtimecmp[1][0] = {reg2hw.compare_upper1_0.q,reg2hw.compare_lower1_0.q}; ++ + assign mtimecmp_update[0][0] = reg2hw.compare_upper0_0.qe | reg2hw.compare_lower0_0.qe; ++ assign mtimecmp_update[1][0] = reg2hw.compare_upper0_0.qe | reg2hw.compare_lower0_0.qe; + + assign intr_timer_expired_0_0_o = intr_out[0]; +- assign intr_timer_en = reg2hw.intr_enable0[0].q; +- assign intr_timer_state_q = reg2hw.intr_state0[0].q; +- assign intr_timer_test_q = reg2hw.intr_test0[0].q; +- assign intr_timer_test_qe = reg2hw.intr_test0[0].qe; +- assign hw2reg.intr_state0[0].de = intr_timer_state_de | mtimecmp_update[0][0]; +- assign hw2reg.intr_state0[0].d = intr_timer_state_d & ~mtimecmp_update[0][0]; +- ++ assign intr_timer_en[0] = reg2hw.intr_enable0[0].q; ++ assign intr_timer_state_q[0] = reg2hw.intr_state0[0].q; ++ assign intr_timer_test_q[0] = reg2hw.intr_test0[0].q; ++ assign intr_timer_test_qe[0] = reg2hw.intr_test0[0].qe; ++ assign intr_timer_expired_1_0_o = intr_out[1]; ++ assign intr_timer_en[1] = reg2hw.intr_enable1[0].q; ++ assign intr_timer_state_q[1] = reg2hw.intr_state1[0].q; ++ assign intr_timer_test_q[1] = reg2hw.intr_test1[0].q; ++ assign intr_timer_test_qe[1] = reg2hw.intr_test1[0].qe; ++ ++ assign hw2reg.intr_state0[0].de = intr_timer_state_de[0] | mtimecmp_update[0][0]; ++ assign hw2reg.intr_state0[0].d = intr_timer_state_d[0] & ~mtimecmp_update[0][0]; ++ assign hw2reg.intr_state1[0].de = intr_timer_state_de[1] | mtimecmp_update[1][0]; ++ assign hw2reg.intr_state1[0].d = intr_timer_state_d[1] & ~mtimecmp_update[1][0]; + + for (genvar h = 0 ; h < N_HARTS ; h++) begin : gen_harts + prim_intr_hw #( +@@ -79,14 +102,14 @@ module rv_timer ( + ) u_intr_hw ( + .clk_i, + .rst_ni, +- .event_intr_i (intr_timer_set), ++ .event_intr_i (intr_timer_set[h]), + +- .reg2hw_intr_enable_q_i (intr_timer_en[h*N_TIMERS+:N_TIMERS]), +- .reg2hw_intr_test_q_i (intr_timer_test_q[h*N_TIMERS+:N_TIMERS]), +- .reg2hw_intr_test_qe_i (intr_timer_test_qe[h]), +- .reg2hw_intr_state_q_i (intr_timer_state_q[h*N_TIMERS+:N_TIMERS]), +- .hw2reg_intr_state_de_o (intr_timer_state_de), +- .hw2reg_intr_state_d_o (intr_timer_state_d[h*N_TIMERS+:N_TIMERS]), ++ .reg2hw_intr_enable_q_i(intr_timer_en[h*N_TIMERS+:N_TIMERS]), ++ .reg2hw_intr_test_q_i(intr_timer_test_q[h*N_TIMERS+:N_TIMERS]), ++ .reg2hw_intr_test_qe_i(intr_timer_test_qe[h]), ++ .reg2hw_intr_state_q_i(intr_timer_state_q[h*N_TIMERS+:N_TIMERS]), ++ .hw2reg_intr_state_de_o(intr_timer_state_de[h]), ++ .hw2reg_intr_state_d_o(intr_timer_state_d[h*N_TIMERS+:N_TIMERS]), + + .intr_o (intr_out[h*N_TIMERS+:N_TIMERS]) + ); +@@ -96,18 +119,14 @@ module rv_timer ( + ) u_core ( + .clk_i, + .rst_ni, +- +- .active (active[h]), +- .prescaler (prescaler[h]), +- .step (step[h]), +- +- .tick (tick[h]), +- +- .mtime_d (mtime_d[h]), +- .mtime (mtime[h]), +- .mtimecmp (mtimecmp[h]), +- +- .intr (intr_timer_set[h*N_TIMERS+:N_TIMERS]) ++ .active(active[h]), ++ .prescaler(prescaler[h]), ++ .step(step[h]), ++ .tick(tick[h]), ++ .mtime_d(mtime_d[h]), ++ .mtime(mtime[h]), ++ .mtimecmp(mtimecmp[h]), ++ .intr(intr_timer_set[h*N_TIMERS+:N_TIMERS]) + ); + end : gen_harts + +@@ -115,15 +134,12 @@ module rv_timer ( + rv_timer_reg_top u_reg ( + .clk_i, + .rst_ni, +- + .tl_i, + .tl_o, +- + .reg2hw, + .hw2reg, +- +- .intg_err_o (), +- .devmode_i (1'b1) ++ .intg_err_o(), ++ .devmode_i(1'b1) + ); + + //////////////// +diff --git a/hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv b/hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv +index 2b04665b2..5723d2818 100644 +--- a/hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv ++++ b/hw/ip/rv_timer/rtl/rv_timer_reg_pkg.sv +@@ -7,11 +7,11 @@ + package rv_timer_reg_pkg; + + // Param list +- parameter int N_HARTS = 1; ++ parameter int N_HARTS = 2; + parameter int N_TIMERS = 1; + + // Address widths within the block +- parameter int BlockAw = 9; ++ parameter int BlockAw = 10; + + //////////////////////////// + // Typedefs for registers // +@@ -61,6 +61,46 @@ package rv_timer_reg_pkg; + logic qe; + } rv_timer_reg2hw_intr_test0_mreg_t; + ++ typedef struct packed { ++ struct packed { ++ logic [11:0] q; ++ } prescale; ++ struct packed { ++ logic [7:0] q; ++ } step; ++ } rv_timer_reg2hw_cfg1_reg_t; ++ ++ typedef struct packed { ++ logic [31:0] q; ++ } rv_timer_reg2hw_timer_v_lower1_reg_t; ++ ++ typedef struct packed { ++ logic [31:0] q; ++ } rv_timer_reg2hw_timer_v_upper1_reg_t; ++ ++ typedef struct packed { ++ logic [31:0] q; ++ logic qe; ++ } rv_timer_reg2hw_compare_lower1_0_reg_t; ++ ++ typedef struct packed { ++ logic [31:0] q; ++ logic qe; ++ } rv_timer_reg2hw_compare_upper1_0_reg_t; ++ ++ typedef struct packed { ++ logic q; ++ } rv_timer_reg2hw_intr_enable1_mreg_t; ++ ++ typedef struct packed { ++ logic q; ++ } rv_timer_reg2hw_intr_state1_mreg_t; ++ ++ typedef struct packed { ++ logic q; ++ logic qe; ++ } rv_timer_reg2hw_intr_test1_mreg_t; ++ + typedef struct packed { + logic [31:0] d; + logic de; +@@ -76,39 +116,74 @@ package rv_timer_reg_pkg; + logic de; + } rv_timer_hw2reg_intr_state0_mreg_t; + ++ typedef struct packed { ++ logic [31:0] d; ++ logic de; ++ } rv_timer_hw2reg_timer_v_lower1_reg_t; ++ ++ typedef struct packed { ++ logic [31:0] d; ++ logic de; ++ } rv_timer_hw2reg_timer_v_upper1_reg_t; ++ ++ typedef struct packed { ++ logic d; ++ logic de; ++ } rv_timer_hw2reg_intr_state1_mreg_t; ++ + // Register -> HW type + typedef struct packed { +- rv_timer_reg2hw_ctrl_mreg_t [0:0] ctrl; // [154:154] +- rv_timer_reg2hw_cfg0_reg_t cfg0; // [153:134] +- rv_timer_reg2hw_timer_v_lower0_reg_t timer_v_lower0; // [133:102] +- rv_timer_reg2hw_timer_v_upper0_reg_t timer_v_upper0; // [101:70] +- rv_timer_reg2hw_compare_lower0_0_reg_t compare_lower0_0; // [69:37] +- rv_timer_reg2hw_compare_upper0_0_reg_t compare_upper0_0; // [36:4] +- rv_timer_reg2hw_intr_enable0_mreg_t [0:0] intr_enable0; // [3:3] +- rv_timer_reg2hw_intr_state0_mreg_t [0:0] intr_state0; // [2:2] +- rv_timer_reg2hw_intr_test0_mreg_t [0:0] intr_test0; // [1:0] ++ rv_timer_reg2hw_ctrl_mreg_t [1:0] ctrl; // [309:308] ++ rv_timer_reg2hw_cfg0_reg_t cfg0; // [307:288] ++ rv_timer_reg2hw_timer_v_lower0_reg_t timer_v_lower0; // [287:256] ++ rv_timer_reg2hw_timer_v_upper0_reg_t timer_v_upper0; // [255:224] ++ rv_timer_reg2hw_compare_lower0_0_reg_t compare_lower0_0; // [223:191] ++ rv_timer_reg2hw_compare_upper0_0_reg_t compare_upper0_0; // [190:158] ++ rv_timer_reg2hw_intr_enable0_mreg_t [0:0] intr_enable0; // [157:157] ++ rv_timer_reg2hw_intr_state0_mreg_t [0:0] intr_state0; // [156:156] ++ rv_timer_reg2hw_intr_test0_mreg_t [0:0] intr_test0; // [155:154] ++ rv_timer_reg2hw_cfg1_reg_t cfg1; // [153:134] ++ rv_timer_reg2hw_timer_v_lower1_reg_t timer_v_lower1; // [133:102] ++ rv_timer_reg2hw_timer_v_upper1_reg_t timer_v_upper1; // [101:70] ++ rv_timer_reg2hw_compare_lower1_0_reg_t compare_lower1_0; // [69:37] ++ rv_timer_reg2hw_compare_upper1_0_reg_t compare_upper1_0; // [36:4] ++ rv_timer_reg2hw_intr_enable1_mreg_t [0:0] intr_enable1; // [3:3] ++ rv_timer_reg2hw_intr_state1_mreg_t [0:0] intr_state1; // [2:2] ++ rv_timer_reg2hw_intr_test1_mreg_t [0:0] intr_test1; // [1:0] + } rv_timer_reg2hw_t; + + // HW -> register type + typedef struct packed { +- rv_timer_hw2reg_timer_v_lower0_reg_t timer_v_lower0; // [67:35] +- rv_timer_hw2reg_timer_v_upper0_reg_t timer_v_upper0; // [34:2] +- rv_timer_hw2reg_intr_state0_mreg_t [0:0] intr_state0; // [1:0] ++ rv_timer_hw2reg_timer_v_lower0_reg_t timer_v_lower0; // [135:103] ++ rv_timer_hw2reg_timer_v_upper0_reg_t timer_v_upper0; // [102:70] ++ rv_timer_hw2reg_intr_state0_mreg_t [0:0] intr_state0; // [69:68] ++ rv_timer_hw2reg_timer_v_lower1_reg_t timer_v_lower1; // [67:35] ++ rv_timer_hw2reg_timer_v_upper1_reg_t timer_v_upper1; // [34:2] ++ rv_timer_hw2reg_intr_state1_mreg_t [0:0] intr_state1; // [1:0] + } rv_timer_hw2reg_t; + + // Register offsets +- parameter logic [BlockAw-1:0] RV_TIMER_CTRL_OFFSET = 9'h 0; +- parameter logic [BlockAw-1:0] RV_TIMER_CFG0_OFFSET = 9'h 100; +- parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_LOWER0_OFFSET = 9'h 104; +- parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_UPPER0_OFFSET = 9'h 108; +- parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_LOWER0_0_OFFSET = 9'h 10c; +- parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_UPPER0_0_OFFSET = 9'h 110; +- parameter logic [BlockAw-1:0] RV_TIMER_INTR_ENABLE0_OFFSET = 9'h 114; +- parameter logic [BlockAw-1:0] RV_TIMER_INTR_STATE0_OFFSET = 9'h 118; +- parameter logic [BlockAw-1:0] RV_TIMER_INTR_TEST0_OFFSET = 9'h 11c; ++ parameter logic [BlockAw-1:0] RV_TIMER_CTRL_OFFSET = 10'h 0; ++ parameter logic [BlockAw-1:0] RV_TIMER_CFG0_OFFSET = 10'h 100; ++ parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_LOWER0_OFFSET = 10'h 104; ++ parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_UPPER0_OFFSET = 10'h 108; ++ parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_LOWER0_0_OFFSET = 10'h 10c; ++ parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_UPPER0_0_OFFSET = 10'h 110; ++ parameter logic [BlockAw-1:0] RV_TIMER_INTR_ENABLE0_OFFSET = 10'h 114; ++ parameter logic [BlockAw-1:0] RV_TIMER_INTR_STATE0_OFFSET = 10'h 118; ++ parameter logic [BlockAw-1:0] RV_TIMER_INTR_TEST0_OFFSET = 10'h 11c; ++ parameter logic [BlockAw-1:0] RV_TIMER_CFG1_OFFSET = 10'h 200; ++ parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_LOWER1_OFFSET = 10'h 204; ++ parameter logic [BlockAw-1:0] RV_TIMER_TIMER_V_UPPER1_OFFSET = 10'h 208; ++ parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_LOWER1_0_OFFSET = 10'h 20c; ++ parameter logic [BlockAw-1:0] RV_TIMER_COMPARE_UPPER1_0_OFFSET = 10'h 210; ++ parameter logic [BlockAw-1:0] RV_TIMER_INTR_ENABLE1_OFFSET = 10'h 214; ++ parameter logic [BlockAw-1:0] RV_TIMER_INTR_STATE1_OFFSET = 10'h 218; ++ parameter logic [BlockAw-1:0] RV_TIMER_INTR_TEST1_OFFSET = 10'h 21c; + + // Reset values for hwext registers and their fields + parameter logic [0:0] RV_TIMER_INTR_TEST0_RESVAL = 1'h 0; ++ parameter logic [0:0] RV_TIMER_INTR_TEST1_RESVAL = 1'h 0; + + // Register index + typedef enum int { +@@ -120,20 +195,36 @@ package rv_timer_reg_pkg; + RV_TIMER_COMPARE_UPPER0_0, + RV_TIMER_INTR_ENABLE0, + RV_TIMER_INTR_STATE0, +- RV_TIMER_INTR_TEST0 ++ RV_TIMER_INTR_TEST0, ++ RV_TIMER_CFG1, ++ RV_TIMER_TIMER_V_LOWER1, ++ RV_TIMER_TIMER_V_UPPER1, ++ RV_TIMER_COMPARE_LOWER1_0, ++ RV_TIMER_COMPARE_UPPER1_0, ++ RV_TIMER_INTR_ENABLE1, ++ RV_TIMER_INTR_STATE1, ++ RV_TIMER_INTR_TEST1 + } rv_timer_id_e; + + // Register width information to check illegal writes +- parameter logic [3:0] RV_TIMER_PERMIT [9] = '{ +- 4'b 0001, // index[0] RV_TIMER_CTRL +- 4'b 0111, // index[1] RV_TIMER_CFG0 +- 4'b 1111, // index[2] RV_TIMER_TIMER_V_LOWER0 +- 4'b 1111, // index[3] RV_TIMER_TIMER_V_UPPER0 +- 4'b 1111, // index[4] RV_TIMER_COMPARE_LOWER0_0 +- 4'b 1111, // index[5] RV_TIMER_COMPARE_UPPER0_0 +- 4'b 0001, // index[6] RV_TIMER_INTR_ENABLE0 +- 4'b 0001, // index[7] RV_TIMER_INTR_STATE0 +- 4'b 0001 // index[8] RV_TIMER_INTR_TEST0 ++ parameter logic [3:0] RV_TIMER_PERMIT [17] = '{ ++ 4'b 0001, // index[ 0] RV_TIMER_CTRL ++ 4'b 0111, // index[ 1] RV_TIMER_CFG0 ++ 4'b 1111, // index[ 2] RV_TIMER_TIMER_V_LOWER0 ++ 4'b 1111, // index[ 3] RV_TIMER_TIMER_V_UPPER0 ++ 4'b 1111, // index[ 4] RV_TIMER_COMPARE_LOWER0_0 ++ 4'b 1111, // index[ 5] RV_TIMER_COMPARE_UPPER0_0 ++ 4'b 0001, // index[ 6] RV_TIMER_INTR_ENABLE0 ++ 4'b 0001, // index[ 7] RV_TIMER_INTR_STATE0 ++ 4'b 0001, // index[ 8] RV_TIMER_INTR_TEST0 ++ 4'b 0111, // index[ 9] RV_TIMER_CFG1 ++ 4'b 1111, // index[10] RV_TIMER_TIMER_V_LOWER1 ++ 4'b 1111, // index[11] RV_TIMER_TIMER_V_UPPER1 ++ 4'b 1111, // index[12] RV_TIMER_COMPARE_LOWER1_0 ++ 4'b 1111, // index[13] RV_TIMER_COMPARE_UPPER1_0 ++ 4'b 0001, // index[14] RV_TIMER_INTR_ENABLE1 ++ 4'b 0001, // index[15] RV_TIMER_INTR_STATE1 ++ 4'b 0001 // index[16] RV_TIMER_INTR_TEST1 + }; + + endpackage diff --git a/hw/ip/rv_timer/rtl/rv_timer_reg_top.sv b/hw/ip/rv_timer/rtl/rv_timer_reg_top.sv -index 548772059..9521e9089 100644 +index 548772059..413282d82 100644 --- a/hw/ip/rv_timer/rtl/rv_timer_reg_top.sv +++ b/hw/ip/rv_timer/rtl/rv_timer_reg_top.sv +@@ -25,7 +25,7 @@ module rv_timer_reg_top ( + + import rv_timer_reg_pkg::* ; + +- localparam int AW = 9; ++ localparam int AW = 10; + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + @@ -45,38 +45,10 @@ module rv_timer_reg_top ( tlul_pkg::tl_h2d_t tl_reg_h2d; tlul_pkg::tl_d2h_t tl_reg_d2h; @@ -43,7 +552,7 @@ index 548772059..9521e9089 100644 tlul_adapter_reg #( .RegAw(AW), -@@ -99,7 +71,7 @@ module rv_timer_reg_top ( +@@ -99,14 +71,17 @@ module rv_timer_reg_top ( ); assign reg_rdata = reg_rdata_next ; @@ -52,3 +561,510 @@ index 548772059..9521e9089 100644 // Define SW related signals // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 +- logic ctrl_qs; +- logic ctrl_wd; +- logic ctrl_we; ++ logic ctrl_active_0_qs; ++ logic ctrl_active_0_wd; ++ logic ctrl_active_0_we; ++ logic ctrl_active_1_qs; ++ logic ctrl_active_1_wd; ++ logic ctrl_active_1_we; + logic [11:0] cfg0_prescale_qs; + logic [11:0] cfg0_prescale_wd; + logic cfg0_prescale_we; +@@ -133,23 +108,50 @@ module rv_timer_reg_top ( + logic intr_state0_we; + logic intr_test0_wd; + logic intr_test0_we; ++ logic [11:0] cfg1_prescale_qs; ++ logic [11:0] cfg1_prescale_wd; ++ logic cfg1_prescale_we; ++ logic [7:0] cfg1_step_qs; ++ logic [7:0] cfg1_step_wd; ++ logic cfg1_step_we; ++ logic [31:0] timer_v_lower1_qs; ++ logic [31:0] timer_v_lower1_wd; ++ logic timer_v_lower1_we; ++ logic [31:0] timer_v_upper1_qs; ++ logic [31:0] timer_v_upper1_wd; ++ logic timer_v_upper1_we; ++ logic [31:0] compare_lower1_0_qs; ++ logic [31:0] compare_lower1_0_wd; ++ logic compare_lower1_0_we; ++ logic [31:0] compare_upper1_0_qs; ++ logic [31:0] compare_upper1_0_wd; ++ logic compare_upper1_0_we; ++ logic intr_enable1_qs; ++ logic intr_enable1_wd; ++ logic intr_enable1_we; ++ logic intr_state1_qs; ++ logic intr_state1_wd; ++ logic intr_state1_we; ++ logic intr_test1_wd; ++ logic intr_test1_we; + + // Register instances + + // Subregister 0 of Multireg ctrl + // R[ctrl]: V(False) + ++ // F[active_0]: 0:0 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) +- ) u_ctrl ( ++ ) u_ctrl_active_0 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface +- .we (ctrl_we), +- .wd (ctrl_wd), ++ .we (ctrl_active_0_we), ++ .wd (ctrl_active_0_wd), + + // from internal hardware + .de (1'b0), +@@ -160,10 +162,37 @@ module rv_timer_reg_top ( + .q (reg2hw.ctrl[0].q ), + + // to register interface (read) +- .qs (ctrl_qs) ++ .qs (ctrl_active_0_qs) + ); + + ++ // F[active_1]: 1:1 ++ prim_subreg #( ++ .DW (1), ++ .SWACCESS("RW"), ++ .RESVAL (1'h0) ++ ) u_ctrl_active_1 ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (ctrl_active_1_we), ++ .wd (ctrl_active_1_wd), ++ ++ // from internal hardware ++ .de (1'b0), ++ .d ('0 ), ++ ++ // to internal hardware ++ .qe (), ++ .q (reg2hw.ctrl[1].q ), ++ ++ // to register interface (read) ++ .qs (ctrl_active_1_qs) ++ ); ++ ++ ++ + // R[cfg0]: V(False) + + // F[prescale]: 11:0 +@@ -402,20 +431,266 @@ module rv_timer_reg_top ( + ); + + ++ // R[cfg1]: V(False) ++ ++ // F[prescale]: 11:0 ++ prim_subreg #( ++ .DW (12), ++ .SWACCESS("RW"), ++ .RESVAL (12'h0) ++ ) u_cfg1_prescale ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (cfg1_prescale_we), ++ .wd (cfg1_prescale_wd), ++ ++ // from internal hardware ++ .de (1'b0), ++ .d ('0 ), ++ ++ // to internal hardware ++ .qe (), ++ .q (reg2hw.cfg1.prescale.q ), ++ ++ // to register interface (read) ++ .qs (cfg1_prescale_qs) ++ ); ++ ++ ++ // F[step]: 23:16 ++ prim_subreg #( ++ .DW (8), ++ .SWACCESS("RW"), ++ .RESVAL (8'h1) ++ ) u_cfg1_step ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (cfg1_step_we), ++ .wd (cfg1_step_wd), ++ ++ // from internal hardware ++ .de (1'b0), ++ .d ('0 ), ++ ++ // to internal hardware ++ .qe (), ++ .q (reg2hw.cfg1.step.q ), ++ ++ // to register interface (read) ++ .qs (cfg1_step_qs) ++ ); ++ ++ ++ // R[timer_v_lower1]: V(False) ++ ++ prim_subreg #( ++ .DW (32), ++ .SWACCESS("RW"), ++ .RESVAL (32'h0) ++ ) u_timer_v_lower1 ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (timer_v_lower1_we), ++ .wd (timer_v_lower1_wd), ++ ++ // from internal hardware ++ .de (hw2reg.timer_v_lower1.de), ++ .d (hw2reg.timer_v_lower1.d ), ++ ++ // to internal hardware ++ .qe (), ++ .q (reg2hw.timer_v_lower1.q ), ++ ++ // to register interface (read) ++ .qs (timer_v_lower1_qs) ++ ); + + +- logic [8:0] addr_hit; ++ // R[timer_v_upper1]: V(False) ++ ++ prim_subreg #( ++ .DW (32), ++ .SWACCESS("RW"), ++ .RESVAL (32'h0) ++ ) u_timer_v_upper1 ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (timer_v_upper1_we), ++ .wd (timer_v_upper1_wd), ++ ++ // from internal hardware ++ .de (hw2reg.timer_v_upper1.de), ++ .d (hw2reg.timer_v_upper1.d ), ++ ++ // to internal hardware ++ .qe (), ++ .q (reg2hw.timer_v_upper1.q ), ++ ++ // to register interface (read) ++ .qs (timer_v_upper1_qs) ++ ); ++ ++ ++ // R[compare_lower1_0]: V(False) ++ ++ prim_subreg #( ++ .DW (32), ++ .SWACCESS("RW"), ++ .RESVAL (32'hffffffff) ++ ) u_compare_lower1_0 ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (compare_lower1_0_we), ++ .wd (compare_lower1_0_wd), ++ ++ // from internal hardware ++ .de (1'b0), ++ .d ('0 ), ++ ++ // to internal hardware ++ .qe (reg2hw.compare_lower1_0.qe), ++ .q (reg2hw.compare_lower1_0.q ), ++ ++ // to register interface (read) ++ .qs (compare_lower1_0_qs) ++ ); ++ ++ ++ // R[compare_upper1_0]: V(False) ++ ++ prim_subreg #( ++ .DW (32), ++ .SWACCESS("RW"), ++ .RESVAL (32'hffffffff) ++ ) u_compare_upper1_0 ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (compare_upper1_0_we), ++ .wd (compare_upper1_0_wd), ++ ++ // from internal hardware ++ .de (1'b0), ++ .d ('0 ), ++ ++ // to internal hardware ++ .qe (reg2hw.compare_upper1_0.qe), ++ .q (reg2hw.compare_upper1_0.q ), ++ ++ // to register interface (read) ++ .qs (compare_upper1_0_qs) ++ ); ++ ++ ++ ++ // Subregister 0 of Multireg intr_enable1 ++ // R[intr_enable1]: V(False) ++ ++ prim_subreg #( ++ .DW (1), ++ .SWACCESS("RW"), ++ .RESVAL (1'h0) ++ ) u_intr_enable1 ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (intr_enable1_we), ++ .wd (intr_enable1_wd), ++ ++ // from internal hardware ++ .de (1'b0), ++ .d ('0 ), ++ ++ // to internal hardware ++ .qe (), ++ .q (reg2hw.intr_enable1[0].q ), ++ ++ // to register interface (read) ++ .qs (intr_enable1_qs) ++ ); ++ ++ ++ ++ // Subregister 0 of Multireg intr_state1 ++ // R[intr_state1]: V(False) ++ ++ prim_subreg #( ++ .DW (1), ++ .SWACCESS("W1C"), ++ .RESVAL (1'h0) ++ ) u_intr_state1 ( ++ .clk_i (clk_i ), ++ .rst_ni (rst_ni ), ++ ++ // from register interface ++ .we (intr_state1_we), ++ .wd (intr_state1_wd), ++ ++ // from internal hardware ++ .de (hw2reg.intr_state1[0].de), ++ .d (hw2reg.intr_state1[0].d ), ++ ++ // to internal hardware ++ .qe (), ++ .q (reg2hw.intr_state1[0].q ), ++ ++ // to register interface (read) ++ .qs (intr_state1_qs) ++ ); ++ ++ ++ ++ // Subregister 0 of Multireg intr_test1 ++ // R[intr_test1]: V(True) ++ ++ prim_subreg_ext #( ++ .DW (1) ++ ) u_intr_test1 ( ++ .re (1'b0), ++ .we (intr_test1_we), ++ .wd (intr_test1_wd), ++ .d ('0), ++ .qre (), ++ .qe (reg2hw.intr_test1[0].qe), ++ .q (reg2hw.intr_test1[0].q ), ++ .qs () ++ ); ++ ++ ++ ++ ++ logic [16:0] addr_hit; + always_comb begin + addr_hit = '0; +- addr_hit[0] = (reg_addr == RV_TIMER_CTRL_OFFSET); +- addr_hit[1] = (reg_addr == RV_TIMER_CFG0_OFFSET); +- addr_hit[2] = (reg_addr == RV_TIMER_TIMER_V_LOWER0_OFFSET); +- addr_hit[3] = (reg_addr == RV_TIMER_TIMER_V_UPPER0_OFFSET); +- addr_hit[4] = (reg_addr == RV_TIMER_COMPARE_LOWER0_0_OFFSET); +- addr_hit[5] = (reg_addr == RV_TIMER_COMPARE_UPPER0_0_OFFSET); +- addr_hit[6] = (reg_addr == RV_TIMER_INTR_ENABLE0_OFFSET); +- addr_hit[7] = (reg_addr == RV_TIMER_INTR_STATE0_OFFSET); +- addr_hit[8] = (reg_addr == RV_TIMER_INTR_TEST0_OFFSET); ++ addr_hit[ 0] = (reg_addr == RV_TIMER_CTRL_OFFSET); ++ addr_hit[ 1] = (reg_addr == RV_TIMER_CFG0_OFFSET); ++ addr_hit[ 2] = (reg_addr == RV_TIMER_TIMER_V_LOWER0_OFFSET); ++ addr_hit[ 3] = (reg_addr == RV_TIMER_TIMER_V_UPPER0_OFFSET); ++ addr_hit[ 4] = (reg_addr == RV_TIMER_COMPARE_LOWER0_0_OFFSET); ++ addr_hit[ 5] = (reg_addr == RV_TIMER_COMPARE_UPPER0_0_OFFSET); ++ addr_hit[ 6] = (reg_addr == RV_TIMER_INTR_ENABLE0_OFFSET); ++ addr_hit[ 7] = (reg_addr == RV_TIMER_INTR_STATE0_OFFSET); ++ addr_hit[ 8] = (reg_addr == RV_TIMER_INTR_TEST0_OFFSET); ++ addr_hit[ 9] = (reg_addr == RV_TIMER_CFG1_OFFSET); ++ addr_hit[10] = (reg_addr == RV_TIMER_TIMER_V_LOWER1_OFFSET); ++ addr_hit[11] = (reg_addr == RV_TIMER_TIMER_V_UPPER1_OFFSET); ++ addr_hit[12] = (reg_addr == RV_TIMER_COMPARE_LOWER1_0_OFFSET); ++ addr_hit[13] = (reg_addr == RV_TIMER_COMPARE_UPPER1_0_OFFSET); ++ addr_hit[14] = (reg_addr == RV_TIMER_INTR_ENABLE1_OFFSET); ++ addr_hit[15] = (reg_addr == RV_TIMER_INTR_STATE1_OFFSET); ++ addr_hit[16] = (reg_addr == RV_TIMER_INTR_TEST1_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; +@@ -423,19 +698,30 @@ module rv_timer_reg_top ( + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & +- ((addr_hit[0] & (|(RV_TIMER_PERMIT[0] & ~reg_be))) | +- (addr_hit[1] & (|(RV_TIMER_PERMIT[1] & ~reg_be))) | +- (addr_hit[2] & (|(RV_TIMER_PERMIT[2] & ~reg_be))) | +- (addr_hit[3] & (|(RV_TIMER_PERMIT[3] & ~reg_be))) | +- (addr_hit[4] & (|(RV_TIMER_PERMIT[4] & ~reg_be))) | +- (addr_hit[5] & (|(RV_TIMER_PERMIT[5] & ~reg_be))) | +- (addr_hit[6] & (|(RV_TIMER_PERMIT[6] & ~reg_be))) | +- (addr_hit[7] & (|(RV_TIMER_PERMIT[7] & ~reg_be))) | +- (addr_hit[8] & (|(RV_TIMER_PERMIT[8] & ~reg_be))))); ++ ((addr_hit[ 0] & (|(RV_TIMER_PERMIT[ 0] & ~reg_be))) | ++ (addr_hit[ 1] & (|(RV_TIMER_PERMIT[ 1] & ~reg_be))) | ++ (addr_hit[ 2] & (|(RV_TIMER_PERMIT[ 2] & ~reg_be))) | ++ (addr_hit[ 3] & (|(RV_TIMER_PERMIT[ 3] & ~reg_be))) | ++ (addr_hit[ 4] & (|(RV_TIMER_PERMIT[ 4] & ~reg_be))) | ++ (addr_hit[ 5] & (|(RV_TIMER_PERMIT[ 5] & ~reg_be))) | ++ (addr_hit[ 6] & (|(RV_TIMER_PERMIT[ 6] & ~reg_be))) | ++ (addr_hit[ 7] & (|(RV_TIMER_PERMIT[ 7] & ~reg_be))) | ++ (addr_hit[ 8] & (|(RV_TIMER_PERMIT[ 8] & ~reg_be))) | ++ (addr_hit[ 9] & (|(RV_TIMER_PERMIT[ 9] & ~reg_be))) | ++ (addr_hit[10] & (|(RV_TIMER_PERMIT[10] & ~reg_be))) | ++ (addr_hit[11] & (|(RV_TIMER_PERMIT[11] & ~reg_be))) | ++ (addr_hit[12] & (|(RV_TIMER_PERMIT[12] & ~reg_be))) | ++ (addr_hit[13] & (|(RV_TIMER_PERMIT[13] & ~reg_be))) | ++ (addr_hit[14] & (|(RV_TIMER_PERMIT[14] & ~reg_be))) | ++ (addr_hit[15] & (|(RV_TIMER_PERMIT[15] & ~reg_be))) | ++ (addr_hit[16] & (|(RV_TIMER_PERMIT[16] & ~reg_be))))); + end + +- assign ctrl_we = addr_hit[0] & reg_we & !reg_error; +- assign ctrl_wd = reg_wdata[0]; ++ assign ctrl_active_0_we = addr_hit[0] & reg_we & !reg_error; ++ assign ctrl_active_0_wd = reg_wdata[0]; ++ ++ assign ctrl_active_1_we = addr_hit[0] & reg_we & !reg_error; ++ assign ctrl_active_1_wd = reg_wdata[1]; + + assign cfg0_prescale_we = addr_hit[1] & reg_we & !reg_error; + assign cfg0_prescale_wd = reg_wdata[11:0]; +@@ -464,12 +750,40 @@ module rv_timer_reg_top ( + assign intr_test0_we = addr_hit[8] & reg_we & !reg_error; + assign intr_test0_wd = reg_wdata[0]; + ++ assign cfg1_prescale_we = addr_hit[9] & reg_we & !reg_error; ++ assign cfg1_prescale_wd = reg_wdata[11:0]; ++ ++ assign cfg1_step_we = addr_hit[9] & reg_we & !reg_error; ++ assign cfg1_step_wd = reg_wdata[23:16]; ++ ++ assign timer_v_lower1_we = addr_hit[10] & reg_we & !reg_error; ++ assign timer_v_lower1_wd = reg_wdata[31:0]; ++ ++ assign timer_v_upper1_we = addr_hit[11] & reg_we & !reg_error; ++ assign timer_v_upper1_wd = reg_wdata[31:0]; ++ ++ assign compare_lower1_0_we = addr_hit[12] & reg_we & !reg_error; ++ assign compare_lower1_0_wd = reg_wdata[31:0]; ++ ++ assign compare_upper1_0_we = addr_hit[13] & reg_we & !reg_error; ++ assign compare_upper1_0_wd = reg_wdata[31:0]; ++ ++ assign intr_enable1_we = addr_hit[14] & reg_we & !reg_error; ++ assign intr_enable1_wd = reg_wdata[0]; ++ ++ assign intr_state1_we = addr_hit[15] & reg_we & !reg_error; ++ assign intr_state1_wd = reg_wdata[0]; ++ ++ assign intr_test1_we = addr_hit[16] & reg_we & !reg_error; ++ assign intr_test1_wd = reg_wdata[0]; ++ + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin +- reg_rdata_next[0] = ctrl_qs; ++ reg_rdata_next[0] = ctrl_active_0_qs; ++ reg_rdata_next[1] = ctrl_active_1_qs; + end + + addr_hit[1]: begin +@@ -505,6 +819,39 @@ module rv_timer_reg_top ( + reg_rdata_next[0] = '0; + end + ++ addr_hit[9]: begin ++ reg_rdata_next[11:0] = cfg1_prescale_qs; ++ reg_rdata_next[23:16] = cfg1_step_qs; ++ end ++ ++ addr_hit[10]: begin ++ reg_rdata_next[31:0] = timer_v_lower1_qs; ++ end ++ ++ addr_hit[11]: begin ++ reg_rdata_next[31:0] = timer_v_upper1_qs; ++ end ++ ++ addr_hit[12]: begin ++ reg_rdata_next[31:0] = compare_lower1_0_qs; ++ end ++ ++ addr_hit[13]: begin ++ reg_rdata_next[31:0] = compare_upper1_0_qs; ++ end ++ ++ addr_hit[14]: begin ++ reg_rdata_next[0] = intr_enable1_qs; ++ end ++ ++ addr_hit[15]: begin ++ reg_rdata_next[0] = intr_state1_qs; ++ end ++ ++ addr_hit[16]: begin ++ reg_rdata_next[0] = '0; ++ end ++ + default: begin + reg_rdata_next = '1; + end diff --git a/mcu_cfg.hjson b/mcu_cfg.hjson index 79ba5d889..12d89f707 100644 --- a/mcu_cfg.hjson +++ b/mcu_cfg.hjson @@ -52,26 +52,34 @@ offset: 0x00028000, length: 0x00008000, }, - power_manager: { + spi: { offset: 0x00030000, length: 0x00010000, }, - rv_timer: { + power_manager: { offset: 0x00040000, length: 0x00010000, }, - dma: { + rv_timer_ao: { offset: 0x00050000, length: 0x00010000, }, - pad: { + dma: { offset: 0x00060000, length: 0x00010000, }, - spi: { + fast_intr_ctrl: { offset: 0x00070000, length: 0x00010000, }, + ext_periph: { + offset: 0x00080000, + length: 0x00010000, + }, + pad: { + offset: 0x00090000, + length: 0x00010000, + }, }, peripherals: { @@ -93,7 +101,7 @@ offset: 0x00030000, length: 0x00010000, }, - ext_periph: { + rv_timer: { offset: 0x00040000, length: 0x00010000, }, @@ -120,62 +128,61 @@ uart_intr_rx_break_err: 6, uart_intr_rx_timeout: 7, uart_intr_rx_parity_err: 8, - gpio_intr_0: 9, - gpio_intr_1: 10, - gpio_intr_2: 11, - gpio_intr_3: 12, - gpio_intr_4: 13, - gpio_intr_5: 14, - gpio_intr_6: 15, - gpio_intr_7: 16, - gpio_intr_8: 17, - gpio_intr_9: 18, - gpio_intr_10: 19, - gpio_intr_11: 20, - gpio_intr_12: 21, - gpio_intr_13: 22, - gpio_intr_14: 23, - gpio_intr_15: 24, - gpio_intr_16: 25, - gpio_intr_17: 26, - gpio_intr_18: 27, - gpio_intr_19: 28, - gpio_intr_20: 29, - gpio_intr_21: 30, - gpio_intr_22: 31, - gpio_intr_23: 32, - gpio_intr_24: 33, - gpio_intr_25: 34, - gpio_intr_26: 35, - gpio_intr_27: 36, - gpio_intr_28: 37, - gpio_intr_29: 38, - gpio_intr_30: 39, - gpio_intr_31: 40, - intr_fmt_watermark: 41, - intr_rx_watermark: 42, - intr_fmt_overflow: 43, - intr_rx_overflow: 44, - intr_nak: 45, - intr_scl_interference: 46, - intr_sda_interference: 47, - intr_stretch_timeout: 48, - intr_sda_unstable: 49, - intr_trans_complete: 50, - intr_tx_empty: 51, - intr_tx_nonempty: 52, - intr_tx_overflow: 53, - intr_acq_overflow: 54, - intr_ack_stop: 55, - intr_host_timeout: 56, - dma_intr_done: 57, - spi_flash_intr_error: 58, - spi_flash_intr_event: 59, - spi_intr_error: 60, - spi_intr_event: 61, - // Interrupt lines available for external interrupt sources - ext_intr_0: 62, - ext_intr_1: 63 + gpio_intr_8: 9, + gpio_intr_9: 10, + gpio_intr_10: 11, + gpio_intr_11: 12, + gpio_intr_12: 13, + gpio_intr_13: 14, + gpio_intr_14: 15, + gpio_intr_15: 16, + gpio_intr_16: 17, + gpio_intr_17: 18, + gpio_intr_18: 19, + gpio_intr_19: 20, + gpio_intr_20: 21, + gpio_intr_21: 22, + gpio_intr_22: 23, + gpio_intr_23: 24, + gpio_intr_24: 25, + gpio_intr_25: 26, + gpio_intr_26: 27, + gpio_intr_27: 28, + gpio_intr_28: 29, + gpio_intr_29: 30, + gpio_intr_30: 31, + gpio_intr_31: 32, + intr_fmt_watermark: 33, + intr_rx_watermark: 34, + intr_fmt_overflow: 35, + intr_rx_overflow: 36, + intr_nak: 37, + intr_scl_interference: 38, + intr_sda_interference: 39, + intr_stretch_timeout: 40, + intr_sda_unstable: 41, + intr_trans_complete: 42, + intr_tx_empty: 43, + intr_tx_nonempty: 44, + intr_tx_overflow: 45, + intr_acq_overflow: 46, + intr_ack_stop: 47, + intr_host_timeout: 48, + ext_intr_0: 49, + ext_intr_1: 50, + ext_intr_2: 51, + ext_intr_3: 52, + ext_intr_4: 53, + ext_intr_5: 54, + ext_intr_6: 55, + ext_intr_7: 56, + ext_intr_8: 57, + ext_intr_9: 58, + ext_intr_10: 59, + ext_intr_11: 60, + ext_intr_12: 61, + ext_intr_13: 62, + ext_intr_14: 63, }, pads: { @@ -267,5 +274,4 @@ } } - } diff --git a/sw/Makefile b/sw/Makefile index 1f95eb240..89454d29c 100644 --- a/sw/Makefile +++ b/sw/Makefile @@ -16,13 +16,13 @@ # Author: Robert Balas (balasr@iis.ee.ethz.ch) -MAKE = make +MAKE = make # riscv toolchain install path -RISCV ?= ~/.riscv -RISCV_EXE_PREFIX = $(RISCV)/bin/riscv32-unknown-elf- +RISCV ?= ~/.riscv +RISCV_EXE_PREFIX = $(RISCV)/bin/riscv32-unknown-elf- -TARGET ?= sim +TARGET ?= sim # GCC configuration CUSTOM_GCC_FLAGS = @@ -41,6 +41,8 @@ LIB_DRIVERS += $(wildcard device/lib/drivers/gpio/*.c) LIB_DRIVERS += $(wildcard device/lib/drivers/i2c/*.c) LIB_DRIVERS += $(wildcard device/lib/drivers/dma/*.c) LIB_DRIVERS += $(wildcard device/lib/drivers/power_manager/*.c) +LIB_DRIVERS += $(wildcard device/lib/drivers/fast_intr_ctrl/*.c) +LIB_DRIVERS += $(wildcard device/lib/drivers/spi_mem/*.c) LIB_DRIVERS += $(wildcard device/lib/drivers/spi_memio/*.c) LIB_DRIVERS += $(wildcard device/lib/drivers/spi_host/*.c) INC_FOLDERS = $(sort $(dir $(wildcard device/target/$(TARGET)/))) @@ -65,7 +67,6 @@ INC_FOLDERS_GCC = $(addprefix -I ,$(INC_FOLDERS)) %.dump: %.elf $(RISCV_EXE_PREFIX)objdump -xD $^ > $@ - # Running custom programs: # This is an example for running a Hello World in the testbench # We link with our custom crt0.s and syscalls.c against newlib so that we can @@ -255,6 +256,36 @@ applications/example_power_gating_core/example_power_gating_core.elf: applicatio -L $(RISCV)/riscv32-unknown-elf/lib \ -lc -lm -lgcc -flto -ffunction-sections -fdata-sections -specs=nano.specs +applications/example_power_gating_periph/example_power_gating_periph.elf: applications/example_power_gating_periph/example_power_gating_periph.c + $(RISCV_EXE_PREFIX)gcc -march=rv32imc -o $@ -w -Os -g -nostdlib \ + $(CUSTOM_GCC_FLAGS) \ + -DHOST_BUILD \ + -T linker/link.ld \ + -I $(RISCV)/riscv32-unknown-elf/include \ + $(INC_FOLDERS_GCC) \ + -static \ + $(LIB_CRT) \ + $^ $(LIB_RUNTIME) \ + $(LIB_BASE) \ + $(LIB_DRIVERS) \ + -L $(RISCV)/riscv32-unknown-elf/lib \ + -lc -lm -lgcc -flto -ffunction-sections -fdata-sections -specs=nano.specs + +applications/example_power_gating_ram_blocks/example_power_gating_ram_blocks.elf: applications/example_power_gating_ram_blocks/example_power_gating_ram_blocks.c + $(RISCV_EXE_PREFIX)gcc -march=rv32imc -o $@ -w -Os -g -nostdlib \ + $(CUSTOM_GCC_FLAGS) \ + -DHOST_BUILD \ + -T linker/link.ld \ + -I $(RISCV)/riscv32-unknown-elf/include \ + $(INC_FOLDERS_GCC) \ + -static \ + $(LIB_CRT) \ + $^ $(LIB_RUNTIME) \ + $(LIB_BASE) \ + $(LIB_DRIVERS) \ + -L $(RISCV)/riscv32-unknown-elf/lib \ + -lc -lm -lgcc -flto -ffunction-sections -fdata-sections -specs=nano.specs + applications/spi_host_example/spi_host_example.elf: applications/spi_host_example/spi_host_example.c $(RISCV_EXE_PREFIX)gcc -march=rv32imc -o $@ -w -Os -g -nostdlib \ $(CUSTOM_GCC_FLAGS) \ diff --git a/sw/applications/dma_example/dma_example.c b/sw/applications/dma_example/dma_example.c index a8ab9ce69..d48ae178f 100644 --- a/sw/applications/dma_example/dma_example.c +++ b/sw/applications/dma_example/dma_example.c @@ -9,9 +9,9 @@ #include "hart.h" #include "handler.h" #include "core_v_mini_mcu.h" -#include "rv_plic.h" -#include "rv_plic_regs.h" #include "dma.h" +#include "fast_intr_ctrl.h" +#include "fast_intr_ctrl_regs.h" // Choose which scenarios to test #define TEST_4_BYTES_ALIGNED @@ -29,49 +29,24 @@ uint32_t copied_data_1B[TEST_DATA_SIZE] __attribute__ ((aligned (4))) = { 0 }; int8_t dma_intr_flag; -// Interrupt controller variables -dif_plic_params_t rv_plic_params; -dif_plic_t rv_plic; -dif_plic_result_t plic_res; -dif_plic_irq_id_t intr_num; - -void handler_irq_external(void) { - // Claim/clear interrupt - plic_res = dif_plic_irq_claim(&rv_plic, 0, &intr_num); - if (plic_res == kDifPlicOk && intr_num == DMA_INTR_DONE) { - dma_intr_flag = 1; - } +void handler_irq_fast_dma(void) +{ + fast_intr_ctrl_t fast_intr_ctrl; + fast_intr_ctrl.base_addr = mmio_region_from_addr((uintptr_t)FAST_INTR_CTRL_START_ADDRESS); + clear_fast_interrupt(&fast_intr_ctrl, kDma_e); + + dma_intr_flag = 1; } int main(int argc, char *argv[]) { printf("--- DMA EXAMPLE ---\n"); - rv_plic_params.base_addr = mmio_region_from_addr((uintptr_t)PLIC_START_ADDRESS); - plic_res = dif_plic_init(rv_plic_params, &rv_plic); - if (plic_res != kDifPlicOk) { - printf("PLIC initialization failed\n;"); - return EXIT_FAILURE; - } - - // Set dma priority to 1 (target threshold is by default 0) to trigger an interrupt to the target (the processor) - plic_res = dif_plic_irq_set_priority(&rv_plic, DMA_INTR_DONE, 1); - if (plic_res != kDifPlicOk) { - printf("Set DMA priority failed\n;"); - return EXIT_FAILURE; - } - - plic_res = dif_plic_irq_set_enabled(&rv_plic, DMA_INTR_DONE, 0, kDifPlicToggleEnabled); - if (plic_res != kDifPlicOk) { - printf("Enable DMA interrupt failed\n;"); - return EXIT_FAILURE; - } - // Enable interrupt on processor side // Enable global interrupt for machine-level interrupts CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - // Set mie.MEIE bit to one to enable machine-level external interrupts - const uint32_t mask = 1 << 11;//IRQ_EXT_ENABLE_OFFSET; + // Set mie.MEIE bit to one to enable machine-level fast dma interrupt + const uint32_t mask = 1 << 19; CSR_SET_BITS(CSR_REG_MIE, mask); // dma peripheral structure to access the registers @@ -89,11 +64,6 @@ int main(int argc, char *argv[]) while(dma_intr_flag==0) { wait_for_interrupt(); } - // Complete the interrupt - plic_res = dif_plic_irq_complete(&rv_plic, 0, &intr_num); - if (plic_res != kDifPlicOk || intr_num != DMA_INTR_DONE) { - printf("DMA interrupt complete failed\n;"); - } #endif // TEST_4_BYTES_ALIGNED #ifdef TEST_2_BYTES_ALIGNED @@ -108,11 +78,6 @@ int main(int argc, char *argv[]) while(dma_intr_flag==0) { wait_for_interrupt(); } - // Complete the interrupt - plic_res = dif_plic_irq_complete(&rv_plic, 0, &intr_num); - if (plic_res != kDifPlicOk || intr_num != DMA_INTR_DONE) { - printf("DMA interrupt complete failed\n;"); - } #endif // TEST_2_BYTES_ALIGNED #ifdef TEST_BYTE_ALIGNED @@ -127,13 +92,8 @@ int main(int argc, char *argv[]) while(dma_intr_flag==0) { wait_for_interrupt(); } - // Complete the interrupt - plic_res = dif_plic_irq_complete(&rv_plic, 0, &intr_num); - if (plic_res != kDifPlicOk || intr_num != DMA_INTR_DONE) { - printf("DMA interrupt complete failed\n;"); - } #endif // TEST_BYTE_ALIGNED - + int32_t errors; #ifdef TEST_4_BYTES_ALIGNED diff --git a/sw/applications/example_power_gating_core/example_power_gating_core.c b/sw/applications/example_power_gating_core/example_power_gating_core.c index a389f11be..f609d7d42 100644 --- a/sw/applications/example_power_gating_core/example_power_gating_core.c +++ b/sw/applications/example_power_gating_core/example_power_gating_core.c @@ -11,53 +11,123 @@ #include "rv_timer.h" #include "power_manager.h" #include "soc_ctrl.h" +#include "rv_plic.h" +#include "rv_plic_regs.h" +#include "gpio.h" -static rv_timer_t timer; +static rv_timer_t timer_0_1; +static rv_timer_t timer_2_3; static const uint64_t kTickFreqHz = 1000 * 1000; // 1 MHz static power_manager_t power_manager; +static dif_plic_t rv_plic; +static gpio_t gpio; int main(int argc, char *argv[]) { + // Setup power_manager + mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); + power_manager.base_addr = power_manager_reg; + power_manager_counters_t power_manager_cpu_counters; - //Get current Frequency + // Setup plic + dif_plic_params_t rv_plic_params; + rv_plic_params.base_addr = mmio_region_from_addr((uintptr_t)PLIC_START_ADDRESS); + dif_plic_init(rv_plic_params, &rv_plic); + + // Get current Frequency soc_ctrl_t soc_ctrl; soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); uint32_t freq_hz = soc_ctrl_get_frequency(&soc_ctrl); - // Setup rv_timer - mmio_region_t timer_reg = mmio_region_from_addr(RV_TIMER_START_ADDRESS); - rv_timer_init(timer_reg, (rv_timer_config_t){.hart_count = 1, .comparator_count = 1}, &timer); + // Setup rv_timer_0_1 + mmio_region_t timer_0_1_reg = mmio_region_from_addr(RV_TIMER_AO_START_ADDRESS); + rv_timer_init(timer_0_1_reg, (rv_timer_config_t){.hart_count = 2, .comparator_count = 1}, &timer_0_1); rv_timer_tick_params_t tick_params; rv_timer_approximate_tick_params(freq_hz, kTickFreqHz, &tick_params); - rv_timer_set_tick_params(&timer, 0, tick_params); - rv_timer_irq_enable(&timer, 0, 0, kRvTimerEnabled); - rv_timer_arm(&timer, 0, 0, 1024); - rv_timer_counter_set_enabled(&timer, 0, kRvTimerEnabled); - // Setup power_manager - mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); - power_manager.base_addr = power_manager_reg; + // Setup rv_timer_2_3 + mmio_region_t timer_2_3_reg = mmio_region_from_addr(RV_TIMER_START_ADDRESS); + rv_timer_init(timer_2_3_reg, (rv_timer_config_t){.hart_count = 2, .comparator_count = 1}, &timer_2_3); + // Setup gpio + gpio_params_t gpio_params; + gpio_params.base_addr = mmio_region_from_addr((uintptr_t)GPIO_START_ADDRESS); + gpio_init(gpio_params, &gpio); - power_manager_cpu_counters_t power_manager_cpu_counters; - // the reset_on must be greater thatn powergate_on (i.e. first turn on, then you deassert the reset) - // the reset_off must be greater thatn powergate_off (i.e. first turn off, then you reset) - - // reset_off, reset_on, powergate_off, powergate_on - if (power_gate_cpu_counters_init(&power_manager_cpu_counters, 40, 40, 30, 30) != kPowerManagerOk) + // Init cpu_subsystem's counters + if (power_gate_counters_init(&power_manager_cpu_counters, 40, 40, 30, 30, 20, 20) != kPowerManagerOk_e) { printf("Error: power manager fail. Check the reset and powergate counters value\n"); return EXIT_FAILURE; } - // Power gate the core and wait for rv_timer interrupt - if (power_gate_core(&power_manager, kTimer, &power_manager_cpu_counters) != kPowerManagerOk) + // Power-gate and wake-up due to timer_0 + rv_timer_set_tick_params(&timer_0_1, 0, tick_params); + rv_timer_irq_enable(&timer_0_1, 0, 0, kRvTimerEnabled); + rv_timer_arm(&timer_0_1, 0, 0, 1024); + rv_timer_counter_set_enabled(&timer_0_1, 0, kRvTimerEnabled); + + if (power_gate_core(&power_manager, kTimer_0_e, &power_manager_cpu_counters) != kPowerManagerOk_e) + { + printf("Error: power manager fail.\n"); + return EXIT_FAILURE; + } + + // Power-gate and wake-up due to timer_1 + rv_timer_set_tick_params(&timer_0_1, 1, tick_params); + rv_timer_irq_enable(&timer_0_1, 1, 0, kRvTimerEnabled); + rv_timer_arm(&timer_0_1, 1, 0, 1024); + rv_timer_counter_set_enabled(&timer_0_1, 1, kRvTimerEnabled); + + if (power_gate_core(&power_manager, kTimer_1_e, &power_manager_cpu_counters) != kPowerManagerOk_e) + { + printf("Error: power manager fail.\n"); + return EXIT_FAILURE; + } + + // Power-gate and wake-up due to timer_2 + rv_timer_set_tick_params(&timer_2_3, 0, tick_params); + rv_timer_irq_enable(&timer_2_3, 0, 0, kRvTimerEnabled); + rv_timer_arm(&timer_2_3, 0, 0, 1024); + rv_timer_counter_set_enabled(&timer_2_3, 0, kRvTimerEnabled); + + if (power_gate_core(&power_manager, kTimer_2_e, &power_manager_cpu_counters) != kPowerManagerOk_e) + { + printf("Error: power manager fail.\n"); + return EXIT_FAILURE; + } + + // Power-gate and wake-up due to timer_3 + rv_timer_set_tick_params(&timer_2_3, 1, tick_params); + rv_timer_irq_enable(&timer_2_3, 1, 0, kRvTimerEnabled); + rv_timer_arm(&timer_2_3, 1, 0, 1024); + rv_timer_counter_set_enabled(&timer_2_3, 1, kRvTimerEnabled); + + if (power_gate_core(&power_manager, kTimer_3_e, &power_manager_cpu_counters) != kPowerManagerOk_e) + { + printf("Error: power manager fail.\n"); + return EXIT_FAILURE; + } + +#ifdef USE_EXTERNAL_DEVICE + // Power-gate and wake-up due to plic + dif_plic_irq_set_priority(&rv_plic, GPIO_INTR_31, 1); + dif_plic_irq_set_enabled(&rv_plic, GPIO_INTR_31, 0, kDifPlicToggleEnabled); + gpio_output_set_enabled(&gpio, 30, true); + gpio_irq_set_trigger(&gpio, 1 << 31, kGpioIrqTriggerLevelHigh); + gpio_irq_set_enabled(&gpio, 31, true); + gpio_write(&gpio, 30, true); + + if (power_gate_core(&power_manager, kPlic_e, &power_manager_cpu_counters) != kPowerManagerOk_e) { printf("Error: power manager fail.\n"); return EXIT_FAILURE; } + dif_plic_irq_id_t intr_num; + dif_plic_irq_complete(&rv_plic, 0, &intr_num); +#endif /* write something to stdout */ printf("Success.\n"); return EXIT_SUCCESS; diff --git a/sw/applications/example_power_gating_periph/example_power_gating_periph.c b/sw/applications/example_power_gating_periph/example_power_gating_periph.c new file mode 100644 index 000000000..232a45cf9 --- /dev/null +++ b/sw/applications/example_power_gating_periph/example_power_gating_periph.c @@ -0,0 +1,50 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include "csr.h" +#include "hart.h" +#include "handler.h" +#include "core_v_mini_mcu.h" +#include "power_manager.h" + +static power_manager_t power_manager; + +int main(int argc, char *argv[]) +{ + // Setup power_manager + mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); + power_manager.base_addr = power_manager_reg; + + power_manager_counters_t power_manager_periph_counters; + + // Init peripheral_subsystem's counters + if (power_gate_counters_init(&power_manager_periph_counters, 40, 40, 30, 30, 20, 20) != kPowerManagerOk_e) + { + printf("Error: power manager fail. Check the reset and powergate counters value\n"); + return EXIT_FAILURE; + } + + // Power off peripheral_subsystem + if (power_gate_domain(&power_manager, kPeriph_e, kOff_e, &power_manager_periph_counters) != kPowerManagerOk_e) + { + printf("Error: power manager fail.\n"); + return EXIT_FAILURE; + } + + // Wait some time + for (int i=0; i<100; i++) asm volatile("nop;"); + + // Power on peripheral_subsystem + if (power_gate_domain(&power_manager, kPeriph_e, kOn_e, &power_manager_periph_counters) != kPowerManagerOk_e) + { + printf("Error: power manager fail.\n"); + return EXIT_FAILURE; + } + + /* write something to stdout */ + printf("Success.\n"); + return EXIT_SUCCESS; +} diff --git a/sw/applications/example_power_gating_ram_blocks/example_power_gating_ram_blocks.c b/sw/applications/example_power_gating_ram_blocks/example_power_gating_ram_blocks.c new file mode 100644 index 000000000..67a7ca363 --- /dev/null +++ b/sw/applications/example_power_gating_ram_blocks/example_power_gating_ram_blocks.c @@ -0,0 +1,59 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include "csr.h" +#include "hart.h" +#include "handler.h" +#include "core_v_mini_mcu.h" +#include "power_manager.h" + +static power_manager_t power_manager; + +int main(int argc, char *argv[]) +{ + + +#if MEMORY_BANKS > 2 + // Setup power_manager + mmio_region_t power_manager_reg = mmio_region_from_addr(POWER_MANAGER_START_ADDRESS); + power_manager.base_addr = power_manager_reg; + + power_manager_counters_t power_manager_ram_blocks_counters; + + // Init ram block 2's counters + if (power_gate_counters_init(&power_manager_ram_blocks_counters, 40, 40, 30, 30, 20, 20) != kPowerManagerOk_e) + { + printf("Error: power manager fail. Check the reset and powergate counters value\n"); + return EXIT_FAILURE; + } + + // Power off ram block 2 + if (power_gate_domain(&power_manager, kRam_2_e, kOff_e, &power_manager_ram_blocks_counters) != kPowerManagerOk_e) + { + printf("Error: power manager fail.\n"); + return EXIT_FAILURE; + } + + // Wait some time + for (int i=0; i<100; i++) asm volatile("nop"); + + // Power on ram block 2 + if (power_gate_domain(&power_manager, kRam_2_e, kOn_e, &power_manager_ram_blocks_counters) != kPowerManagerOk_e) + { + printf("Error: power manager fail.\n"); + return EXIT_FAILURE; + } + + /* write something to stdout */ + printf("Success.\n"); + return EXIT_SUCCESS; + +#else + #pragma message ( "this application can run only when MEMORY_BANKS > 2" ) + return EXIT_FAILURE; +#endif + +} diff --git a/sw/applications/gpio_pmw/gpio_pmw.c b/sw/applications/gpio_pmw/gpio_pmw.c index ef32c41d3..ebd67d7b4 100644 --- a/sw/applications/gpio_pmw/gpio_pmw.c +++ b/sw/applications/gpio_pmw/gpio_pmw.c @@ -9,10 +9,8 @@ #define GPIO_PMW 2 - int main(int argc, char *argv[]) { - gpio_params_t gpio_params; gpio_t gpio; gpio_result_t gpio_res; @@ -28,6 +26,5 @@ int main(int argc, char *argv[]) for(int i=0;i<1000;i++) asm volatile("nop"); } - return EXIT_SUCCESS; } diff --git a/sw/applications/matadd/matadd.c b/sw/applications/matadd/matadd.c index 1ec0a2dfd..6efaaa7bc 100644 --- a/sw/applications/matadd/matadd.c +++ b/sw/applications/matadd/matadd.c @@ -21,7 +21,6 @@ int main() uint32_t errors = 0; unsigned int instr, cycles, ldstall, jrstall, imstall; - CSR_WRITE(CSR_REG_MCYCLE, 0); //execute the kernel @@ -39,15 +38,11 @@ int main() void __attribute__ ((noinline)) matrixAdd(int32_t * A, int32_t * B, int32_t * C, int N, int M) { - - for(int i = 0; i < N; i++) { for(int j = 0; j < M; j++) { C[i*N+j] = A[i*WIDTH+j] + B[i*WIDTH+j]; } } - - } uint32_t check_results(int32_t * C, int N, int M) @@ -68,4 +63,4 @@ uint32_t check_results(int32_t * C, int N, int M) } return err; -} \ No newline at end of file +} diff --git a/sw/applications/matadd/matrixAdd32.h b/sw/applications/matadd/matrixAdd32.h index e047a1115..a5f360627 100644 --- a/sw/applications/matadd/matrixAdd32.h +++ b/sw/applications/matadd/matrixAdd32.h @@ -2,60 +2,60 @@ #define MatrixAdd32_H_ int32_t m_a[16*16] = { --267220638, -815694637, -357240193, 52586566, 471263969, -752743258, -54811671, -330483534, -895389047, 476606065, -261687046, -301494394, 101299356, 1064594637, 876939884, 673598893, -510087407, 21095419, -66273695, 200819447, 230905645, -522677817, 466985617, -42864608, 925345137, -985253526, 963426323, 34126990, -894741205, -944572242, -62503253, -88084923, --40863508, 775424478, -977993934, -563294903, 240810335, -950840151, 841082377, 814816122, 1010825869, 626595210, -30466653, 32965586, -1009681585, -398274647, 209852250, -680997577, -831825297, 371554642, 209565266, -173321792, 130553499, -846489230, -837855833, -291296547, -656131005, -1008649794, -644660179, -559832327, -957317256, 414035806, 238077607, -417354312, -691270381, 167236288, -370338394, 264811381, -740211299, -502137446, -216028919, -576761164, -1005576983, -300300576, -51567714, 742968985, -713639053, 81381137, -254911471, -456085969, --657637814, 212880558, 164912940, 975706502, -558175870, -522438623, 219649600, -149341108, -761491992, -324770181, -905679666, -1066241764, 852450941, -105770862, -706293797, 965826475, -605386582, 397282251, -510180840, 322039481, 906789344, 577829424, -244909961, -6565162, -10463653, -275962613, 1045813592, 287658995, 202626085, -913131320, -953473425, 7501200, -44568419, 631042458, -962343731, 389765403, 510986448, 615528098, 854389577, 873031590, 291656555, 717742724, 139337062, 1014134612, 37179482, 156110030, 549532436, -211305424, -146967397, -910154681, 306466943, 809719463, 990862734, -321035009, -503247368, -434011427, -184327001, -460285290, -695885128, 745541667, 549735829, 972687164, 81845219, 626415449, --869892524, 7650305, -668932203, 612640394, -533618868, -767284692, 263874653, -505082478, -333082894, -170998598, 351985173, 539903843, 161284779, -223326011, -386924128, -894616525, --205913216, 983230715, 184759813, 3745004, -421392253, 311771810, 809133901, 541639735, 1029270115, 390582486, 1059667793, -308077038, -345200733, 661937983, -69729012, -313649214, --457079064, 660862401, -419895058, -352985806, 748622990, 789128492, 57857836, 123409871, 367565501, 714681971, 90478156, 401194382, -25590123, 808922190, 231668089, 365978441, --168791957, 500701111, 966566283, -619646012, 410934777, -567381204, 405170082, -954683259, -176892010, 205925886, 1035377376, 91289957, 478111519, 220727997, -859802080, -155168848, -723982461, -833318195, -445511314, -903460885, 167471780, 423323222, -640855013, 480396600, -268314639, -850542572, 257027787, -315635254, 560711756, -717798753, -372060287, -544448897, --103077323, -640041517, 577573751, 1039664378, -546538923, 739571966, 680289428, 412799378, 987282320, -378880850, 588647906, -965191092, -829907433, 739600408, -33720223, 56361300, --1068334620, -399957948, -960664907, -540542510, 280786542, -752129362, -10289650, 1029788294, -636639267, 1029706817, -892387611, 191199904, -965464658, -1048403025, -734580512, 872029387, +-267220638, -815694637, -357240193, 52586566, 471263969, -752743258, -54811671, -330483534, -895389047, 476606065, -261687046, -301494394, 101299356, 1064594637, 876939884, 673598893, +510087407, 21095419, -66273695, 200819447, 230905645, -522677817, 466985617, -42864608, 925345137, -985253526, 963426323, 34126990, -894741205, -944572242, -62503253, -88084923, +-40863508, 775424478, -977993934, -563294903, 240810335, -950840151, 841082377, 814816122, 1010825869, 626595210, -30466653, 32965586, -1009681585, -398274647, 209852250, -680997577, +831825297, 371554642, 209565266, -173321792, 130553499, -846489230, -837855833, -291296547, -656131005, -1008649794, -644660179, -559832327, -957317256, 414035806, 238077607, -417354312, +691270381, 167236288, -370338394, 264811381, -740211299, -502137446, -216028919, -576761164, -1005576983, -300300576, -51567714, 742968985, -713639053, 81381137, -254911471, -456085969, +-657637814, 212880558, 164912940, 975706502, -558175870, -522438623, 219649600, -149341108, -761491992, -324770181, -905679666, -1066241764, 852450941, -105770862, -706293797, 965826475, +605386582, 397282251, -510180840, 322039481, 906789344, 577829424, -244909961, -6565162, -10463653, -275962613, 1045813592, 287658995, 202626085, -913131320, -953473425, 7501200, +44568419, 631042458, -962343731, 389765403, 510986448, 615528098, 854389577, 873031590, 291656555, 717742724, 139337062, 1014134612, 37179482, 156110030, 549532436, -211305424, +146967397, -910154681, 306466943, 809719463, 990862734, -321035009, -503247368, -434011427, -184327001, -460285290, -695885128, 745541667, 549735829, 972687164, 81845219, 626415449, +-869892524, 7650305, -668932203, 612640394, -533618868, -767284692, 263874653, -505082478, -333082894, -170998598, 351985173, 539903843, 161284779, -223326011, -386924128, -894616525, +-205913216, 983230715, 184759813, 3745004, -421392253, 311771810, 809133901, 541639735, 1029270115, 390582486, 1059667793, -308077038, -345200733, 661937983, -69729012, -313649214, +-457079064, 660862401, -419895058, -352985806, 748622990, 789128492, 57857836, 123409871, 367565501, 714681971, 90478156, 401194382, -25590123, 808922190, 231668089, 365978441, +-168791957, 500701111, 966566283, -619646012, 410934777, -567381204, 405170082, -954683259, -176892010, 205925886, 1035377376, 91289957, 478111519, 220727997, -859802080, -155168848, +723982461, -833318195, -445511314, -903460885, 167471780, 423323222, -640855013, 480396600, -268314639, -850542572, 257027787, -315635254, 560711756, -717798753, -372060287, -544448897, +-103077323, -640041517, 577573751, 1039664378, -546538923, 739571966, 680289428, 412799378, 987282320, -378880850, 588647906, -965191092, -829907433, 739600408, -33720223, 56361300, +-1068334620, -399957948, -960664907, -540542510, 280786542, -752129362, -10289650, 1029788294, -636639267, 1029706817, -892387611, 191199904, -965464658, -1048403025, -734580512, 872029387, }; int32_t m_b[16*16] = { --451882475, -777460700, 909169980, -96074001, -300818508, 814405880, -568048006, -83472456, 402440048, 810240641, -180564453, 216877888, -140613462, 620727378, -909318526, 765805622, --231722067, -336894715, -1073684733, -121460761, -23888211, 438175722, -904262018, 145258576, -356787314, 372900212, -358591099, 140421444, -928238022, -99914115, 968352616, -71902672, --7354035, -831973999, 233305822, -392287490, -729923194, -828467700, -323283176, -788941348, -111739211, -199056442, -476803416, 465916744, 443852965, -376815395, 148885406, 124331090, --998134941, -490161461, 607731285, 887008149, 683830004, -186741406, -241303958, 456378716, 536730595, 967225269, 1037796891, -802215107, 382626188, 791688228, 538691527, -19673298, -251682349, 598278365, 984763713, 698038628, 821027888, -495782484, -798473539, -424505599, 310436971, 361824506, -130460722, -847926918, 926418138, 637997507, 565305015, 901041052, -236841072, 748341019, 851219634, 437917539, 979456559, 834327011, -191800443, 415161968, -687346999, -41616108, 226338567, 671381489, -248505365, -991524242, 465050274, 673573191, --432551530, 1057245412, 714468280, -650829182, -850172935, 408331778, 846612827, 884618062, -1025138869, 389044228, 241552082, 1038961376, -425996140, -770151901, -59811946, 433319347, -420324744, -41895865, -626338369, -617719112, -398763632, 40560785, 608712418, 270292226, 276772130, 713936878, -39616963, 852564869, 651061789, -1069752389, 942487510, -212496210, --884568730, -614540093, 940597970, 963278316, 500604546, -89930534, -362276438, 800923761, 799305363, 67728257, -935053727, -507421158, 453168328, -270267180, 767962559, 540805, --178905319, 755067965, -132287841, -8637376, 608185815, 427835026, 103464976, -203264205, 80225884, 539643001, -362743073, -487778248, 792077066, 697184933, 827496823, 790812604, -249285726, 359686773, 419021969, 454726313, 124358246, 47824230, -619837186, -913155286, -381944316, 783327309, 572077053, -225060553, 787746239, 671339856, 730167112, 870184696, -319311551, 932192632, -376845525, -288051918, 713264893, -102198441, -315559203, -635483087, -76253988, -427900440, -508626018, -847322511, -717023663, 649773356, -751674700, -363502823, -896873064, -967112426, -607994984, 346538028, -403535863, -456242519, -865446025, -238823125, 568667781, -1008745310, -517236588, -90482335, -769550983, -553756781, -473911347, -317302102, -308779302, 610106502, -99323447, -610238668, 176302035, 320291710, 22124485, 927846370, -961507070, 1046393978, 623269088, -385024596, -636139940, -661255126, -1024580190, -710776275, -874358552, -978379641, 484825057, -177908522, -643611415, -197553591, 406358020, 460342548, 408235584, -809119385, 1047128507, -592130753, -50891763, 786819419, 314046385, 461621105, --328939806, 375494681, 558517164, 640788713, -419567316, -499867631, 629778826, 201608525, 1006046604, 259505742, 994398852, 338082134, -444011788, 128878595, -672831452, 18560178, +-451882475, -777460700, 909169980, -96074001, -300818508, 814405880, -568048006, -83472456, 402440048, 810240641, -180564453, 216877888, -140613462, 620727378, -909318526, 765805622, +-231722067, -336894715, -1073684733, -121460761, -23888211, 438175722, -904262018, 145258576, -356787314, 372900212, -358591099, 140421444, -928238022, -99914115, 968352616, -71902672, +-7354035, -831973999, 233305822, -392287490, -729923194, -828467700, -323283176, -788941348, -111739211, -199056442, -476803416, 465916744, 443852965, -376815395, 148885406, 124331090, +-998134941, -490161461, 607731285, 887008149, 683830004, -186741406, -241303958, 456378716, 536730595, 967225269, 1037796891, -802215107, 382626188, 791688228, 538691527, -19673298, +251682349, 598278365, 984763713, 698038628, 821027888, -495782484, -798473539, -424505599, 310436971, 361824506, -130460722, -847926918, 926418138, 637997507, 565305015, 901041052, +236841072, 748341019, 851219634, 437917539, 979456559, 834327011, -191800443, 415161968, -687346999, -41616108, 226338567, 671381489, -248505365, -991524242, 465050274, 673573191, +-432551530, 1057245412, 714468280, -650829182, -850172935, 408331778, 846612827, 884618062, -1025138869, 389044228, 241552082, 1038961376, -425996140, -770151901, -59811946, 433319347, +420324744, -41895865, -626338369, -617719112, -398763632, 40560785, 608712418, 270292226, 276772130, 713936878, -39616963, 852564869, 651061789, -1069752389, 942487510, -212496210, +-884568730, -614540093, 940597970, 963278316, 500604546, -89930534, -362276438, 800923761, 799305363, 67728257, -935053727, -507421158, 453168328, -270267180, 767962559, 540805, +-178905319, 755067965, -132287841, -8637376, 608185815, 427835026, 103464976, -203264205, 80225884, 539643001, -362743073, -487778248, 792077066, 697184933, 827496823, 790812604, +249285726, 359686773, 419021969, 454726313, 124358246, 47824230, -619837186, -913155286, -381944316, 783327309, 572077053, -225060553, 787746239, 671339856, 730167112, 870184696, +319311551, 932192632, -376845525, -288051918, 713264893, -102198441, -315559203, -635483087, -76253988, -427900440, -508626018, -847322511, -717023663, 649773356, -751674700, -363502823, +896873064, -967112426, -607994984, 346538028, -403535863, -456242519, -865446025, -238823125, 568667781, -1008745310, -517236588, -90482335, -769550983, -553756781, -473911347, -317302102, +308779302, 610106502, -99323447, -610238668, 176302035, 320291710, 22124485, 927846370, -961507070, 1046393978, 623269088, -385024596, -636139940, -661255126, -1024580190, -710776275, +874358552, -978379641, 484825057, -177908522, -643611415, -197553591, 406358020, 460342548, 408235584, -809119385, 1047128507, -592130753, -50891763, 786819419, 314046385, 461621105, +-328939806, 375494681, 558517164, 640788713, -419567316, -499867631, 629778826, 201608525, 1006046604, 259505742, 994398852, 338082134, -444011788, 128878595, -672831452, 18560178, }; int32_t m_exp[16*16] = { --719103113, -1593155337, 551929787, -43487435, 170445461, 61662622, -622859677, -413955990, -492948999, 1286846706, -442251499, -84616506, -39314106, 1685322015, -32378642, 1439404515, -278365340, -315799296, -1139958428, 79358686, 207017434, -84502095, -437276401, 102393968, 568557823, -612353314, 604835224, 174548434, -1822979227, -1044486357, 905849363, -159987595, --48217543, -56549521, -744688112, -955582393, -489112859, -1779307851, 517799201, 25874774, 899086658, 427538768, -507270069, 498882330, -565828620, -775090042, 358737656, -556666487, --166309644, -118606819, 817296551, 713686357, 814383503, -1033230636, -1079159791, 165082169, -119400410, -41424525, 393136712, -1362047434, -574691068, 1205724034, 776769134, -437027610, -942952730, 765514653, 614425319, 962850009, 80816589, -997919930, -1014502458, -1001266763, -695140012, 61523930, -182028436, -104957933, 212779085, 719378644, 310393544, 444955083, --420796742, 961221577, 1016132574, 1413624041, 421280689, 311888388, 27849157, 265820860, -1448838991, -366386289, -679341099, -394860275, 603945576, -1097295104, -241243523, 1639399666, -172835052, 1454527663, 204287440, -328789701, 56616409, 986161202, 601702866, 878052900, -1035602522, 113081615, 1287365674, 1326620371, -223370055, -1683283221, -1013285371, 440820547, -464893163, 589146593, -1588682100, -227953709, 112222816, 656088883, 1463101995, 1143323816, 568428685, 1431679602, 99720099, 1866699481, 688241271, -913642359, 1492019946, -423801634, --737601333, -1524694774, 1247064913, 1772997779, 1491467280, -410965543, -865523806, 366912334, 614978362, -392557033, -1630938855, 238120509, 1002904157, 702419984, 849807778, 626956254, --1048797843, 762718270, -801220044, 604003018, 74566947, -339449666, 367339629, -708346683, -252857010, 368644403, -10757900, 52125595, 953361845, 473858922, 440572695, -103803921, -43372510, 1342917488, 603781782, 458471317, -297034007, 359596040, 189296715, -371515551, 647325799, 1173909795, 1631744846, -533137591, 442545506, 1333277839, 660438100, 556535482, --137767513, 1593055033, -796740583, -641037724, 1461887883, 686930051, -257701367, -512073216, 291311513, 286781531, -418147862, -446128129, -742613786, 1458695546, -520006611, 2475618, -728081107, -466411315, 358571299, -273107984, 7398914, -1023623723, -460275943, -1193506384, 391775771, -802819424, 518140788, 807622, -291439464, -333028784, -1333713427, -472470950, -1032761763, -223211693, -544834761, -1513699553, 343773815, 743614932, -618730528, 1408242970, -1229821709, 195851406, 880296875, -700659850, -75428184, -1379053879, -1396640477, -1255225172, -771281229, -1618421158, 1062398808, 861755856, -1190150338, 542018375, 1086647448, 873141926, 1395517904, -1188000235, 1635776413, -1557321845, -880799196, 1526419827, 280326162, 517982405, --1397274426, -24463267, -402147743, 100246203, -138780774, -1251996993, 619489176, 1231396819, 369407337, 1289212559, 102011241, 529282038, -1409476446, -919524430, -1407411964, 890589565, +-719103113, -1593155337, 551929787, -43487435, 170445461, 61662622, -622859677, -413955990, -492948999, 1286846706, -442251499, -84616506, -39314106, 1685322015, -32378642, 1439404515, +278365340, -315799296, -1139958428, 79358686, 207017434, -84502095, -437276401, 102393968, 568557823, -612353314, 604835224, 174548434, -1822979227, -1044486357, 905849363, -159987595, +-48217543, -56549521, -744688112, -955582393, -489112859, -1779307851, 517799201, 25874774, 899086658, 427538768, -507270069, 498882330, -565828620, -775090042, 358737656, -556666487, +-166309644, -118606819, 817296551, 713686357, 814383503, -1033230636, -1079159791, 165082169, -119400410, -41424525, 393136712, -1362047434, -574691068, 1205724034, 776769134, -437027610, +942952730, 765514653, 614425319, 962850009, 80816589, -997919930, -1014502458, -1001266763, -695140012, 61523930, -182028436, -104957933, 212779085, 719378644, 310393544, 444955083, +-420796742, 961221577, 1016132574, 1413624041, 421280689, 311888388, 27849157, 265820860, -1448838991, -366386289, -679341099, -394860275, 603945576, -1097295104, -241243523, 1639399666, +172835052, 1454527663, 204287440, -328789701, 56616409, 986161202, 601702866, 878052900, -1035602522, 113081615, 1287365674, 1326620371, -223370055, -1683283221, -1013285371, 440820547, +464893163, 589146593, -1588682100, -227953709, 112222816, 656088883, 1463101995, 1143323816, 568428685, 1431679602, 99720099, 1866699481, 688241271, -913642359, 1492019946, -423801634, +-737601333, -1524694774, 1247064913, 1772997779, 1491467280, -410965543, -865523806, 366912334, 614978362, -392557033, -1630938855, 238120509, 1002904157, 702419984, 849807778, 626956254, +-1048797843, 762718270, -801220044, 604003018, 74566947, -339449666, 367339629, -708346683, -252857010, 368644403, -10757900, 52125595, 953361845, 473858922, 440572695, -103803921, +43372510, 1342917488, 603781782, 458471317, -297034007, 359596040, 189296715, -371515551, 647325799, 1173909795, 1631744846, -533137591, 442545506, 1333277839, 660438100, 556535482, +-137767513, 1593055033, -796740583, -641037724, 1461887883, 686930051, -257701367, -512073216, 291311513, 286781531, -418147862, -446128129, -742613786, 1458695546, -520006611, 2475618, +728081107, -466411315, 358571299, -273107984, 7398914, -1023623723, -460275943, -1193506384, 391775771, -802819424, 518140788, 807622, -291439464, -333028784, -1333713427, -472470950, +1032761763, -223211693, -544834761, -1513699553, 343773815, 743614932, -618730528, 1408242970, -1229821709, 195851406, 880296875, -700659850, -75428184, -1379053879, -1396640477, -1255225172, +771281229, -1618421158, 1062398808, 861755856, -1190150338, 542018375, 1086647448, 873141926, 1395517904, -1188000235, 1635776413, -1557321845, -880799196, 1526419827, 280326162, 517982405, +-1397274426, -24463267, -402147743, 100246203, -138780774, -1251996993, 619489176, 1231396819, 369407337, 1289212559, 102011241, 529282038, -1409476446, -919524430, -1407411964, 890589565, }; #define WIDTH 16 diff --git a/sw/applications/spi_host_dma_example/spi_host_dma_example.c b/sw/applications/spi_host_dma_example/spi_host_dma_example.c index 142413385..73c4595d2 100644 --- a/sw/applications/spi_host_dma_example/spi_host_dma_example.c +++ b/sw/applications/spi_host_dma_example/spi_host_dma_example.c @@ -15,6 +15,8 @@ #include "soc_ctrl.h" #include "spi_host.h" #include "dma.h" +#include "fast_intr_ctrl.h" +#include "fast_intr_ctrl_regs.h" // Un-comment this line to use the SPI FLASH instead of the default SPI #define USE_SPI_FLASH @@ -22,24 +24,16 @@ #define COPY_DATA_BYTES 15 #define SPI_BYTES (4 * (uint32_t)((COPY_DATA_BYTES-1) / 4 + 1)) // Only sends data when an entire word has been received -// int8_t spi_intr_flag; int8_t dma_intr_flag; - -// Interrupt controller variables -dif_plic_params_t rv_plic_params; -dif_plic_t rv_plic; -dif_plic_result_t plic_res; -dif_plic_irq_id_t intr_num; - spi_host_t spi_host; -void handler_irq_external(void) { - // Claim/clear interrupt - plic_res = dif_plic_irq_claim(&rv_plic, 0, &intr_num); - // DMA Interrupt - if (plic_res == kDifPlicOk && intr_num == DMA_INTR_DONE) { - dma_intr_flag = 1; - } +void handler_irq_fast_dma(void) +{ + fast_intr_ctrl_t fast_intr_ctrl; + fast_intr_ctrl.base_addr = mmio_region_from_addr((uintptr_t)FAST_INTR_CTRL_START_ADDRESS); + clear_fast_interrupt(&fast_intr_ctrl, kDma_e); + + dma_intr_flag = 1; } // Reserve memory array @@ -57,33 +51,11 @@ int main(int argc, char *argv[]) soc_ctrl_t soc_ctrl; soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - // Init the PLIC - rv_plic_params.base_addr = mmio_region_from_addr((uintptr_t)PLIC_START_ADDRESS); - plic_res = dif_plic_init(rv_plic_params, &rv_plic); - if (plic_res != kDifPlicOk) { - printf("Unable to set the PLIC\n;"); - return EXIT_FAILURE; - } - - // Set DMA priority to 1 (target threshold is by default 0) to trigger an interrupt to the target (the processor) - plic_res = dif_plic_irq_set_priority(&rv_plic, DMA_INTR_DONE, 1); - if (plic_res != kDifPlicOk) { - printf("Unable to set the PLIC priority\n;"); - return EXIT_FAILURE; - } - - // Enable DMA interrupt - plic_res = dif_plic_irq_set_enabled(&rv_plic, DMA_INTR_DONE, 0, kDifPlicToggleEnabled); - if (plic_res != kDifPlicOk) { - printf("Unable to enable the PLIC irq\n;"); - return EXIT_FAILURE; - } - // Enable interrupt on processor side // Enable global interrupt for machine-level interrupts CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - // Set mie.MEIE bit to one to enable machine-level external interrupts - const uint32_t mask = 1 << 11;// ; + // Set mie.MEIE bit to one to enable machine-level fast dma interrupt + const uint32_t mask = 1 << 19; CSR_SET_BITS(CSR_REG_MIE, mask); // spi_intr_flag = 0; dma_intr_flag = 0; @@ -148,7 +120,7 @@ int main(int argc, char *argv[]) // The address bytes sent through the SPI to the Flash are in reverse order uint32_t flash_data_addr = flash_data; - uint32_t read_byte_cmd = (flash_data_addr >> 16); + uint32_t read_byte_cmd = (flash_data_addr >> 16); read_byte_cmd = (read_byte_cmd | (flash_data_addr & 0xff00)); read_byte_cmd = (read_byte_cmd | ((flash_data_addr & 0xff) << 16)); // Add read command in the first byte sent @@ -189,12 +161,6 @@ int main(int argc, char *argv[]) } printf("triggered!\n"); - // Complete interrupt - plic_res = dif_plic_irq_complete(&rv_plic, 0, &intr_num); - if (plic_res != kDifPlicOk || intr_num != DMA_INTR_DONE) { - printf("IRQ complete incorrect\n;"); - } - // The data is already in memory -- Check results printf("flash vs ram...\n"); diff --git a/sw/applications/spi_host_example/spi_host_example.c b/sw/applications/spi_host_example/spi_host_example.c index 9141eee8e..a54e70303 100644 --- a/sw/applications/spi_host_example/spi_host_example.c +++ b/sw/applications/spi_host_example/spi_host_example.c @@ -10,36 +10,32 @@ #include "csr.h" #include "hart.h" #include "handler.h" -#include "rv_plic.h" -#include "rv_plic_regs.h" #include "soc_ctrl.h" #include "spi_host.h" +#include "fast_intr_ctrl.h" +#include "fast_intr_ctrl_regs.h" // Simple example to check the SPI host peripheral is working. It checks the ram and flash have the same content #define DATA_CHUNK_ADDR 0x00008000 int8_t spi_intr_flag; +spi_host_t spi_host; +uint32_t flash_data[8]; -// Interrupt controller variables -dif_plic_params_t rv_plic_params; -dif_plic_t rv_plic; -dif_plic_result_t plic_res; -dif_plic_irq_id_t intr_num; +void handler_irq_fast_spi(void) +{ + // Disable SPI interrupts + spi_enable_evt_intr(&spi_host, false); + spi_enable_rxwm_intr(&spi_host, false); -spi_host_t spi_host; + // Clear fast interrupt + fast_intr_ctrl_t fast_intr_ctrl; + fast_intr_ctrl.base_addr = mmio_region_from_addr((uintptr_t)FAST_INTR_CTRL_START_ADDRESS); + clear_fast_interrupt(&fast_intr_ctrl, kSpi_e); -void handler_irq_external(void) { - // Claim/clear interrupt - plic_res = dif_plic_irq_claim(&rv_plic, 0, &intr_num); - if (plic_res == kDifPlicOk && intr_num == SPI_INTR_EVENT) { - spi_intr_flag = 1; - // Disable SPI interrupt otherwise it stays on until RX FIFO is read - dif_plic_irq_set_enabled(&rv_plic, SPI_INTR_EVENT, 0, kDifPlicToggleDisabled); - } + spi_intr_flag = 1; } -uint32_t flash_data[8]; - int main(int argc, char *argv[]) { // spi_host_t spi_host; @@ -48,18 +44,11 @@ int main(int argc, char *argv[]) soc_ctrl_t soc_ctrl; soc_ctrl.base_addr = mmio_region_from_addr((uintptr_t)SOC_CTRL_START_ADDRESS); - // Init the PLIC - rv_plic_params.base_addr = mmio_region_from_addr((uintptr_t)PLIC_START_ADDRESS); - plic_res = dif_plic_init(rv_plic_params, &rv_plic); - // Set SPI interrupt priority to 1 - plic_res = dif_plic_irq_set_priority(&rv_plic, SPI_INTR_EVENT, 1); - // Enable SPI interrupt - plic_res = dif_plic_irq_set_enabled(&rv_plic, SPI_INTR_EVENT, 0, kDifPlicToggleEnabled); // Enable interrupt on processor side // Enable global interrupt for machine-level interrupts CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); - // Set mie.MEIE bit to one to enable machine-level external interrupts - const uint32_t mask = 1 << 11;// ; + // Set mie.MEIE bit to one to enable machine-level fast spi interrupt + const uint32_t mask = 1 << 20; CSR_SET_BITS(CSR_REG_MIE, mask); spi_intr_flag = 0; @@ -166,8 +155,10 @@ int main(int argc, char *argv[]) wait_for_interrupt(); } - // Complete interrupt - plic_res = dif_plic_irq_complete(&rv_plic, 0, &intr_num); + // Enable event interrupt + spi_enable_evt_intr(&spi_host, true); + // Enable RX watermark interrupt + spi_enable_rxwm_intr(&spi_host, true); // Read data from SPI RX FIFO for (int i=0; i<8; i++) { diff --git a/sw/device/lib/crt/vectors.S b/sw/device/lib/crt/vectors.S index 4bba06284..041eae2d2 100644 --- a/sw/device/lib/crt/vectors.S +++ b/sw/device/lib/crt/vectors.S @@ -49,10 +49,36 @@ vector_table: j __no_irq_handler // 15 : unmapped j __no_irq_handler - // vendor interrupts: on Ibex interrupt ids 30-16 are the "fast" interrupts - .rept 15 + // 16 : fast interrupt - timer_1 + j handler_irq_fast_timer_1 + // 17 : fast interrupt - timer_2 + j handler_irq_fast_timer_2 + // 18 : fast interrupt - timer_3 + j handler_irq_fast_timer_3 + // 19 : fast interrupt - dma + j handler_irq_fast_dma + // 20 : fast interrupt - spi + j handler_irq_fast_spi + // 21 : fast interrupt - gpio_0 + j handler_irq_fast_gpio_0 + // 22 : fast interrupt - gpio_1 + j handler_irq_fast_gpio_1 + // 23 : fast interrupt - gpio_2 + j handler_irq_fast_gpio_2 + // 24 : fast interrupt - gpio_3 + j handler_irq_fast_gpio_3 + // 25 : fast interrupt - gpio_4 + j handler_irq_fast_gpio_4 + // 26 : fast interrupt - gpio_5 + j handler_irq_fast_gpio_5 + // 27 : fast interrupt - gpio_6 + j handler_irq_fast_gpio_6 + // 28 : fast interrupt - gpio_7 + j handler_irq_fast_gpio_7 + // 29 : fast interrupt - unmapped + j __no_irq_handler + // 30 : fast interrupt - unmapped j __no_irq_handler - .endr // vendor interrupts: on Ibex interrupt id 31 is for non-maskable interrupts j __no_irq_handler // 64-32 : not connected on Ibex diff --git a/sw/device/lib/crt_flash_exec/vectors.S b/sw/device/lib/crt_flash_exec/vectors.S index c853ee9a7..488ebf60c 100644 --- a/sw/device/lib/crt_flash_exec/vectors.S +++ b/sw/device/lib/crt_flash_exec/vectors.S @@ -49,10 +49,36 @@ vector_table: j __no_irq_handler // 15 : unmapped j __no_irq_handler - // vendor interrupts: on Ibex interrupt ids 30-16 are the "fast" interrupts - .rept 15 + // 16 : fast interrupt - timer_1 + j handler_irq_fast_timer_1 + // 17 : fast interrupt - timer_2 + j handler_irq_fast_timer_2 + // 18 : fast interrupt - timer_3 + j handler_irq_fast_timer_3 + // 19 : fast interrupt - dma + j handler_irq_fast_dma + // 20 : fast interrupt - spi + j handler_irq_fast_spi + // 21 : fast interrupt - gpio_0 + j handler_irq_fast_gpio_0 + // 22 : fast interrupt - gpio_1 + j handler_irq_fast_gpio_1 + // 23 : fast interrupt - gpio_2 + j handler_irq_fast_gpio_2 + // 24 : fast interrupt - gpio_3 + j handler_irq_fast_gpio_3 + // 25 : fast interrupt - gpio_4 + j handler_irq_fast_gpio_4 + // 26 : fast interrupt - gpio_5 + j handler_irq_fast_gpio_5 + // 27 : fast interrupt - gpio_6 + j handler_irq_fast_gpio_6 + // 28 : fast interrupt - gpio_7 + j handler_irq_fast_gpio_7 + // 29 : fast interrupt - unmapped + j __no_irq_handler + // 30 : fast interrupt - unmapped j __no_irq_handler - .endr // vendor interrupts: on Ibex interrupt id 31 is for non-maskable interrupts j __no_irq_handler // 64-32 : not connected on Ibex diff --git a/sw/device/lib/crt_flash_load/vectors.S b/sw/device/lib/crt_flash_load/vectors.S index 4bba06284..041eae2d2 100644 --- a/sw/device/lib/crt_flash_load/vectors.S +++ b/sw/device/lib/crt_flash_load/vectors.S @@ -49,10 +49,36 @@ vector_table: j __no_irq_handler // 15 : unmapped j __no_irq_handler - // vendor interrupts: on Ibex interrupt ids 30-16 are the "fast" interrupts - .rept 15 + // 16 : fast interrupt - timer_1 + j handler_irq_fast_timer_1 + // 17 : fast interrupt - timer_2 + j handler_irq_fast_timer_2 + // 18 : fast interrupt - timer_3 + j handler_irq_fast_timer_3 + // 19 : fast interrupt - dma + j handler_irq_fast_dma + // 20 : fast interrupt - spi + j handler_irq_fast_spi + // 21 : fast interrupt - gpio_0 + j handler_irq_fast_gpio_0 + // 22 : fast interrupt - gpio_1 + j handler_irq_fast_gpio_1 + // 23 : fast interrupt - gpio_2 + j handler_irq_fast_gpio_2 + // 24 : fast interrupt - gpio_3 + j handler_irq_fast_gpio_3 + // 25 : fast interrupt - gpio_4 + j handler_irq_fast_gpio_4 + // 26 : fast interrupt - gpio_5 + j handler_irq_fast_gpio_5 + // 27 : fast interrupt - gpio_6 + j handler_irq_fast_gpio_6 + // 28 : fast interrupt - gpio_7 + j handler_irq_fast_gpio_7 + // 29 : fast interrupt - unmapped + j __no_irq_handler + // 30 : fast interrupt - unmapped j __no_irq_handler - .endr // vendor interrupts: on Ibex interrupt id 31 is for non-maskable interrupts j __no_irq_handler // 64-32 : not connected on Ibex diff --git a/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.c b/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.c new file mode 100644 index 000000000..dcc9a6035 --- /dev/null +++ b/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.c @@ -0,0 +1,24 @@ +// Copyright 2022 OpenHW Group +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#include "fast_intr_ctrl.h" + +#include +#include + +#include "mmio.h" + +#include "core_v_mini_mcu.h" + +#include "fast_intr_ctrl_regs.h" // Generated. + +fast_intr_ctrl_result_t clear_fast_interrupt(fast_intr_ctrl_t* fast_intr_ctrl, fast_intr_ctrl_fast_interrupt_t fast_interrupt) +{ + uint32_t reg = 0; + + reg = bitfield_bit32_write(reg, fast_interrupt, true); + mmio_region_write32(fast_intr_ctrl->base_addr, (ptrdiff_t)(FAST_INTR_CTRL_FAST_INTR_CLEAR_REG_OFFSET), reg); + + return kFastIntrCtrlOk_e; +} diff --git a/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.h b/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.h new file mode 100644 index 000000000..ef4ddce82 --- /dev/null +++ b/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl.h @@ -0,0 +1,62 @@ +// Copyright 2022 OpenHW Group +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#ifndef _FAST_INTR_CTRL_H_ +#define _FAST_INTR_CTRL_H_ + +#include +#include + +#include "mmio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialization parameters for FAST INTR CTRL. + * + */ +typedef struct fast_intr_ctrl { + /** + * The base address for the fast intr ctrl hardware registers. + */ + mmio_region_t base_addr; +} fast_intr_ctrl_t; + +/** + * Results. + */ +typedef enum fast_intr_ctrl_result { + kFastIntrCtrlOk_e = 0, + kFastIntrCtrlError_e = 1, +} fast_intr_ctrl_result_t; + +/** + * Fast interrupts. + */ +typedef enum fast_intr_ctrl_fast_interrupt { + kTimer_1_e = 0, + kTimer_2_e = 1, + kTimer_3_e = 2, + kDma_e = 3, + kSpi_e = 4, + kSpiFlash = 5, + kGpio_0_e = 6, + kGpio_1_e = 7, + kGpio_2_e = 8, + kGpio_3_e = 9, + kGpio_4_e = 10, + kGpio_5_e = 11, + kGpio_6_e = 12, + kGpio_7_e = 13, +} fast_intr_ctrl_fast_interrupt_t; + +fast_intr_ctrl_result_t clear_fast_interrupt(fast_intr_ctrl_t* fast_intr_ctrl, fast_intr_ctrl_fast_interrupt_t fast_interrupt); + +#ifdef __cplusplus +} +#endif + +#endif // _FAST_INTR_CTRL_H_ diff --git a/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl_regs.h b/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl_regs.h new file mode 100644 index 000000000..75a159021 --- /dev/null +++ b/sw/device/lib/drivers/fast_intr_ctrl/fast_intr_ctrl_regs.h @@ -0,0 +1,37 @@ +// Generated register defines for fast_intr_ctrl + +// Copyright information found in source file: +// Copyright lowRISC contributors. + +// Licensing information found in source file: +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef _FAST_INTR_CTRL_REG_DEFS_ +#define _FAST_INTR_CTRL_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define FAST_INTR_CTRL_PARAM_REG_WIDTH 32 + +// Pending fast interrupt +#define FAST_INTR_CTRL_FAST_INTR_PENDING_REG_OFFSET 0x0 +#define FAST_INTR_CTRL_FAST_INTR_PENDING_FAST_INTR_PENDING_MASK 0xffff +#define FAST_INTR_CTRL_FAST_INTR_PENDING_FAST_INTR_PENDING_OFFSET 0 +#define FAST_INTR_CTRL_FAST_INTR_PENDING_FAST_INTR_PENDING_FIELD \ + ((bitfield_field32_t) { .mask = FAST_INTR_CTRL_FAST_INTR_PENDING_FAST_INTR_PENDING_MASK, .index = FAST_INTR_CTRL_FAST_INTR_PENDING_FAST_INTR_PENDING_OFFSET }) + +// Clear fast interrupt +#define FAST_INTR_CTRL_FAST_INTR_CLEAR_REG_OFFSET 0x4 +#define FAST_INTR_CTRL_FAST_INTR_CLEAR_FAST_INTR_CLEAR_MASK 0xffff +#define FAST_INTR_CTRL_FAST_INTR_CLEAR_FAST_INTR_CLEAR_OFFSET 0 +#define FAST_INTR_CTRL_FAST_INTR_CLEAR_FAST_INTR_CLEAR_FIELD \ + ((bitfield_field32_t) { .mask = FAST_INTR_CTRL_FAST_INTR_CLEAR_FAST_INTR_CLEAR_MASK, .index = FAST_INTR_CTRL_FAST_INTR_CLEAR_FAST_INTR_CLEAR_OFFSET }) + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _FAST_INTR_CTRL_REG_DEFS_ +// End generated register defines for fast_intr_ctrl \ No newline at end of file diff --git a/sw/device/lib/drivers/power_manager/data/power_manager.h.tpl b/sw/device/lib/drivers/power_manager/data/power_manager.h.tpl new file mode 100644 index 000000000..e03a6b47f --- /dev/null +++ b/sw/device/lib/drivers/power_manager/data/power_manager.h.tpl @@ -0,0 +1,103 @@ +// Copyright 2022 OpenHW Group +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +#ifndef _POWER_MANAGER_H_ +#define _POWER_MANAGER_H_ + +#include +#include + +#include "mmio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Results. + */ +typedef enum power_manager_result { + kPowerManagerOk_e = 0, + kPowerManagerError_e = 1, +} power_manager_result_t; + +/** + * Domains. + */ +typedef enum power_manager_sel_domain { + kPeriph_e = 0, +% for bank in range(ram_numbanks): + kRam_${bank}_e = ${bank+1}, +% endfor +} power_manager_sel_domain_t; + +/** + * Domain states. + */ +typedef enum power_manager_sel_state { + kOn_e = 0, + kOff_e = 1, +} power_manager_sel_state_t; + +/** + * Interrupt source. + */ +typedef enum power_manager_sel_intr { + kTimer_0_e = 0, + kPlic_e = 1, + kTimer_1_e = 2, + kTimer_2_e = 3, + kTimer_3_e = 4, + kDma_e = 5, + kSpi_e = 6, + kSpiFlash_e = 7, + kGpio_0_e = 8, + kGpio_1_e = 9, + kGpio_2_e = 10, + kGpio_3_e = 11, + kGpio_4_e = 12, + kGpio_5_e = 13, + kGpio_6_e = 14, + kGpio_7_e = 15, + kExt_0_e = 16, + kExt_1_e = 17, + kExt_2_e = 18, + kExt_3_e = 19, +} power_manager_sel_intr_t; + +/** + * Initialization parameters for POWER MANAGER. + * + */ +typedef struct power_manager { + /** + * The base address for the power_manager hardware registers. + */ + mmio_region_t base_addr; +} power_manager_t; + +typedef struct power_manager_counters { + /** + * The counter to set and unset the reset and switch of the CPU. + */ + uint32_t reset_off; + uint32_t reset_on; + uint32_t switch_off; + uint32_t switch_on; + uint32_t iso_off; + uint32_t iso_on; + +} power_manager_counters_t; + +power_manager_result_t power_gate_counters_init(power_manager_counters_t* counters, uint32_t reset_off, uint32_t reset_on, uint32_t switch_off, uint32_t switch_on, uint32_t iso_off, uint32_t iso_on); + +power_manager_result_t power_gate_core(const power_manager_t *power_manager, power_manager_sel_intr_t sel_intr, power_manager_counters_t* cpu_counters); + +power_manager_result_t power_gate_domain(const power_manager_t *power_manager, power_manager_sel_domain_t sel_domain, power_manager_sel_state_t sel_state, power_manager_counters_t* domain_counters); + +#ifdef __cplusplus +} +#endif + +#endif // _POWER_MANAGER_H_ diff --git a/sw/device/lib/drivers/power_manager/power_manager.c b/sw/device/lib/drivers/power_manager/power_manager.c index 48e7dc0ae..c581827a1 100644 --- a/sw/device/lib/drivers/power_manager/power_manager.c +++ b/sw/device/lib/drivers/power_manager/power_manager.c @@ -13,9 +13,10 @@ #include "power_manager_regs.h" // Generated. +#include "fast_intr_ctrl_regs.h" // Generated. + void power_gate_core_asm() { - asm volatile ( // write POWER_GATE_CORE[0] = 1 @@ -109,6 +110,41 @@ void power_gate_core_asm() [power_manager_core_reg_x31_reg_offset] "i" (POWER_MANAGER_CORE_REG_X31_REG_OFFSET) \ ); + asm volatile ( + + // write CORE_REG_Xn[31:0] = Xn + "lui a0, %[base_address_20bit]\n" + "csrr a1, mstatus\n" + "sw a1, %[power_manager_core_csr_mstatus_reg_offset](a0)\n" + "csrr a1, mie\n" + "sw a1, %[power_manager_core_csr_mie_reg_offset](a0)\n" + "csrr a1, mscratch\n" + "sw a1, %[power_manager_core_csr_mscratch_reg_offset](a0)\n" + "csrr a1, mepc\n" + "sw a1, %[power_manager_core_csr_mepc_reg_offset](a0)\n" + "csrr a1, mcause\n" + "sw a1, %[power_manager_core_csr_mcause_reg_offset](a0)\n" + "csrr a1, mtval\n" + "sw a1, %[power_manager_core_csr_mtval_reg_offset](a0)\n" + "csrr a1, mtvec\n" + "sw a1, %[power_manager_core_csr_mtvec_reg_offset](a0)\n" + "csrr a1, mcycle\n" + "sw a1, %[power_manager_core_csr_mcycle_reg_offset](a0)\n" + "csrr a1, minstret\n" + "sw a1, %[power_manager_core_csr_minstret_reg_offset](a0)\n" : : \ + \ + [base_address_20bit] "i" (POWER_MANAGER_START_ADDRESS >> 12), \ + [power_manager_core_csr_mstatus_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MSTATUS_REG_OFFSET), \ + [power_manager_core_csr_mie_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MIE_REG_OFFSET), \ + [power_manager_core_csr_mscratch_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MSCRATCH_REG_OFFSET), \ + [power_manager_core_csr_mepc_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MEPC_REG_OFFSET), \ + [power_manager_core_csr_mcause_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MCAUSE_REG_OFFSET), \ + [power_manager_core_csr_mtval_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MTVAL_REG_OFFSET), \ + [power_manager_core_csr_mtvec_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MTVEC_REG_OFFSET), \ + [power_manager_core_csr_mcycle_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MCYCLE_REG_OFFSET), \ + [power_manager_core_csr_minstret_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MINSTRET_REG_OFFSET) \ + ); + asm volatile ( // write RESTORE_ADDRESS[31:0] = PC @@ -130,7 +166,7 @@ void power_gate_core_asm() // write POWER_GATE_CORE[0] = 0 "wakeup:" "lui a0, %[base_address_20bit]\n" - "sw x0, %[power_manager_power_gate_core_reg_offset](a0)\n" + "sw x0, %[power_manager_power_gate_core_reg_offset](a0)\n" // write WAKEUP_STATE[0] = 0 "sw x0, %[power_manager_wakeup_state_reg_offset](a0)\n" @@ -222,64 +258,146 @@ void power_gate_core_asm() [power_manager_core_reg_x31_reg_offset] "i" (POWER_MANAGER_CORE_REG_X31_REG_OFFSET) \ ); + asm volatile ( + + // read CORE_REG_Xn[31:0] = Xn + "lui a0, %[base_address_20bit]\n" + "lw a1, %[power_manager_core_csr_mstatus_reg_offset](a0)\n" + "csrw mstatus, a1\n" + "lw a1, %[power_manager_core_csr_mie_reg_offset](a0)\n" + "csrw mie, a1\n" + "lw a1, %[power_manager_core_csr_mscratch_reg_offset](a0)\n" + "csrw mscratch, a1\n" + "lw a1, %[power_manager_core_csr_mepc_reg_offset](a0)\n" + "csrw mepc, a1\n" + "lw a1, %[power_manager_core_csr_mcause_reg_offset](a0)\n" + "csrw mcause, a1\n" + "lw a1, %[power_manager_core_csr_mtval_reg_offset](a0)\n" + "csrw mtval, a1\n" + "lw a1, %[power_manager_core_csr_mtvec_reg_offset](a0)\n" + "csrw mtvec, a1\n" + "lw a1, %[power_manager_core_csr_mcycle_reg_offset](a0)\n" + "csrw mcycle, a1\n" + "lw a1, %[power_manager_core_csr_minstret_reg_offset](a0)\n" + "csrw minstret, a1\n" : : \ + \ + [base_address_20bit] "i" (POWER_MANAGER_START_ADDRESS >> 12), \ + [power_manager_core_csr_mstatus_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MSTATUS_REG_OFFSET), \ + [power_manager_core_csr_mie_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MIE_REG_OFFSET), \ + [power_manager_core_csr_mscratch_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MSCRATCH_REG_OFFSET), \ + [power_manager_core_csr_mepc_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MEPC_REG_OFFSET), \ + [power_manager_core_csr_mcause_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MCAUSE_REG_OFFSET), \ + [power_manager_core_csr_mtval_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MTVAL_REG_OFFSET), \ + [power_manager_core_csr_mtvec_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MTVEC_REG_OFFSET), \ + [power_manager_core_csr_mcycle_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MCYCLE_REG_OFFSET), \ + [power_manager_core_csr_minstret_reg_offset] "i" (POWER_MANAGER_CORE_CSR_MINSTRET_REG_OFFSET) \ + ); + return; } -power_manager_result_t __attribute__ ((noinline)) power_gate_core(const power_manager_t *power_manager, power_manager_sel_intr_t sel_intr, power_manager_cpu_counters_t* cpu_counter) +power_manager_result_t __attribute__ ((noinline)) power_gate_core(const power_manager_t *power_manager, power_manager_sel_intr_t sel_intr, power_manager_counters_t* cpu_counter) { - - uint32_t reg = 0; - if (sel_intr == kTimer) + // set counters + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_RESET_ASSERT_COUNTER_REG_OFFSET), cpu_counter->reset_off); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_RESET_DEASSERT_COUNTER_REG_OFFSET), cpu_counter->reset_on); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_SWITCH_OFF_COUNTER_REG_OFFSET), cpu_counter->switch_off); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_SWITCH_ON_COUNTER_REG_OFFSET), cpu_counter->switch_on); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_ISO_OFF_COUNTER_REG_OFFSET), cpu_counter->iso_off); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_ISO_ON_COUNTER_REG_OFFSET), cpu_counter->iso_on); + + // enable wakeup timers + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_EN_WAIT_FOR_INTR_REG_OFFSET), 1 << sel_intr); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_INTR_STATE_REG_OFFSET), 0x0); + + power_gate_core_asm(); + + // clean up states + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_EN_WAIT_FOR_INTR_REG_OFFSET), 0x0); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_INTR_STATE_REG_OFFSET), 0x0); + + // stop counters + reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_RESET_ASSERT_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_RESET_DEASSERT_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_SWITCH_OFF_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_SWITCH_ON_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_ISO_OFF_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_ISO_ON_STOP_BIT_COUNTER_BIT, true); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_COUNTERS_STOP_REG_OFFSET), reg); + + // clear fast interrupt + if (sel_intr >= 2 || sel_intr <= 15) { + mmio_region_t base_addr = mmio_region_from_addr((uintptr_t)FAST_INTR_CTRL_START_ADDRESS); + reg = bitfield_bit32_write(reg, sel_intr, true); + mmio_region_write32(base_addr, (ptrdiff_t)(FAST_INTR_CTRL_FAST_INTR_CLEAR_REG_OFFSET), reg); + } - //set counters - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_RESET_ASSERT_COUNTER_REG_OFFSET), cpu_counter->reset_off); - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_RESET_DEASSERT_COUNTER_REG_OFFSET), cpu_counter->reset_on); - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_SWITCH_OFF_COUNTER_REG_OFFSET), cpu_counter->powergate_off); - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_SWITCH_ON_COUNTER_REG_OFFSET), cpu_counter->powergate_on); - - //enable wakeup timers - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_EN_WAIT_FOR_INTR_REG_OFFSET), 0x1); - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_INTR_STATE_REG_OFFSET), 0x0); - - power_gate_core_asm(); - - //clean up states - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_EN_WAIT_FOR_INTR_REG_OFFSET), 0x0); - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_INTR_STATE_REG_OFFSET), 0x0); + return kPowerManagerOk_e; +} - //stop counters - reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_RESET_ASSERT_STOP_BIT_COUNTER_BIT, true); - reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_RESET_DEASSERT_STOP_BIT_COUNTER_BIT, true); - reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_SWITCH_OFF_STOP_BIT_COUNTER_BIT, true); - reg = bitfield_bit32_write(reg, POWER_MANAGER_CPU_COUNTERS_STOP_CPU_SWITCH_ON_STOP_BIT_COUNTER_BIT, true); - mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_CPU_COUNTERS_STOP_REG_OFFSET), reg); +power_manager_result_t power_gate_domain(const power_manager_t *power_manager, power_manager_sel_domain_t sel_domain, power_manager_sel_state_t sel_state, power_manager_counters_t* domain_counters) +{ + uint32_t reg = 0; + if (sel_domain == kPeriph_e) + { + // set counters + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_RESET_ASSERT_COUNTER_REG_OFFSET), domain_counters->reset_off); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_RESET_DEASSERT_COUNTER_REG_OFFSET), domain_counters->reset_on); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_SWITCH_OFF_COUNTER_REG_OFFSET), domain_counters->switch_off); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_SWITCH_ON_COUNTER_REG_OFFSET), domain_counters->switch_on); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_ISO_OFF_COUNTER_REG_OFFSET), domain_counters->iso_off); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_ISO_ON_COUNTER_REG_OFFSET), domain_counters->iso_on); + + if (sel_state == kOn_e) + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_POWER_GATE_PERIPH_REG_OFFSET), 0x0); + else + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_POWER_GATE_PERIPH_REG_OFFSET), 0x1); + + // stop counters + reg = bitfield_bit32_write(reg, POWER_MANAGER_PERIPH_COUNTERS_STOP_PERIPH_RESET_ASSERT_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_PERIPH_COUNTERS_STOP_PERIPH_RESET_DEASSERT_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_PERIPH_COUNTERS_STOP_PERIPH_SWITCH_OFF_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_PERIPH_COUNTERS_STOP_PERIPH_SWITCH_ON_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_PERIPH_COUNTERS_STOP_PERIPH_ISO_OFF_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_PERIPH_COUNTERS_STOP_PERIPH_ISO_ON_STOP_BIT_COUNTER_BIT, true); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_PERIPH_COUNTERS_STOP_REG_OFFSET), reg); } else { - return kPowerManagerError; + // set counters + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_RAM_0_SWITCH_OFF_COUNTER_REG_OFFSET + (0x14 * (sel_domain - 1))), domain_counters->switch_off); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_RAM_0_SWITCH_ON_COUNTER_REG_OFFSET + (0x14 * (sel_domain - 1))), domain_counters->switch_on); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_RAM_0_ISO_OFF_COUNTER_REG_OFFSET + (0x14 * (sel_domain - 1))), domain_counters->iso_off); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_RAM_0_ISO_ON_COUNTER_REG_OFFSET + (0x14 * (sel_domain - 1))), domain_counters->iso_on); + + if (sel_state == kOn_e) + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_POWER_GATE_RAM_BLOCK_0_REG_OFFSET + (0x4 * (sel_domain - 1))), 0x0); + else + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_POWER_GATE_RAM_BLOCK_0_REG_OFFSET + (0x4 * (sel_domain - 1))), 0x1); + + // stop counters + reg = bitfield_bit32_write(reg, POWER_MANAGER_RAM_0_COUNTERS_STOP_RAM_0_SWITCH_OFF_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_RAM_0_COUNTERS_STOP_RAM_0_SWITCH_ON_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_RAM_0_COUNTERS_STOP_RAM_0_ISO_OFF_STOP_BIT_COUNTER_BIT, true); + reg = bitfield_bit32_write(reg, POWER_MANAGER_RAM_0_COUNTERS_STOP_RAM_0_ISO_ON_STOP_BIT_COUNTER_BIT, true); + mmio_region_write32(power_manager->base_addr, (ptrdiff_t)(POWER_MANAGER_RAM_0_COUNTERS_STOP_REG_OFFSET + (0x14 * (sel_domain - 1))), reg); } - return kPowerManagerOk; + return kPowerManagerOk_e; } -power_manager_result_t power_gate_cpu_counters_init(power_manager_cpu_counters_t* cpu_counter, uint32_t reset_off, uint32_t reset_on, uint32_t powergate_off, uint32_t powergate_on) +power_manager_result_t power_gate_counters_init(power_manager_counters_t* counters, uint32_t reset_off, uint32_t reset_on, uint32_t switch_off, uint32_t switch_on, uint32_t iso_off, uint32_t iso_on) { - - // the reset_on must be greater thatn powergate_on (i.e. first turn on, then you deassert the reset) - // the reset_off must be greater thatn powergate_off (i.e. first turn off, then you reset) - - if(reset_on <= powergate_on) return kPowerManagerError; - if(reset_off <= powergate_off) return kPowerManagerError; - - cpu_counter->reset_off = reset_off; - cpu_counter->reset_on = reset_on; - cpu_counter->powergate_off = powergate_off; - cpu_counter->powergate_on = powergate_on; - - return kPowerManagerOk; + counters->reset_off = reset_off; + counters->reset_on = reset_on; + counters->switch_off = switch_off; + counters->switch_on = switch_on; + counters->iso_off = iso_off; + counters->iso_on = iso_on; + + return kPowerManagerOk_e; } - diff --git a/sw/device/lib/drivers/power_manager/power_manager.h b/sw/device/lib/drivers/power_manager/power_manager.h deleted file mode 100644 index 4d9c2f336..000000000 --- a/sw/device/lib/drivers/power_manager/power_manager.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2022 OpenHW Group -// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 - -#ifndef _POWER_MANAGER_H_ -#define _POWER_MANAGER_H_ - -#include -#include - -#include "mmio.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Results. - */ -typedef enum power_manager_result { - kPowerManagerOk = 0, - kPowerManagerError = 2, -} power_manager_result_t; - -/** - * Interrupt source. - */ -typedef enum power_manager_sel_intr { - kTimer = 0, -} power_manager_sel_intr_t; - -/** - * Initialization parameters for POWER MANAGER. - * - */ -typedef struct power_manager { - /** - * The base address for the power_manager hardware registers. - */ - mmio_region_t base_addr; -} power_manager_t; - - -typedef struct power_manager_cpu_counters { - /** - * The counter to set and unset the reset and switch of the CPU. - */ - uint32_t reset_off; - uint32_t reset_on; - uint32_t powergate_off; - uint32_t powergate_on; - -} power_manager_cpu_counters_t; - -/** - * Power gate core and wait for interrupt to wake-up. - */ - -power_manager_result_t power_gate_cpu_counters_init(power_manager_cpu_counters_t* cpu_counter, uint32_t reset_off, uint32_t reset_on, uint32_t powergate_off, uint32_t powergate_on); - -power_manager_result_t power_gate_core(const power_manager_t *power_manager, power_manager_sel_intr_t sel_intr, power_manager_cpu_counters_t* cpu_counter); - - - - -#ifdef __cplusplus -} -#endif - -#endif // _POWER_MANAGER_H_ diff --git a/sw/device/lib/drivers/power_manager/power_manager_regs.h b/sw/device/lib/drivers/power_manager/power_manager_regs.h deleted file mode 100644 index 9d3babf0d..000000000 --- a/sw/device/lib/drivers/power_manager/power_manager_regs.h +++ /dev/null @@ -1,179 +0,0 @@ -// Generated register defines for power_manager - -// Copyright information found in source file: -// Copyright lowRISC contributors. - -// Licensing information found in source file: -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#ifndef _POWER_MANAGER_REG_DEFS_ -#define _POWER_MANAGER_REG_DEFS_ - -#ifdef __cplusplus -extern "C" { -#endif -// Register width -#define POWER_MANAGER_PARAM_REG_WIDTH 32 - -// Used to power gate the core -#define POWER_MANAGER_POWER_GATE_CORE_REG_OFFSET 0x0 -#define POWER_MANAGER_POWER_GATE_CORE_POWER_GATE_CORE_BIT 0 - -// Wake-up state of the system -#define POWER_MANAGER_WAKEUP_STATE_REG_OFFSET 0x4 -#define POWER_MANAGER_WAKEUP_STATE_WAKEUP_STATE_BIT 0 - -// Restore xddress value -#define POWER_MANAGER_RESTORE_ADDRESS_REG_OFFSET 0x8 - -// Core reg x1 value -#define POWER_MANAGER_CORE_REG_X1_REG_OFFSET 0xc - -// Core reg x2 value -#define POWER_MANAGER_CORE_REG_X2_REG_OFFSET 0x10 - -// Core reg x3 value -#define POWER_MANAGER_CORE_REG_X3_REG_OFFSET 0x14 - -// Core reg x4 value -#define POWER_MANAGER_CORE_REG_X4_REG_OFFSET 0x18 - -// Core reg x5 value -#define POWER_MANAGER_CORE_REG_X5_REG_OFFSET 0x1c - -// Core reg x6 value -#define POWER_MANAGER_CORE_REG_X6_REG_OFFSET 0x20 - -// Core reg x7 value -#define POWER_MANAGER_CORE_REG_X7_REG_OFFSET 0x24 - -// Core reg x8 value -#define POWER_MANAGER_CORE_REG_X8_REG_OFFSET 0x28 - -// Core reg x9 value -#define POWER_MANAGER_CORE_REG_X9_REG_OFFSET 0x2c - -// Core reg x10 value -#define POWER_MANAGER_CORE_REG_X10_REG_OFFSET 0x30 - -// Core reg x11 value -#define POWER_MANAGER_CORE_REG_X11_REG_OFFSET 0x34 - -// Core reg x12 value -#define POWER_MANAGER_CORE_REG_X12_REG_OFFSET 0x38 - -// Core reg x13 value -#define POWER_MANAGER_CORE_REG_X13_REG_OFFSET 0x3c - -// Core reg x14 value -#define POWER_MANAGER_CORE_REG_X14_REG_OFFSET 0x40 - -// Core reg x15 value -#define POWER_MANAGER_CORE_REG_X15_REG_OFFSET 0x44 - -// Core reg x16 value -#define POWER_MANAGER_CORE_REG_X16_REG_OFFSET 0x48 - -// Core reg x17 value -#define POWER_MANAGER_CORE_REG_X17_REG_OFFSET 0x4c - -// Core reg x18 value -#define POWER_MANAGER_CORE_REG_X18_REG_OFFSET 0x50 - -// Core reg x19 value -#define POWER_MANAGER_CORE_REG_X19_REG_OFFSET 0x54 - -// Core reg x20 value -#define POWER_MANAGER_CORE_REG_X20_REG_OFFSET 0x58 - -// Core reg x21 value -#define POWER_MANAGER_CORE_REG_X21_REG_OFFSET 0x5c - -// Core reg x22 value -#define POWER_MANAGER_CORE_REG_X22_REG_OFFSET 0x60 - -// Core reg x23 value -#define POWER_MANAGER_CORE_REG_X23_REG_OFFSET 0x64 - -// Core reg x24 value -#define POWER_MANAGER_CORE_REG_X24_REG_OFFSET 0x68 - -// Core reg x25 value -#define POWER_MANAGER_CORE_REG_X25_REG_OFFSET 0x6c - -// Core reg x26 value -#define POWER_MANAGER_CORE_REG_X26_REG_OFFSET 0x70 - -// Core reg x27 value -#define POWER_MANAGER_CORE_REG_X27_REG_OFFSET 0x74 - -// Core reg x28 value -#define POWER_MANAGER_CORE_REG_X28_REG_OFFSET 0x78 - -// Core reg x29 value -#define POWER_MANAGER_CORE_REG_X29_REG_OFFSET 0x7c - -// Core reg x30 value -#define POWER_MANAGER_CORE_REG_X30_REG_OFFSET 0x80 - -// Core reg x31 value -#define POWER_MANAGER_CORE_REG_X31_REG_OFFSET 0x84 - -// Core csr c0 value -#define POWER_MANAGER_CORE_CSR_C0_REG_OFFSET 0x88 - -// Core csr c1 value -#define POWER_MANAGER_CORE_CSR_C1_REG_OFFSET 0x8c - -// Core csr c2 value -#define POWER_MANAGER_CORE_CSR_C2_REG_OFFSET 0x90 - -// Core csr c3 value -#define POWER_MANAGER_CORE_CSR_C3_REG_OFFSET 0x94 - -// Core csr c4 value -#define POWER_MANAGER_CORE_CSR_C4_REG_OFFSET 0x98 - -// Core csr c5 value -#define POWER_MANAGER_CORE_CSR_C5_REG_OFFSET 0x9c - -// Core csr c6 value -#define POWER_MANAGER_CORE_CSR_C6_REG_OFFSET 0xa0 - -// Core csr c7 value -#define POWER_MANAGER_CORE_CSR_C7_REG_OFFSET 0xa4 - -// Enable wait for interrupt -#define POWER_MANAGER_EN_WAIT_FOR_INTR_REG_OFFSET 0xa8 -#define POWER_MANAGER_EN_WAIT_FOR_INTR_EN_WAIT_FOR_INTR_BIT 0 - -// Interrupt state -#define POWER_MANAGER_INTR_STATE_REG_OFFSET 0xac -#define POWER_MANAGER_INTR_STATE_INTR_STATE_BIT 0 - -// Counter before resetting the CPU -#define POWER_MANAGER_CPU_RESET_ASSERT_COUNTER_REG_OFFSET 0xb0 - -// Counter before unreset the CPU -#define POWER_MANAGER_CPU_RESET_DEASSERT_COUNTER_REG_OFFSET 0xb4 - -// Counter before switching off the CPU -#define POWER_MANAGER_CPU_SWITCH_OFF_COUNTER_REG_OFFSET 0xb8 - -// Counter before switching on the CPU -#define POWER_MANAGER_CPU_SWITCH_ON_COUNTER_REG_OFFSET 0xbc - -// Bits to stop the counters keeping the done_o signal high -#define POWER_MANAGER_CPU_COUNTERS_STOP_REG_OFFSET 0xc0 -#define POWER_MANAGER_CPU_COUNTERS_STOP_CPU_RESET_ASSERT_STOP_BIT_COUNTER_BIT 0 -#define POWER_MANAGER_CPU_COUNTERS_STOP_CPU_RESET_DEASSERT_STOP_BIT_COUNTER_BIT \ - 1 -#define POWER_MANAGER_CPU_COUNTERS_STOP_CPU_SWITCH_OFF_STOP_BIT_COUNTER_BIT 2 -#define POWER_MANAGER_CPU_COUNTERS_STOP_CPU_SWITCH_ON_STOP_BIT_COUNTER_BIT 3 - -#ifdef __cplusplus -} // extern "C" -#endif -#endif // _POWER_MANAGER_REG_DEFS_ -// End generated register defines for power_manager \ No newline at end of file diff --git a/sw/device/lib/drivers/rv_timer/rv_timer_regs.h b/sw/device/lib/drivers/rv_timer/rv_timer_regs.h index e2f655ccb..07b38d996 100644 --- a/sw/device/lib/drivers/rv_timer/rv_timer_regs.h +++ b/sw/device/lib/drivers/rv_timer/rv_timer_regs.h @@ -14,7 +14,7 @@ extern "C" { #endif // Number of harts -#define RV_TIMER_PARAM_N_HARTS 1 +#define RV_TIMER_PARAM_N_HARTS 2 // Number of timers per Hart #define RV_TIMER_PARAM_N_TIMERS 1 @@ -30,6 +30,7 @@ extern "C" { // Control register #define RV_TIMER_CTRL_REG_OFFSET 0x0 #define RV_TIMER_CTRL_ACTIVE_0_BIT 0 +#define RV_TIMER_CTRL_ACTIVE_1_BIT 1 // Configuration for Hart 0 #define RV_TIMER_CFG0_REG_OFFSET 0x100 @@ -81,8 +82,58 @@ extern "C" { #define RV_TIMER_INTR_TEST0_REG_OFFSET 0x11c #define RV_TIMER_INTR_TEST0_T_0_BIT 0 +// Configuration for Hart 1 +#define RV_TIMER_CFG1_REG_OFFSET 0x200 +#define RV_TIMER_CFG1_PRESCALE_MASK 0xfff +#define RV_TIMER_CFG1_PRESCALE_OFFSET 0 +#define RV_TIMER_CFG1_PRESCALE_FIELD \ + ((bitfield_field32_t) { .mask = RV_TIMER_CFG1_PRESCALE_MASK, .index = RV_TIMER_CFG1_PRESCALE_OFFSET }) +#define RV_TIMER_CFG1_STEP_MASK 0xff +#define RV_TIMER_CFG1_STEP_OFFSET 16 +#define RV_TIMER_CFG1_STEP_FIELD \ + ((bitfield_field32_t) { .mask = RV_TIMER_CFG1_STEP_MASK, .index = RV_TIMER_CFG1_STEP_OFFSET }) + +// Timer value Lower +#define RV_TIMER_TIMER_V_LOWER1_REG_OFFSET 0x204 + +// Timer value Upper +#define RV_TIMER_TIMER_V_UPPER1_REG_OFFSET 0x208 + +// Timer value Lower +#define RV_TIMER_COMPARE_LOWER1_0_REG_OFFSET 0x20c + +// Timer value Upper +#define RV_TIMER_COMPARE_UPPER1_0_REG_OFFSET 0x210 + +// Interrupt Enable (common parameters) +#define RV_TIMER_INTR_ENABLE1_IE_FIELD_WIDTH 1 +#define RV_TIMER_INTR_ENABLE1_IE_FIELDS_PER_REG 32 +#define RV_TIMER_INTR_ENABLE1_MULTIREG_COUNT 1 + +// Interrupt Enable +#define RV_TIMER_INTR_ENABLE1_REG_OFFSET 0x214 +#define RV_TIMER_INTR_ENABLE1_IE_0_BIT 0 + +// Interrupt Status (common parameters) +#define RV_TIMER_INTR_STATE1_IS_FIELD_WIDTH 1 +#define RV_TIMER_INTR_STATE1_IS_FIELDS_PER_REG 32 +#define RV_TIMER_INTR_STATE1_MULTIREG_COUNT 1 + +// Interrupt Status +#define RV_TIMER_INTR_STATE1_REG_OFFSET 0x218 +#define RV_TIMER_INTR_STATE1_IS_0_BIT 0 + +// Interrupt test register (common parameters) +#define RV_TIMER_INTR_TEST1_T_FIELD_WIDTH 1 +#define RV_TIMER_INTR_TEST1_T_FIELDS_PER_REG 32 +#define RV_TIMER_INTR_TEST1_MULTIREG_COUNT 1 + +// Interrupt test register +#define RV_TIMER_INTR_TEST1_REG_OFFSET 0x21c +#define RV_TIMER_INTR_TEST1_T_0_BIT 0 + #ifdef __cplusplus } // extern "C" #endif #endif // _RV_TIMER_REG_DEFS_ -// End generated register defines for rv_timer +// End generated register defines for rv_timer \ No newline at end of file diff --git a/sw/device/lib/runtime/core_v_mini_mcu.h.tpl b/sw/device/lib/runtime/core_v_mini_mcu.h.tpl index 13ea2e8ea..fb1cd23cc 100644 --- a/sw/device/lib/runtime/core_v_mini_mcu.h.tpl +++ b/sw/device/lib/runtime/core_v_mini_mcu.h.tpl @@ -9,6 +9,8 @@ extern "C" { #endif // __cplusplus +#define MEMORY_BANKS ${ram_numbanks} + #define DEBUG_START_ADDRESS 0x${debug_start_address} #define DEBUG_SIZE 0x${debug_size_address} #define DEBUG_END_ADDRESS (DEBUG_START_ADDRESS + DEBUG_SIZE) @@ -34,26 +36,34 @@ extern "C" { #define SPI_MEMIO_SIZE 0x${spi_memio_size_address} #define SPI_MEMIO_END_ADDRESS (SPI_MEMIO_START_ADDRESS + SPI_MEMIO_SIZE) +#define SPI_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${spi_start_offset}) +#define SPI_SIZE 0x${spi_size_address} +#define SPI_END_ADDRESS (SPI_START_ADDRESS + SPI_SIZE) + #define POWER_MANAGER_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${power_manager_start_offset}) #define POWER_MANAGER_SIZE 0x${power_manager_size_address} #define POWER_MANAGER_END_ADDRESS (POWER_MANAGER_START_ADDRESS + POWER_MANAGER_SIZE) -#define RV_TIMER_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${rv_timer_start_offset}) -#define RV_TIMER_SIZE 0x${rv_timer_size_address} -#define RV_TIMER_END_ADDRESS (RV_TIMER_START_ADDRESS + RV_TIMER_SIZE) +#define RV_TIMER_AO_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${rv_timer_ao_start_offset}) +#define RV_TIMER_AO_SIZE 0x${rv_timer_ao_size_address} +#define RV_TIMER_AO_END_ADDRESS (RV_TIMER_AO_START_ADDRESS + RV_TIMER_AO_SIZE) #define DMA_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${dma_start_offset}) #define DMA_SIZE 0x${dma_size_address} #define DMA_END_ADDRESS (DMA_START_ADDRESS + DMA_SIZE) +#define FAST_INTR_CTRL_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${fast_intr_ctrl_start_offset}) +#define FAST_INTR_CTRL_SIZE 0x${fast_intr_ctrl_size_address} +#define FAST_INTR_CTRL_END_ADDRESS (FAST_INTR_CTRL_START_ADDRESS + DMA_SIZE) + +#define EXT_PERIPHERAL_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${ext_periph_start_offset}) +#define EXT_PERIPHERAL_SIZE 0x${ext_periph_size_address} +#define EXT_PERIPHERAL_END_ADDRESS (EXT_PERIPHERAL_START_ADDRESS + EXT_PERIPHERAL_SIZE) + #define PAD_ATTRIBUTE_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${pad_attribute_start_offset}) #define PAD_ATTRIBUTE_SIZE 0x${pad_attribute_size_address} #define PAD_ATTRIBUTE_END_ADDRESS (PAD_ATTRIBUTE_START_ADDRESS + PAD_ATTRIBUTE_SIZE) -#define SPI_START_ADDRESS (AO_PERIPHERAL_START_ADDRESS + 0x${spi_start_offset}) -#define SPI_SIZE 0x${spi_size_address} -#define SPI_END_ADDRESS (SPI_START_ADDRESS + SPI_SIZE) - //switch-on/off peripherals #define PERIPHERAL_START_ADDRESS 0x${peripheral_start_address} #define PERIPHERAL_SIZE 0x${peripheral_size_address} @@ -75,9 +85,9 @@ extern "C" { #define I2C_SIZE 0x${i2c_size_address} #define I2C_END_ADDRESS (I2C_START_ADDRESS + I2C_SIZE) -#define EXT_PERIPHERAL_START_ADDRESS (PERIPHERAL_START_ADDRESS + 0x${ext_periph_start_offset}) -#define EXT_PERIPHERAL_SIZE 0x${ext_periph_size_address} -#define EXT_PERIPHERAL_END_ADDRESS (EXT_PERIPHERAL_START_ADDRESS + EXT_PERIPHERAL_SIZE) +#define RV_TIMER_START_ADDRESS (PERIPHERAL_START_ADDRESS + 0x${rv_timer_start_offset}) +#define RV_TIMER_SIZE 0x${rv_timer_size_address} +#define RV_TIMER_END_ADDRESS (RV_TIMER_START_ADDRESS + RV_TIMER_SIZE) #define EXT_SLAVE_START_ADDRESS 0x${ext_slave_start_address} #define EXT_SLAVE_SIZE 0x${ext_slave_size_address} @@ -96,14 +106,6 @@ extern "C" { #define UART_INTR_RX_BREAK_ERR ${uart_intr_rx_break_err} #define UART_INTR_RX_TIMEOUT ${uart_intr_rx_timeout} #define UART_INTR_RX_PARITY_ERR ${uart_intr_rx_parity_err} -#define GPIO_INTR_0 ${gpio_intr_0} -#define GPIO_INTR_1 ${gpio_intr_1} -#define GPIO_INTR_2 ${gpio_intr_2} -#define GPIO_INTR_3 ${gpio_intr_3} -#define GPIO_INTR_4 ${gpio_intr_4} -#define GPIO_INTR_5 ${gpio_intr_5} -#define GPIO_INTR_6 ${gpio_intr_6} -#define GPIO_INTR_7 ${gpio_intr_7} #define GPIO_INTR_8 ${gpio_intr_8} #define GPIO_INTR_9 ${gpio_intr_9} #define GPIO_INTR_10 ${gpio_intr_10} @@ -144,15 +146,21 @@ extern "C" { #define INTR_ACQ_OVERFLOW ${intr_acq_overflow} #define INTR_ACK_STOP ${intr_ack_stop} #define INTR_HOST_TIMEOUT ${intr_host_timeout} -#define DMA_INTR_DONE ${dma_intr_done} -#define SPI_FLASH_INTR_ERROR ${spi_flash_intr_error} -#define SPI_FLASH_INTR_EVENT ${spi_flash_intr_event} -#define SPI_INTR_ERROR ${spi_intr_error} -#define SPI_INTR_EVENT ${spi_intr_event} - -// Interrupt lines available for external interrupt sources #define EXT_INTR_0 ${ext_intr_0} #define EXT_INTR_1 ${ext_intr_1} +#define EXT_INTR_2 ${ext_intr_2} +#define EXT_INTR_3 ${ext_intr_3} +#define EXT_INTR_4 ${ext_intr_4} +#define EXT_INTR_5 ${ext_intr_5} +#define EXT_INTR_6 ${ext_intr_6} +#define EXT_INTR_7 ${ext_intr_7} +#define EXT_INTR_8 ${ext_intr_8} +#define EXT_INTR_9 ${ext_intr_9} +#define EXT_INTR_10 ${ext_intr_10} +#define EXT_INTR_11 ${ext_intr_11} +#define EXT_INTR_12 ${ext_intr_12} +#define EXT_INTR_13 ${ext_intr_13} +#define EXT_INTR_14 ${ext_intr_14} % for pad in pad_list: #define ${pad.localparam}_ATTRIBUTE ${pad.index} diff --git a/sw/device/lib/runtime/handler.c b/sw/device/lib/runtime/handler.c index 8ee1a0d81..6bc9785bd 100644 --- a/sw/device/lib/runtime/handler.c +++ b/sw/device/lib/runtime/handler.c @@ -82,6 +82,84 @@ __attribute__((weak)) void handler_irq_external(void) { } } +__attribute__((weak)) void handler_irq_fast_timer_1(void) { + printf("Fast timer 1 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_timer_2(void) { + printf("Fast timer 2 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_timer_3(void) { + printf("Fast timer 3 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_dma(void) { + printf("Fast dma IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_spi(void) { + printf("Fast spi IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_gpio_0(void) { + printf("Fast gpio 0 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_gpio_1(void) { + printf("Fast gpio 1 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_gpio_2(void) { + printf("Fast gpio 2 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_gpio_3(void) { + printf("Fast gpio 3 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_gpio_4(void) { + printf("Fast gpio 4 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_gpio_5(void) { + printf("Fast gpio 5 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_gpio_6(void) { + printf("Fast gpio 6 IRQ triggered!\n"); + while (1) { + } +} + +__attribute__((weak)) void handler_irq_fast_gpio_7(void) { + printf("Fast gpio 7 IRQ triggered!\n"); + while (1) { + } +} + __attribute__((weak)) void handler_instr_acc_fault(void) { const char fault_msg[] = "Instruction access fault, mtval shows fault address\n"; diff --git a/sw/device/lib/runtime/handler.h b/sw/device/lib/runtime/handler.h index 014b4d39c..c62399ecf 100644 --- a/sw/device/lib/runtime/handler.h +++ b/sw/device/lib/runtime/handler.h @@ -48,7 +48,7 @@ typedef enum exc_id { INTERRUPT_HANDLER_ABI void handler_exception(void); /** - * SW IRQ handler. + * Software IRQ handler. * * `handler.c` provides a weak definition of this symbol, which can be overriden * at link-time by providing an additional non-weak definition. @@ -64,13 +64,117 @@ INTERRUPT_HANDLER_ABI void handler_irq_software(void); INTERRUPT_HANDLER_ABI void handler_irq_timer(void); /** - * external IRQ handler. + * External IRQ handler. * * `handler.c` provides a weak definition of this symbol, which can be overriden * at link-time by providing an additional non-weak definition. */ INTERRUPT_HANDLER_ABI void handler_irq_external(void); +/** + * Fast timer 1 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_timer_1(void); + +/** + * Fast timer 2 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_timer_2(void); + +/** + * Fast timer 3 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_timer_3(void); + +/** + * Fast dma IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_dma(void); + +/** + * Fast spi IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_spi(void); + +/** + * Fast gpio 0 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_gpio_0(void); + +/** + * Fast gpio 1 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_gpio_1(void); + +/** + * Fast gpio 2 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_gpio_2(void); + +/** + * Fast gpio 3 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_gpio_3(void); + +/** + * Fast gpio 4 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_gpio_4(void); + +/** + * Fast gpio 5 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_gpio_5(void); + +/** + * Fast gpio 6 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_gpio_6(void); + +/** + * Fast gpio 7 IRQ handler. + * + * `handler.c` provides a weak definition of this symbol, which can be overriden + * at link-time by providing an additional non-weak definition. + */ +INTERRUPT_HANDLER_ABI void handler_irq_fast_gpio_7(void); + /** * Instruction access fault. * diff --git a/util/mcu_gen.py b/util/mcu_gen.py index f1859a6f3..4747254ae 100755 --- a/util/mcu_gen.py +++ b/util/mcu_gen.py @@ -25,7 +25,6 @@ def __init__(self, name, cell_name, pad_type, index): self.localparam = 'PAD_' + name.upper() self.pad_type = pad_type - self.interface = ' inout logic ' + self.name + '_io,\n' if pad_type == 'input': @@ -81,8 +80,6 @@ def __init__(self, name, cell_name, pad_type, index): ' .pad_attributes_i(pad_attributes_i[core_v_mini_mcu_pkg::' + self.localparam + '])\n' + \ ');\n\n' - - # Compile a regex to trim trailing whitespaces on lines. re_trailws = re.compile(r'[ \t\r]+$', re.MULTILINE) @@ -227,21 +224,27 @@ def main(): spi_memio_start_offset = string2int(obj['ao_peripherals']['spi_memio']['offset']) spi_memio_size_address = string2int(obj['ao_peripherals']['spi_memio']['length']) + spi_start_offset = string2int(obj['ao_peripherals']['spi']['offset']) + spi_size_address = string2int(obj['ao_peripherals']['spi']['length']) + power_manager_start_offset = string2int(obj['ao_peripherals']['power_manager']['offset']) power_manager_size_address = string2int(obj['ao_peripherals']['power_manager']['length']) - rv_timer_start_offset = string2int(obj['ao_peripherals']['rv_timer']['offset']) - rv_timer_size_address = string2int(obj['ao_peripherals']['rv_timer']['length']) + rv_timer_ao_start_offset = string2int(obj['ao_peripherals']['rv_timer_ao']['offset']) + rv_timer_ao_size_address = string2int(obj['ao_peripherals']['rv_timer_ao']['length']) dma_start_offset = string2int(obj['ao_peripherals']['dma']['offset']) dma_size_address = string2int(obj['ao_peripherals']['dma']['length']) + fast_intr_ctrl_start_offset = string2int(obj['ao_peripherals']['fast_intr_ctrl']['offset']) + fast_intr_ctrl_size_address = string2int(obj['ao_peripherals']['fast_intr_ctrl']['length']) + + ext_periph_start_offset = string2int(obj['ao_peripherals']['ext_periph']['offset']) + ext_periph_size_address = string2int(obj['ao_peripherals']['ext_periph']['length']) + pad_attribute_start_offset = string2int(obj['ao_peripherals']['pad']['offset']) pad_attribute_size_address = string2int(obj['ao_peripherals']['pad']['length']) - spi_start_offset = string2int(obj['ao_peripherals']['spi']['offset']) - spi_size_address = string2int(obj['ao_peripherals']['spi']['length']) - peripheral_start_address = string2int(obj['peripherals']['address']) if int(peripheral_start_address, 16) < int('10000', 16): exit("peripheral start address must be greater than 0x10000") @@ -260,8 +263,8 @@ def main(): i2c_start_offset = string2int(obj['peripherals']['i2c']['offset']) i2c_size_address = string2int(obj['peripherals']['i2c']['length']) - ext_periph_start_offset = string2int(obj['peripherals']['ext_periph']['offset']) - ext_periph_size_address = string2int(obj['peripherals']['ext_periph']['length']) + rv_timer_start_offset = string2int(obj['peripherals']['rv_timer']['offset']) + rv_timer_size_address = string2int(obj['peripherals']['rv_timer']['length']) ext_slave_start_address = string2int(obj['ext_slaves']['address']) ext_slave_size_address = string2int(obj['ext_slaves']['length']) @@ -284,7 +287,6 @@ def main(): if ((int(linker_onchip_data_size_address,16) + int(linker_onchip_code_size_address,16)) > int(ram_size_address,16)): exit("The code and data section must fit in the RAM size, instead they takes " + str(linker_onchip_data_size_address + linker_onchip_code_size_address)) - null_intr = obj['interrupts']['null_intr'] uart_intr_tx_watermark = obj['interrupts']['uart_intr_tx_watermark'] uart_intr_rx_watermark = obj['interrupts']['uart_intr_rx_watermark'] @@ -294,14 +296,6 @@ def main(): uart_intr_rx_break_err = obj['interrupts']['uart_intr_rx_break_err'] uart_intr_rx_timeout = obj['interrupts']['uart_intr_rx_timeout'] uart_intr_rx_parity_err = obj['interrupts']['uart_intr_rx_parity_err'] - gpio_intr_0 = obj['interrupts']['gpio_intr_0'] - gpio_intr_1 = obj['interrupts']['gpio_intr_1'] - gpio_intr_2 = obj['interrupts']['gpio_intr_2'] - gpio_intr_3 = obj['interrupts']['gpio_intr_3'] - gpio_intr_4 = obj['interrupts']['gpio_intr_4'] - gpio_intr_5 = obj['interrupts']['gpio_intr_5'] - gpio_intr_6 = obj['interrupts']['gpio_intr_6'] - gpio_intr_7 = obj['interrupts']['gpio_intr_7'] gpio_intr_8 = obj['interrupts']['gpio_intr_8'] gpio_intr_9 = obj['interrupts']['gpio_intr_9'] gpio_intr_10 = obj['interrupts']['gpio_intr_10'] @@ -342,32 +336,36 @@ def main(): intr_acq_overflow = obj['interrupts']['intr_acq_overflow'] intr_ack_stop = obj['interrupts']['intr_ack_stop'] intr_host_timeout = obj['interrupts']['intr_host_timeout'] - dma_intr_done = obj['interrupts']['dma_intr_done'] - spi_flash_intr_error = obj['interrupts']['spi_flash_intr_error'] - spi_flash_intr_event = obj['interrupts']['spi_flash_intr_event'] - spi_intr_error = obj['interrupts']['spi_intr_error'] - spi_intr_event = obj['interrupts']['spi_intr_event'] - # Interrupt lines available for external interrupt sources ext_intr_0 = obj['interrupts']['ext_intr_0'] ext_intr_1 = obj['interrupts']['ext_intr_1'] - - pads = obj['pads'] - - pad_list = [] + ext_intr_2 = obj['interrupts']['ext_intr_2'] + ext_intr_3 = obj['interrupts']['ext_intr_3'] + ext_intr_4 = obj['interrupts']['ext_intr_4'] + ext_intr_5 = obj['interrupts']['ext_intr_5'] + ext_intr_6 = obj['interrupts']['ext_intr_6'] + ext_intr_7 = obj['interrupts']['ext_intr_7'] + ext_intr_8 = obj['interrupts']['ext_intr_8'] + ext_intr_9 = obj['interrupts']['ext_intr_9'] + ext_intr_10 = obj['interrupts']['ext_intr_10'] + ext_intr_11 = obj['interrupts']['ext_intr_11'] + ext_intr_12 = obj['interrupts']['ext_intr_12'] + ext_intr_13 = obj['interrupts']['ext_intr_13'] + ext_intr_14 = obj['interrupts']['ext_intr_14'] + + pads = obj['pads'] + pad_list = [] pad_index_counter = 0 for key in pads: pad_name = key - pad_num = pads[key]['num'] + pad_num = pads[key]['num'] pad_type = pads[key]['type'] try: pad_offset = int(pads[key]['num_offset']) except KeyError: pad_offset = 0 - - if pad_num > 1: for p in range(pad_num): pad_cell_name = "pad_" + key + "_" + str(p+pad_offset) + "_i" @@ -382,7 +380,6 @@ def main(): num_internal_pad = pad_index_counter - kwargs = { "cpu_type" : cpu_type, "bus_type" : bus_type, @@ -403,10 +400,14 @@ def main(): "spi_memio_size_address" : spi_memio_size_address, "power_manager_start_offset" : power_manager_start_offset, "power_manager_size_address" : power_manager_size_address, - "rv_timer_start_offset" : rv_timer_start_offset, - "rv_timer_size_address" : rv_timer_size_address, + "rv_timer_ao_start_offset" : rv_timer_ao_start_offset, + "rv_timer_ao_size_address" : rv_timer_ao_size_address, "dma_start_offset" : dma_start_offset, "dma_size_address" : dma_size_address, + "fast_intr_ctrl_start_offset" : fast_intr_ctrl_start_offset, + "fast_intr_ctrl_size_address" : fast_intr_ctrl_size_address, + "ext_periph_start_offset" : ext_periph_start_offset, + "ext_periph_size_address" : ext_periph_size_address, "pad_attribute_start_offset" : pad_attribute_start_offset, "pad_attribute_size_address" : pad_attribute_size_address, "spi_start_offset" : spi_start_offset, @@ -421,8 +422,8 @@ def main(): "gpio_size_address" : gpio_size_address, "i2c_start_offset" : i2c_start_offset, "i2c_size_address" : i2c_size_address, - "ext_periph_start_offset" : ext_periph_start_offset, - "ext_periph_size_address" : ext_periph_size_address, + "rv_timer_start_offset" : rv_timer_start_offset, + "rv_timer_size_address" : rv_timer_size_address, "ext_slave_start_address" : ext_slave_start_address, "ext_slave_size_address" : ext_slave_size_address, "flash_mem_start_address" : flash_mem_start_address, @@ -440,14 +441,6 @@ def main(): "uart_intr_rx_break_err" : uart_intr_rx_break_err, "uart_intr_rx_timeout" : uart_intr_rx_timeout, "uart_intr_rx_parity_err" : uart_intr_rx_parity_err, - "gpio_intr_0" : gpio_intr_0, - "gpio_intr_1" : gpio_intr_1, - "gpio_intr_2" : gpio_intr_2, - "gpio_intr_3" : gpio_intr_3, - "gpio_intr_4" : gpio_intr_4, - "gpio_intr_5" : gpio_intr_5, - "gpio_intr_6" : gpio_intr_6, - "gpio_intr_7" : gpio_intr_7, "gpio_intr_8" : gpio_intr_8, "gpio_intr_9" : gpio_intr_9, "gpio_intr_10" : gpio_intr_10, @@ -488,13 +481,21 @@ def main(): "intr_acq_overflow" : intr_acq_overflow, "intr_ack_stop" : intr_ack_stop, "intr_host_timeout" : intr_host_timeout, - "dma_intr_done" : dma_intr_done, - "spi_flash_intr_error" : spi_flash_intr_error, - "spi_flash_intr_event" : spi_flash_intr_event, - "spi_intr_error" : spi_intr_error, - "spi_intr_event" : spi_intr_event, "ext_intr_0" : ext_intr_0, "ext_intr_1" : ext_intr_1, + "ext_intr_2" : ext_intr_2, + "ext_intr_3" : ext_intr_3, + "ext_intr_4" : ext_intr_4, + "ext_intr_5" : ext_intr_5, + "ext_intr_6" : ext_intr_6, + "ext_intr_7" : ext_intr_7, + "ext_intr_8" : ext_intr_8, + "ext_intr_9" : ext_intr_9, + "ext_intr_10" : ext_intr_10, + "ext_intr_11" : ext_intr_11, + "ext_intr_12" : ext_intr_12, + "ext_intr_13" : ext_intr_13, + "ext_intr_14" : ext_intr_14, "pad_list" : pad_list, "num_internal_pad" : num_internal_pad, }