diff --git a/Bender.lock b/Bender.lock index 6b6a9713..fc41a889 100644 --- a/Bender.lock +++ b/Bender.lock @@ -126,7 +126,7 @@ packages: - register_interface - tech_cells_generic cheshire: - revision: 9f0234c1a40cd332f2b502cbbb5f98bd242b29ba + revision: 3b773c80985294375421c8f8ad57c009c74b3d46 version: null source: Git: https://github.com/pulp-platform/cheshire.git @@ -136,11 +136,13 @@ packages: - axi_llc - axi_riscv_atomics - axi_vga + - clic - clint - common_cells - common_verification - cva6 - idma + - irq_router - opentitan_peripherals - register_interface - riscv-dbg @@ -149,7 +151,7 @@ packages: revision: bed98f88761ca86706c36c4c33ac600d88c42373 version: null source: - Git: https://github.com/pulp-platform/clic.git + Git: https://github.com/pulp-platform/clic dependencies: - common_cells - register_interface @@ -306,6 +308,15 @@ packages: - common_cells - common_verification - register_interface + irq_router: + revision: d1d31350b24f3965b3a51e1bc96c71eb34e94db3 + version: null + source: + Git: https://github.com/pulp-platform/irq_router + dependencies: + - axi + - common_cells + - register_interface l2_tcdm_hybrid_interco: revision: fa55e72859dcfb117a2788a77352193bef94ff2b version: 1.0.0 diff --git a/Bender.yml b/Bender.yml index 0f997a30..5ad9d03f 100644 --- a/Bender.yml +++ b/Bender.yml @@ -12,7 +12,7 @@ package: dependencies: register_interface: { git: https://github.com/pulp-platform/register_interface.git, rev: 2bb08879bc2ceabe2b6a0dc283753048a739e27b } # branch: main until newer version tag later than v0.4.0 axi: { git: https://github.com/pulp-platform/axi.git, version: 0.39.0-beta.9 } # overridden in Bender.local to use axi-rt feature - cheshire: { git: https://github.com/pulp-platform/cheshire.git, rev: 9f0234c1a40cd332f2b502cbbb5f98bd242b29ba } # branch: main + cheshire: { git: https://github.com/pulp-platform/cheshire.git, rev: 3b773c80985294375421c8f8ad57c009c74b3d46 } # branch: aottaviano/cva6-clic hyperbus: { git: https://github.com/pulp-platform/hyperbus.git, rev: 2adb7271438cdb96c19fbaf3e2a6bf89ffeee568 } # branch: lv/phys_in_use car_l2: { git: git@iis-git.ee.ethz.ch:carfield/carfield_l2_mem.git, rev: 08503a05307ef556ed5439619c70c039ff93d77a } # branch: main safety_island: { git: git@iis-git.ee.ethz.ch:carfield/safety-island.git, rev: 60e768a3ef29f47339e31674d497293f5a768893 } # branch: atops diff --git a/carfield.mk b/carfield.mk index 958a0c12..8a1548f9 100644 --- a/carfield.mk +++ b/carfield.mk @@ -17,6 +17,13 @@ TBENCH ?= tb_carfield_soc BOOTMODE ?= 0 # default passive bootmode PRELMODE ?= 1 # default serial link preload VOPTARGS ?= +# Interrupt configuration in cheshire +# CLINT interruptible harts +CLINTCORES := 3 +# PLIC interruptible harts +PLICCORES := 6 +# PLIC number of input interrupts +PLIC_NUM_INTRS := 128 # Include cheshire's makefrag only if the dependency was cloned -include $(CHS_ROOT)/cheshire.mk @@ -100,6 +107,18 @@ hw/regs/carfield_reg_pkg.sv hw/regs/carfield_reg_top.sv: hw/regs/carfield_regs.h ## not forget to check in the generated RTL. regenerate_soc_regs: hw/regs/carfield_reg_pkg.sv hw/regs/carfield_reg_top.sv +## @section Carfield CLINT and PLIC interruptible harts configuration + +## The default configuration in cheshire allows for one interruptible hart. When the number of +## external interruptible harts is updated in the cheshire cfg (cheshire_pkg.sv), we need to +## regenerate the PLIC and CLINT accordingly. +## CLINT: define CLINTCORES used in cheshire.mk before including the makefrag. +## PLIC: edit the hjson configuration file in cheshire. +.PHONY: update_plic +update_plic: $(CHS_ROOT)/hw/rv_plic.cfg.hjson + sed -i 's/src: .*/src: $(PLIC_NUM_INTRS),/' $< + sed -i 's/target: .*/target: $(PLICCORES),/' $< + $(CAR_ROOT)/tb/hyp_vip: rm -rf $@ mkdir $@ @@ -164,7 +183,11 @@ car-checkout-deps: .PHONY: car-checkout car-checkout: car-checkout-deps +## @section Carfield initialization .PHONY: car-hw-init +## Initialize carfield by generating cheshire and spatz registers and wrapper, respectively +## This step takes care of the generation of the missing hardware, or an update of the configuration +## of some IPs, such as the PLIC or CLINT. car-hw-init: spatz-hw-init chs-hw-init .PHONY: spatz-hw-init @@ -172,22 +195,29 @@ spatz-hw-init: $(MAKE) -C $(SPATZ_MAKEDIR) -B SPATZ_CLUSTER_CFG=carfield.hjson bootrom .PHONY: chs-hw-init -chs-hw-init: +## This target has a prerequisite, i.e. the PLIC configuration must be chosen before generating the +## hardware. +chs-hw-init: update_plic $(MAKE) chs-hw-all .PHONY: chs-sim-init +## Downloads verification IPs for SPI and I2C from cheshire and used by Carfield. chs-sim-init: $(MAKE) chs-sim-all .PHONY: chs-sw-build +## Builds the SW libraries in cheshire and generates an archive (`libcheshire.a`) available for +## carfield as static library at link time. chs-sw-build: $(MAKE) chs-sw-all .PHONY: car-sw-build +## Builds carfield application SW and specific libraries. It links against `libcheshire.a`. car-sw-build: chs-sw-build $(MAKE) car-sw-all .PHONY: car-init +## Shortcut to initialize carfield with all the targets described above. car-init: car-checkout car-hw-init car-sim-init car-sw-build ############ diff --git a/hw/carfield.sv b/hw/carfield.sv index bacde009..2f521a83 100644 --- a/hw/carfield.sv +++ b/hw/carfield.sv @@ -148,23 +148,115 @@ module carfield **********************************/ `CHESHIRE_TYPEDEF_ALL(carfield_, Cfg) -// Mailbox unit +// Clocking and reset strategy +logic periph_rst_n; +logic safety_rst_n; +logic security_rst_n; +logic pulp_rst_n; +logic spatz_rst_n; +logic l2_rst_n; + +logic host_pwr_on_rst_n; +logic periph_pwr_on_rst_n; +logic safety_pwr_on_rst_n; +logic security_pwr_on_rst_n; +logic pulp_pwr_on_rst_n; +logic spatz_pwr_on_rst_n; +logic l2_pwr_on_rst_n; + +logic periph_clk; +logic safety_clk; +logic security_clk; +logic pulp_clk; +logic spatz_clk; +logic l2_clk; // verilog_lint: waive-start line-length +// Peripheral interrupts +logic [(Cfg.NumExtRouterTargets*(CarfieldNumExtIntrs+NumIntIntrs))-1:0] chs_intrs_distributed; +logic [Cfg.NumExtIrqHarts-1:0] chs_mti; +logic [CarfieldNumPeriphsIntrs-1:0] car_periph_intrs; + +logic car_sys_timer_lo_intr, car_sys_timer_hi_intr, car_sys_timer_lo_intr_sync, car_sys_timer_hi_intr_sync; +logic [3:0] car_adv_timer_intrs, car_adv_timer_events, car_adv_timer_intrs_sync, car_adv_timer_events_sync; +logic [4:0] car_wdt_intrs; +logic car_can_intr; + +// Carfield peripheral interrupts +// Propagate edge-triggered interrupts between periph and host clock domains + +// Advanced timer +for (genvar i=0; i < 3; i++) begin : gen_sync_adv_timer_intrs + edge_propagator i_sync_adv_timer_intrs ( + .clk_tx_i ( periph_clk ), + .rstn_tx_i ( periph_rst_n ), + .edge_i ( car_adv_timer_intrs[i] ), + .clk_rx_i ( host_clk ), + .rstn_rx_i ( host_pwr_on_rst_n ), + .edge_o ( car_adv_timer_intrs_sync[i] ) + ); +end + +for (genvar i=0; i < 3; i++) begin : gen_sync_adv_timer_events + edge_propagator i_sync_adv_timer_events ( + .clk_tx_i ( periph_clk ), + .rstn_tx_i ( periph_rst_n ), + .edge_i ( car_adv_timer_events[i] ), + .clk_rx_i ( host_clk ), + .rstn_rx_i ( host_pwr_on_rst_n ), + .edge_o ( car_adv_timer_events_sync[i] ) + ); +end + +// System timer +edge_propagator i_sync_sys_timer_lo_intr ( + .clk_tx_i ( periph_clk ), + .rstn_tx_i ( periph_rst_n ), + .edge_i ( car_sys_timer_lo_intr ), + .clk_rx_i ( host_clk ), + .rstn_rx_i ( host_pwr_on_rst_n ), + .edge_o ( car_sys_timer_lo_intr_sync ) +); + +edge_propagator i_sync_sys_timer_hi_intr ( + .clk_tx_i ( periph_clk ), + .rstn_tx_i ( periph_rst_n ), + .edge_i ( car_sys_timer_hi_intr ), + .clk_rx_i ( host_clk ), + .rstn_rx_i ( host_pwr_on_rst_n ), + .edge_o ( car_sys_timer_hi_intr_sync ) +); + +// Collect carfield peripheral interrupts to feed cheshire in the host domain +assign car_periph_intrs = { + car_sys_timer_hi_intr_sync, // 1 + car_sys_timer_lo_intr_sync, // 1 + car_adv_timer_events_sync, // 4 + car_adv_timer_intrs_sync, // 4 + car_can_intr, // 1 + car_wdt_intrs // 5 +}; + +// Mailbox unit + localparam int unsigned CheshireNumIntHarts = 1 + Cfg.DualCore; -localparam int unsigned SafedNumIntHarts = 1; -localparam int unsigned SecdNumIntHarts = 1; -localparam int unsigned IntClusterNumIrq = 1; -localparam int unsigned FPClusterNumIrq = 1; +localparam int unsigned SafedNumIntHarts = 1; +localparam int unsigned SecdNumIntHarts = 1; + +// TODO: Comment these constants: the name is not clear, I personally prefer to have raw numbers +//localparam int unsigned IntClusterNumIrq = 1; +//localparam int unsigned FPClusterNumIrq = 1; // Number of receiving side mailboxes per subsystem -localparam int unsigned MailboxesHostd = 4 * CheshireNumIntHarts; -localparam int unsigned MailboxesFPCluster = - spatz_cluster_pkg::NumCores * (CheshireNumIntHarts + SafedNumIntHarts); -localparam int unsigned MailboxesIntCluster = CheshireNumIntHarts + SafedNumIntHarts; -localparam int unsigned MailboxesSafed = CheshireNumIntHarts + SecdNumIntHarts + IntClusterNumIrq + FPClusterNumIrq; -localparam int unsigned MailboxesSecd = CheshireNumIntHarts + SafedNumIntHarts; -localparam int unsigned NumMailboxes = MailboxesHostd + MailboxesFPCluster + MailboxesIntCluster + MailboxesSafed + MailboxesSecd; +// For Cheshire, 4 mailboxes for each application class processor +localparam int unsigned NumMailboxesHostd = 4 * CheshireNumIntHarts; +localparam int unsigned NumMailboxesFPCluster = spatz_cluster_pkg::NumCores * (CheshireNumIntHarts + SafedNumIntHarts); +localparam int unsigned NumMailboxesIntCluster = CheshireNumIntHarts + SafedNumIntHarts; +// For the safety island, consider host domain and security island, and one callback SW interrupt +// from integer and floating point clusters +localparam int unsigned NumMailboxesSafed = CheshireNumIntHarts + SecdNumIntHarts + 1 + 1; //+ IntClusterNumIrq + FPClusterNumIrq; +localparam int unsigned NumMailboxesSecd = CheshireNumIntHarts + SafedNumIntHarts; +localparam int unsigned NumMailboxes = NumMailboxesHostd + NumMailboxesFPCluster + NumMailboxesIntCluster + NumMailboxesSafed + NumMailboxesSecd; // verilog_lint: waive-stop line-length // Interrupt lines @@ -430,30 +522,6 @@ carfield_hw2reg_t car_regs_hw2reg; // spatz_cluster (sw reset 4) // shared_l2_memory (sw reset 5) -logic periph_rst_n; -logic safety_rst_n; -logic security_rst_n; -logic pulp_rst_n; -logic spatz_rst_n; -logic l2_rst_n; - -logic host_pwr_on_rst_n; -logic periph_pwr_on_rst_n; -logic safety_pwr_on_rst_n; -logic security_pwr_on_rst_n; -logic pulp_pwr_on_rst_n; -logic spatz_pwr_on_rst_n; -logic l2_pwr_on_rst_n; - -logic periph_clk; -logic safety_clk; -logic security_clk; -logic pulp_clk; -logic spatz_clk; -logic l2_clk; - - - // Clock Multiplexing for each sub block localparam int unsigned DomainClkDivValueWidth = 24; typedef logic [DomainClkDivValueWidth-1:0] domain_clk_div_value_t; @@ -739,14 +807,37 @@ carfield_a32_d32_reg_rsp_t reg_wdt_rsp; carfield_axi_slv_req_t axi_mbox_req; carfield_axi_slv_rsp_t axi_mbox_rsp; -/*************** -* Carfield IPs * -***************/ +////////////////// +// Carfield IPs // +////////////////// + // Cheshire SoC // Host Clock Domain + +// Interrupts +logic [CarfieldNumExtIntrs-1:0] chs_ext_intrs; +logic [IntClusterNumEoc-1:0] pulpcl_eoc; + +// Edge-triggered interrupts from a different clock domain than cheshire (host clock domain) have +// been synchronized already. Synchronization of level-sensitive interrupts is handled within the +// module, before or inside the interrupt controller. +assign chs_ext_intrs = { + // tie unused to 0 + {(CarfieldNumExtIntrs-21){1'b0}}, + // System peripherals + car_periph_intrs, // 16 + // Mailboxes + secd_hostd_mbox_intr, // 1 + safed_hostd_mbox_intr, // 1 + spatzcl_hostd_mbox_intr, // 1 + pulpcl_hostd_mbox_intr, // 1 + pulpcl_eoc // from integer cluster +}; + cheshire_wrap #( .Cfg ( Cfg ), .ExtHartinfo ( '0 ), + .NumExtIntrs ( CarfieldNumExtIntrs ), .cheshire_axi_ext_llc_ar_chan_t ( carfield_axi_llc_ar_chan_t ), .cheshire_axi_ext_llc_aw_chan_t ( carfield_axi_llc_aw_chan_t ), .cheshire_axi_ext_llc_b_chan_t ( carfield_axi_llc_b_chan_t ), @@ -891,12 +982,13 @@ cheshire_wrap #( .ext_reg_async_slv_ack_o, .ext_reg_async_slv_data_i, // Interrupts from external devices - .intr_ext_i ( /* TODO: connect me */ ), + .intr_ext_i ( chs_ext_intrs ), // Interrupts to external harts - .meip_ext_o ( /* TODO: connect me */ ), - .seip_ext_o ( /* Unused */ ), // Unused - .mtip_ext_o ( /* TODO: connect me */ ), + .meip_ext_o ( /* Unused */ ), + .seip_ext_o ( /* Unused */ ), + .mtip_ext_o ( chs_mti ), .msip_ext_o ( /* Unused */ ), // We use mailboxes for this + .intr_distributed_o ( chs_intrs_distributed ), // Debug interface to external harts .dbg_active_o ( ), .dbg_ext_req_o ( ), @@ -1068,13 +1160,52 @@ l2_wrap #( // Safety Island logic [SafetyIslandCfg.NumInterrupts-1:0] safed_intrs; -assign safed_intrs = { - 59'h0, - spatzcl_safed_mbox_intr, // from spatzcl - pulpcl_safed_mbox_intr, // from pulpcl - secd_safed_mbox_intr, // from secd - hostd_safed_mbox_intr // from hostd +// Safety island interrupts from interrupt router +logic [(NumIntIntrs+CarfieldNumExtIntrs)-1:0] safed_intrs_distributed; +// Safety island edge-triggered interrupts and synchronized edge-triggered interrupts +logic [CarfieldNumTimerIntrs-1:0] safed_edge_triggered_intrs, safed_edge_triggered_intrs_sync; +// Safety island is the only external target for the router in carfield +assign safed_intrs_distributed = chs_intrs_distributed[(NumIntIntrs+CarfieldNumExtIntrs)-1:0]; + +// verilog_lint: waive-start line-length +localparam int unsigned EdgeTriggeredIntrsOffset = NumIntIntrs+IntClusterNumEoc+NumMailboxesHostd+ + CarfieldNumPeriphsIntrs-CarfieldNumTimerIntrs; +assign safed_edge_triggered_intrs = safed_intrs_distributed[ + EdgeTriggeredIntrsOffset+CarfieldNumTimerIntrs-1: + EdgeTriggeredIntrsOffset]; + +// Propagate edge-triggered interrupts between host and safety_island clock domains. In carfield, +// edge-triggered interrupts come from the system timer peripherals (`CarfieldNumTimerIntrs` +// interrupt lines, see `carfield_pkg.sv`). Other interrupt lines are level-triggered. +for (genvar i = 0; i < CarfieldNumTimerIntrs; i++) begin : gen_sync_safed_edge_triggered_intrs + edge_propagator i_sync_safed_edge_triggered_intrs ( + .clk_tx_i ( host_clk ), + .rstn_tx_i ( host_rst_n ), + .edge_i ( safed_edge_triggered_intrs[i] ), + .clk_rx_i ( safety_clk ), + .rstn_rx_i ( safety_pwr_on_rst_n ), + .edge_o ( safed_edge_triggered_intrs_sync[i] ) + ); +end + +// Collect interrupts for the safety island: private interrupts from mailboxes, shared interrupts +// from the interrupt router. +// verilog_lint: waive-start line-length +assign safed_intrs = { + {(SafetyIslandCfg.NumInterrupts-(NumIntIntrs+CarfieldNumExtIntrs+NumMailboxesSafed)){1'b0}}, // Pad remaining interrupts + // Shared interrupts (cheshire and carfield's peripherals interrupts) + safed_intrs_distributed[(NumIntIntrs+CarfieldNumExtIntrs)-1:(EdgeTriggeredIntrsOffset+CarfieldNumTimerIntrs)], // Others up to CarfieldNumExtIntrs + safed_edge_triggered_intrs_sync, // Timer interrupts + safed_intrs_distributed[EdgeTriggeredIntrsOffset-1:(NumIntIntrs+IntClusterNumEoc+NumMailboxesHostd)], // CAN, WDT interrupts + {(NumMailboxesHostd){1'b0}}, // Do not connect cheshire's mailbox interrupts + safed_intrs_distributed[(NumIntIntrs+IntClusterNumEoc)-1:0], // cheshire's peripherals, pulp cluster EOC + // Mailboxes + spatzcl_safed_mbox_intr, // 1 + pulpcl_safed_mbox_intr, // 1 + secd_safed_mbox_intr, // 1 + hostd_safed_mbox_intr // 1 }; +// verilog_lint: waive-stop line-length safety_island_synth_wrapper #( .SafetyIslandCfg ( SafetyIslandCfg ), @@ -1117,12 +1248,12 @@ safety_island_synth_wrapper #( .ref_clk_i ( rt_clk_i ), .rst_ni ( safety_rst_n ), .pwr_on_rst_ni ( safety_pwr_on_rst_n ), - .test_enable_i ( '0 ), + .test_enable_i ( test_mode_i ), .bootmode_i ( bootmode_safe_isln_i ), .fetch_en_i ( car_regs_reg2hw.safety_island_fetch_enable ), // To SoC Bus .axi_isolate_i ( slave_isolate_req [SafetyIslandSlvIdx] ), // To SoC Bus .axi_isolated_o ( master_isolated_rsp [SafetyIslandMstIdx] ), - .irqs_i ( '0 ), + .irqs_i ( safed_intrs ), .debug_req_o ( ), .jtag_tck_i ( jtag_safety_island_tck_i ), .jtag_trst_ni ( jtag_safety_island_trst_ni ), @@ -1168,6 +1299,7 @@ safety_island_synth_wrapper #( logic pulpcl_mbox_intr; assign car_regs_hw2reg.pulp_cluster_eoc.de = 1'b1; assign car_regs_hw2reg.pulp_cluster_busy.de = 1'b1; +assign car_regs_hw2reg.pulp_cluster_eoc.d = pulpcl_eoc; pulp_cluster #( .NB_CORES ( IntClusterNumCores ), @@ -1220,7 +1352,7 @@ pulp_cluster #( .cluster_id_i ( IntClusterIndex ), .en_sa_boot_i ( car_regs_reg2hw.pulp_cluster_boot_enable ), .fetch_en_i ( car_regs_reg2hw.pulp_cluster_fetch_enable ), - .eoc_o ( car_regs_hw2reg.pulp_cluster_eoc.d ), + .eoc_o ( pulpcl_eoc ), .busy_o ( car_regs_hw2reg.pulp_cluster_busy.d ), .axi_isolate_i ( slave_isolate_req [IntClusterSlvIdx] ), .axi_isolated_o ( master_isolated_rsp [IntClusterMstIdx] ), @@ -1272,13 +1404,18 @@ pulp_cluster #( // Floating Point Spatz Cluster // Spatz cluster interrupts -logic [spatz_cluster_pkg::NumCores-1:0] spatzcl_mbox_intr, spatz_cl_mti; +// msi (machine software interrupt): hostd, safed +logic [spatz_cluster_pkg::NumCores-1:0] spatzcl_mbox_intr; +// mti (machine timer interrupt) : hostd (RISC-V clint) +// verilog_lint: waive-start line-length +logic [spatz_cluster_pkg::NumCores-1:0] spatzcl_timer_intr = { chs_mti[FPClusterIntrHart1Idx], chs_mti[FPClusterIntrHart0Idx] }; +// verilog_lint: waive-stop line-length spatz_cluster_wrapper #( .AxiAddrWidth ( Cfg.AddrWidth ), .AxiDataWidth ( Cfg.AxiDataWidth ), .AxiUserWidth ( Cfg.AxiUserWidth ), - .AxiInIdWidth ( AxiSlvIdWidth ), + .AxiInIdWidth ( AxiSlvIdWidth ), .AxiOutIdWidth ( Cfg.AxiMstIdWidth ), .LogDepth ( LogDepth ), @@ -1317,14 +1454,14 @@ spatz_cluster_wrapper #( .clk_i ( spatz_clk ), .rst_ni ( spatz_rst_n ), .pwr_on_rst_ni ( spatz_pwr_on_rst_n ), - .testmode_i ( 1'b0 ), // TODO: connect + .testmode_i ( test_mode_i ), .scan_enable_i ( 1'b0 ), .scan_data_i ( 1'b0 ), .scan_data_o ( /* Unused */ ), - .meip_i ( '0 /* TODO: connect me */ ), // Needed? + .meip_i ( '0 /* Unconnected */ ), .msip_i ( spatzcl_mbox_intr ), - .mtip_i ( '0 /* TODO: connect me */ ), // from hostd - .debug_req_i ( '0 ), + .mtip_i ( spatzcl_timer_intr ), + .debug_req_i ( '0 /* TODO: connect me */ ), //AXI Isolate .axi_isolate_i ( slave_isolate_req [FPClusterSlvIdx] ), .axi_isolated_o ( master_isolated_rsp [FPClusterMstIdx] ), @@ -1402,7 +1539,7 @@ secure_subsystem_synth_wrap #( .pwr_on_rst_ni ( security_pwr_on_rst_n ), .fetch_en_i ( car_regs_reg2hw.security_island_fetch_enable ), .bootmode_i ( '0 ), - .test_enable_i ( '0 ), + .test_enable_i ( test_mode_i ), .irq_ibex_i ( secd_mbox_intr ), // from hostd or safed // JTAG port .jtag_tck_i ( jtag_ot_tck_i ), @@ -1502,7 +1639,7 @@ axi_to_axi_lite #( ) i_axi_to_axi_lite_mailbox ( .clk_i ( host_clk_i ), .rst_ni ( host_pwr_on_rst_n ), - .test_i ( '0 ), + .test_i ( test_mode_i ), .slv_req_i ( axi_d32_mbox_req ), .slv_resp_o( axi_d32_mbox_rsp ), .mst_req_o ( axi_lite_d32_mbox_req ), @@ -1905,8 +2042,8 @@ apb_timer_unit #( .ref_clk_i ( rt_clk_i ), .event_lo_i ( '0 ), .event_hi_i ( '0 ), - .irq_lo_o ( /* TODO connect me */ ), - .irq_hi_o ( /* TODO connect me */ ), + .irq_lo_o ( car_sys_timer_lo_intr ), + .irq_hi_o ( car_sys_timer_hi_intr ), .busy_o ( /* TODO connect me */ ) ); @@ -1927,12 +2064,12 @@ apb_adv_timer #( .PREADY ( apb_mst_rsp[AdvancedTimerIdx].pready ), .PSLVERR ( apb_mst_rsp[AdvancedTimerIdx].pslverr ), .low_speed_clk_i ( rt_clk_i ), - .ext_sig_i ( /* TODO connect me */ ), - .events_o ( /* TODO connect me */ ), - .ch_0_o ( /* TODO connect me */ ), - .ch_1_o ( /* TODO connect me */ ), - .ch_2_o ( /* TODO connect me */ ), - .ch_3_o ( /* TODO connect me */ ) + .ext_sig_i ( '0 /* TODO connect me */ ), + .events_o ( car_adv_timer_events ), + .ch_0_o ( car_adv_timer_intrs ), + .ch_1_o ( ), + .ch_2_o ( ), + .ch_3_o ( ) ); // Watchdog timer @@ -1995,14 +2132,14 @@ aon_timer i_watchdog_timer ( .rst_aon_ni ( periph_pwr_on_rst_n ), .tl_i ( tl_wdt_req ), .tl_o ( tl_wdt_rsp ), - .alert_rx_i ( '0 ), + .alert_rx_i ( '0 ), // TODO: what are these for? .alert_tx_o ( /* TODO connect me */ ), .lc_escalate_en_i ( '0 ), - .intr_wkup_timer_expired_o ( /* TODO connect me */ ), - .intr_wdog_timer_bark_o ( /* TODO connect me */ ), - .nmi_wdog_timer_bark_o ( /* TODO connect me */ ), - .wkup_req_o ( /* TODO connect me */ ), - .aon_timer_rst_req_o ( /* TODO connect me */ ), + .intr_wkup_timer_expired_o ( car_wdt_intrs[0] ), + .intr_wdog_timer_bark_o ( car_wdt_intrs[1] ), + .nmi_wdog_timer_bark_o ( car_wdt_intrs[2] ), + .wkup_req_o ( car_wdt_intrs[3] ), + .aon_timer_rst_req_o ( car_wdt_intrs[4] ), .sleep_mode_i ( '0 ) ); @@ -2048,7 +2185,7 @@ can_top_apb #( .arstn ( periph_pwr_on_rst_n ), .scan_enable ( 1'b0 ), .res_n_out ( ), - .irq ( /* TODO connect me */ ), + .irq ( car_can_intr ), .CAN_tx ( can_tx_o ), .CAN_rx ( can_rx_i ), .timestamp ( can_timestamp ), @@ -2065,5 +2202,3 @@ can_top_apb #( ); endmodule - - diff --git a/hw/carfield_pkg.sv b/hw/carfield_pkg.sv index 004c6e10..78552f3b 100644 --- a/hw/carfield_pkg.sv +++ b/hw/carfield_pkg.sv @@ -14,6 +14,16 @@ package carfield_pkg; import cheshire_pkg::*; import safety_island_pkg::*; +localparam int unsigned CarfieldNumExtIntrs = 32; // Number of external interrupts +localparam int unsigned CarfieldNumInterruptibleHarts = 2; // Spatz (2 Snitch cores) +localparam int unsigned CarfieldNumRouterTargets = 1; // Safety Island + +typedef enum int { + FPClusterIntrHart0Idx = 'd0, + FPClusterIntrHart1Idx = 'd1, + SafedIntrHartIdx = 'd2 +} carfield_ext_intr_harts_e; + typedef enum int { PeriphDomainIdx = 'd0, SafedDomainIdx = 'd1, @@ -73,6 +83,13 @@ typedef enum doub_bt { } axi_end_t; // APB peripherals +localparam int unsigned CarfieldNumTimerIntrs = 10; // 4 adv timer intrs, 4 adv timer events, 2 sys + // timer intrs +localparam int unsigned CarfieldNumWdtIntrs = 5; +localparam int unsigned CarfieldNumCanIntrs = 1; +localparam int unsigned CarfieldNumPeriphsIntrs = CarfieldNumTimerIntrs + + CarfieldNumWdtIntrs + CarfieldNumCanIntrs; + localparam int unsigned NumApbMst = 5; typedef enum int { @@ -134,8 +151,6 @@ typedef enum doub_bt { localparam bit [3:0] AxiNumExtSlv = 3'd2 + 3'd1 + 3'd1 + 3'd1 + 3'd1 + 3'd1 + 3'd1; // Ext Masters: Integer Cluster + Security Island + Safety Island + Floating Point Cluster localparam bit [2:0] AxiNumExtMst = 3'd1 + 3'd1 + 3'd1 + 3'd1; -// Ext Interrupts: Security Island Mailbox -localparam bit [2:0] NumExtIntrs = 3'd1; // Safety island configuration localparam safety_island_cfg_t SafetyIslandCfg = '{ @@ -158,7 +173,7 @@ localparam safety_island_cfg_t SafetyIslandCfg = '{ UseXPulp: 1, UseZfinx: 1, UseTCLS: 1, - NumInterrupts: 64, + NumInterrupts: 128, NumMhpmCounters: 1, // All non-set values should be zero default: '0 @@ -170,6 +185,8 @@ localparam cheshire_cfg_t CarfieldCfgDefault = '{ Cva6RASDepth : ariane_pkg::ArianeDefaultConfig.RASDepth, Cva6BTBEntries : ariane_pkg::ArianeDefaultConfig.BTBEntries, Cva6BHTEntries : ariane_pkg::ArianeDefaultConfig.BHTEntries, + Cva6CLICNumInterruptSrc : 128, + Cva6CLICIntCtlBits : ariane_pkg::ArianeDefaultConfig.CLICIntCtlBits, Cva6NrPMPEntries : 0, Cva6ExtCieLength : 'h1000_0000, // [0x2000_0000, 0x7000_0000) is non-CIE, // [0x7000_0000, 0x8000_0000) is CIE @@ -178,6 +195,9 @@ localparam cheshire_cfg_t CarfieldCfgDefault = '{ DualCore : 0, // Only one core, but rest of config allows for two CoreMaxTxns : 8, CoreMaxTxnsPerId : 4, + // External interrupts + NumExtIrqHarts : CarfieldNumInterruptibleHarts, + NumExtRouterTargets : CarfieldNumRouterTargets, // Interconnect AddrWidth : 48, AxiDataWidth : 64, @@ -230,8 +250,6 @@ localparam cheshire_cfg_t CarfieldCfgDefault = '{ RegExtRegionEnd : '{ 0, 0, 0, 0, 0, PadframeEnd, PllEnd, CarRegsEnd }, // RTC RtcFreq : 32768, - // Ext Irq - NumExtIntrs : NumExtIntrs, // Features Bootrom : 1, Uart : 1, @@ -242,6 +260,8 @@ localparam cheshire_cfg_t CarfieldCfgDefault = '{ SerialLink : 1, Vga : 1, AxiRt : 1, + Clic : 1, + IrqRouter : 1, // Debug DbgIdCode : CheshireIdCode, DbgMaxReqs : 4, @@ -343,6 +363,7 @@ localparam int unsigned IntClusterAxiIdOutWidth = IntClusterAxiIdInWidth + $clog2(IntClusterNumAxiSlv); localparam int unsigned IntClusterMaxUniqId = 1; localparam logic [ 5:0] IntClusterIndex = '0; +localparam int unsigned IntClusterNumEoc = 1; /*******************************/ /* Narrow Parameters: A32, D32 */ diff --git a/hw/cheshire_wrap.sv b/hw/cheshire_wrap.sv index dfb70627..269bc83c 100644 --- a/hw/cheshire_wrap.sv +++ b/hw/cheshire_wrap.sv @@ -17,6 +17,7 @@ module cheshire_wrap #( parameter cheshire_cfg_t Cfg = '0, parameter dm::hartinfo_t [iomsb(Cfg.NumExtDbgHarts)-1:0] ExtHartinfo = '0, + parameter int unsigned NumExtIntrs = 32, parameter type cheshire_axi_ext_llc_ar_chan_t = logic, parameter type cheshire_axi_ext_llc_aw_chan_t = logic, parameter type cheshire_axi_ext_llc_b_chan_t = logic, @@ -262,12 +263,13 @@ module cheshire_wrap output logic [1:0] ext_reg_async_slv_ack_o, input cheshire_reg_ext_rsp_t [1:0] ext_reg_async_slv_data_i, // Interrupts from external devices - input logic [iomsb(Cfg.NumExtIntrs):0] intr_ext_i, + input logic [iomsb(NumExtIntrs):0] intr_ext_i, // Interrupts to external harts output logic [iomsb(Cfg.NumExtIrqHarts):0] meip_ext_o, output logic [iomsb(Cfg.NumExtIrqHarts):0] seip_ext_o, output logic [iomsb(Cfg.NumExtIrqHarts):0] mtip_ext_o, output logic [iomsb(Cfg.NumExtIrqHarts):0] msip_ext_o, + output logic [iomsb(Cfg.NumExtRouterTargets*(NumExtIntrs+NumIntIntrs)):0] intr_distributed_o, // Debug interface to external harts output logic dbg_active_o, output logic [iomsb(Cfg.NumExtDbgHarts):0] dbg_ext_req_o, @@ -352,6 +354,7 @@ end cheshire_soc #( .Cfg ( Cfg ), .ExtHartinfo ( '0 ), + .NumExtIntrs ( NumExtIntrs ), .axi_ext_llc_req_t ( cheshire_axi_ext_llc_req_t ), .axi_ext_llc_rsp_t ( cheshire_axi_ext_llc_rsp_t ), .axi_ext_mst_req_t ( cheshire_axi_ext_mst_req_t ), @@ -384,6 +387,7 @@ cheshire_soc #( .seip_ext_o, .mtip_ext_o, .msip_ext_o, + .intr_distributed_o, // Debug interface to external harts .dbg_active_o , .dbg_ext_req_o ,