diff --git a/Bender.lock b/Bender.lock index 293fc657..49ee12bb 100644 --- a/Bender.lock +++ b/Bender.lock @@ -15,8 +15,8 @@ packages: - apb - register_interface axi: - revision: ac5deb3ff086aa34b168f392c051e92603d6c0e2 - version: 0.39.2 + revision: 853ede23b2a9837951b74dbdc6d18c3eef5bac7d + version: 0.39.5 source: Git: https://github.com/pulp-platform/axi.git dependencies: @@ -44,17 +44,24 @@ packages: - common_cells - common_verification axi_rt: - revision: 56074a195b1c8b05f4bdd73674e437bbcb35f2cd - version: 0.0.0-alpha.7 + revision: 641ea950e24722af747033f2ab85f0e48ea8d7f8 + version: 0.0.0-alpha.9 source: Git: https://github.com/pulp-platform/axi_rt.git dependencies: - axi - common_cells - register_interface + axi_stream: + revision: 54891ff40455ca94a37641b9da4604647878cc07 + version: 0.1.1 + source: + Git: https://github.com/pulp-platform/axi_stream.git + dependencies: + - common_cells axi_vga: - revision: 3718b9930f94a9eaad8ee50b4bccc71df0403084 - version: 0.1.3 + revision: 4d3e70d4f47bb74edc1ab68d99ffc02382e0fb9e + version: 0.1.4 source: Git: https://github.com/pulp-platform/axi_vga.git dependencies: @@ -78,8 +85,8 @@ packages: - common_cells - register_interface common_cells: - revision: 13f28aa0021fc22c0d01a12d618fda58d2c93239 - version: 1.33.0 + revision: c27bce39ebb2e6bae52f60960814a2afca7bd4cb + version: 1.37.0 source: Git: https://github.com/pulp-platform/common_cells.git dependencies: @@ -117,14 +124,16 @@ packages: dependencies: - common_cells idma: - revision: ca1b28816a3706be0bf9ce01378246d5346384f0 - version: 0.5.1 + revision: c12caf59bb482fe44b27361f6924ad346b2d22fe + version: 0.6.3 source: Git: https://github.com/pulp-platform/iDMA.git dependencies: - axi + - axi_stream - common_cells - common_verification + - obi - register_interface irq_router: revision: d1d31350b24f3965b3a51e1bc96c71eb34e94db3 @@ -135,6 +144,14 @@ packages: - axi - common_cells - register_interface + obi: + revision: 5321106817e177d6c16ecc4daa922b96b1bc946b + version: 0.1.5 + source: + Git: https://github.com/pulp-platform/obi.git + dependencies: + - common_cells + - common_verification opentitan_peripherals: revision: cd3153de2783abd3d03d0595e6c4b32413c62f14 version: 0.4.0 @@ -144,9 +161,21 @@ packages: - common_cells - register_interface - tech_cells_generic + pulp-ethernet: + revision: e6e4c8eb7a1dc739492818e45b7ef8196e345b0c + version: null + source: + Git: https://github.com/pulp-platform/pulp-ethernet.git + dependencies: + - axi + - axi_stream + - common_cells + - common_verification + - idma + - register_interface register_interface: - revision: e25b36670ff7aab3402f40efcc2b11ee0f31cf19 - version: 0.4.3 + revision: 5daa85d164cf6b54ad061ea1e4c6f3624556e467 + version: 0.4.5 source: Git: https://github.com/pulp-platform/register_interface.git dependencies: @@ -163,8 +192,8 @@ packages: - common_cells - tech_cells_generic serial_link: - revision: 5a25f5a71074f1ebb6de7b5280f2b16924bcc666 - version: 1.1.1 + revision: c55df03a1da06b00e567cf968b1b1a5f40c9f802 + version: 1.1.2 source: Git: https://github.com/pulp-platform/serial_link.git dependencies: diff --git a/Bender.yml b/Bender.yml index fc2ce82e..4bd4648b 100644 --- a/Bender.yml +++ b/Bender.yml @@ -23,13 +23,14 @@ dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.33.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.0 } cva6: { git: "https://github.com/pulp-platform/cva6.git", rev: pulp-v1.0.0 } - iDMA: { git: "https://github.com/pulp-platform/iDMA.git", version: 0.5.1 } + iDMA: { git: "https://github.com/pulp-platform/iDMA.git", version: 0.6.0 } irq_router: { git: "https://github.com/pulp-platform/irq_router.git", version: 0.0.1-beta.1 } opentitan_peripherals: { git: "https://github.com/pulp-platform/opentitan_peripherals.git", version: 0.4.0 } register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.3 } riscv-dbg: { git: "https://github.com/pulp-platform/riscv-dbg.git", version: 0.8.1 } serial_link: { git: "https://github.com/pulp-platform/serial_link.git", version: 1.1.1 } unbent: { git: "https://github.com/pulp-platform/unbent.git", version: 0.1.6 } + pulp-ethernet: { git: "https://github.com/pulp-platform/pulp-ethernet.git", rev: "e6e4c8e" } # branch: chs-hs export_include_dirs: - hw/include @@ -39,6 +40,7 @@ sources: - hw/regs/cheshire_reg_pkg.sv - hw/regs/cheshire_reg_top.sv - hw/cheshire_pkg.sv + - hw/dma_core_wrap.sv - hw/cheshire_soc.sv - target: any(simulation, test) diff --git a/cheshire.mk b/cheshire.mk index e0fc089d..d32046b0 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -23,6 +23,7 @@ CLINTROOT := $(shell $(BENDER) path clint) AXIRTROOT := $(shell $(BENDER) path axi_rt) AXI_VGA_ROOT := $(shell $(BENDER) path axi_vga) IDMA_ROOT := $(shell $(BENDER) path idma) +ETH_ROOT := $(shell $(BENDER) path pulp-ethernet) REGTOOL ?= $(CHS_REG_DIR)/vendor/lowrisc_opentitan/util/regtool.py @@ -103,6 +104,10 @@ $(CHS_SLINK_DIR)/.generated: $(CHS_ROOT)/hw/serial_link.hjson cp $< $(dir $@)/src/regs/serial_link_single_channel.hjson flock -x $@ $(MAKE) -C $(CHS_SLINK_DIR) update-regs BENDER="$(BENDER)" && touch $@ +# iDMA +$(IDMA_ROOT)/.generated: $(IDMA_ROOT)/target/rtl/idma_reg64_2d.hjson + flock -x $@ sh -c "cp $< $(dir $@)/target/rtl/; $(MAKE) -j1 otp" && touch $@ + CHS_HW_ALL += $(CHS_ROOT)/hw/regs/cheshire_reg_pkg.sv $(CHS_ROOT)/hw/regs/cheshire_reg_top.sv CHS_HW_ALL += $(CLINTROOT)/.generated CHS_HW_ALL += $(OTPROOT)/.generated @@ -133,7 +138,7 @@ CHS_BOOTROM_ALL += $(CHS_ROOT)/hw/bootrom/cheshire_bootrom.sv $(CHS_ROOT)/hw/boo ############## $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc.tcl: $(CHS_ROOT)/Bender.yml - $(BENDER) script vsim -t sim -t cv64a6_imafdcsclic_sv39 -t test -t cva6 -t rtl --vlog-arg="$(VLOG_ARGS)" > $@ + $(BENDER) script vsim -t sim -t cv64a6_imafdcsclic_sv39 -t test -t cva6 -t rtl -t snitch_cluster --vlog-arg="$(VLOG_ARGS)" > $@ echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++11"' >> $@ .PRECIOUS: $(CHS_ROOT)/target/sim/models @@ -169,7 +174,7 @@ include $(CHS_ROOT)/target/xilinx/xilinx.mk CHS_ALL += $(CHS_SW_ALL) $(CHS_HW_ALL) $(CHS_SIM_ALL) -chs-all: $(CHS_ALL) +chs-all: $(CHS_ALL) #idma-gen chs-sw-all: $(CHS_SW_ALL) chs-hw-all: $(CHS_HW_ALL) chs-bootrom-all: $(CHS_BOOTROM_ALL) diff --git a/hw/bootrom/cheshire_bootrom.S b/hw/bootrom/cheshire_bootrom.S index 22bbeb9f..89e388da 100644 --- a/hw/bootrom/cheshire_bootrom.S +++ b/hw/bootrom/cheshire_bootrom.S @@ -62,6 +62,7 @@ _start: andi t0, t0, 2 // regs.HW_FEATURES.llc beqz t0, _prom_check_run la t0, __base_llc + // Only configure half of LLC as SPM _wait_llc_bist: lw t1, 72(t0) // llc.BIST_STATUS_DONE_BIT beqz t1, _wait_llc_bist diff --git a/hw/bootrom/cheshire_bootrom.sv b/hw/bootrom/cheshire_bootrom.sv index 072d4ee4..9c42aeb2 100644 --- a/hw/bootrom/cheshire_bootrom.sv +++ b/hw/bootrom/cheshire_bootrom.sv @@ -2081,4 +2081,4 @@ module cheshire_bootrom #( endcase end -endmodule +endmodule \ No newline at end of file diff --git a/hw/cheshire_pkg.sv b/hw/cheshire_pkg.sv index 691952b0..ea8df5e8 100644 --- a/hw/cheshire_pkg.sv +++ b/hw/cheshire_pkg.sv @@ -91,6 +91,7 @@ package cheshire_pkg; dw_bt AxiDataWidth; dw_bt AxiUserWidth; aw_bt AxiMstIdWidth; + aw_bt TFLenWidth; dw_bt AxiMaxMstTrans; dw_bt AxiMaxSlvTrans; // User signals identify atomics masters. @@ -100,9 +101,11 @@ package cheshire_pkg; dw_bt AxiUserErrBits; dw_bt AxiUserErrLsb; doub_bt AxiUserDefault; // Default user assignment, adjusted by user features (AMO) + bit CorePostCut; // Reg parameters dw_bt RegMaxReadTxns; dw_bt RegMaxWriteTxns; + bit AxiToRegCut; aw_bt RegAmoNumCuts; bit RegAmoPostCut; bit RegAdaptMemCut; @@ -127,6 +130,7 @@ package cheshire_pkg; bit Bootrom; bit Uart; bit I2c; + bit Ethernet; bit SpiHost; bit Gpio; bit Dma; @@ -212,6 +216,7 @@ package cheshire_pkg; typedef struct packed { cheshire_bus_err_intr_t bus_err; logic [31:0] gpio; + logic ethernet; logic spih_spi_event; logic spih_error; logic i2c_host_timeout; @@ -293,6 +298,7 @@ package cheshire_pkg; aw_bt vga; aw_bt ext_base; aw_bt num_in; + aw_bt eth; } axi_in_t; function automatic axi_in_t gen_axi_in(cheshire_cfg_t cfg); @@ -303,6 +309,7 @@ package cheshire_pkg; if (cfg.Dma) begin i++; ret.dma = i; end if (cfg.SerialLink) begin i++; ret.slink = i; end if (cfg.Vga) begin i++; ret.vga = i; end + if (cfg.Ethernet) begin i++; ret.eth = i; end i++; ret.ext_base = i; ret.num_in = i + cfg.AxiExtNumMst; @@ -380,6 +387,7 @@ package cheshire_pkg; aw_bt llc; aw_bt uart; aw_bt i2c; + aw_bt ethernet; aw_bt spi_host; aw_bt gpio; aw_bt slink; @@ -388,6 +396,7 @@ package cheshire_pkg; aw_bt irq_router; aw_bt [2**MaxCoresWidth-1:0] bus_err; aw_bt [2**MaxCoresWidth-1:0] clic; + aw_bt hmr_unit; aw_bt ext_base; aw_bt num_out; aw_bt num_rules; @@ -410,6 +419,7 @@ package cheshire_pkg; if (cfg.Vga) begin i++; ret.vga = i; r++; ret.map[r] = '{i, 'h0300_7000, 'h0300_8000}; end if (cfg.IrqRouter) begin i++; ret.irq_router = i; r++; ret.map[r] = '{i, 'h0208_0000, 'h020c_0000}; end if (cfg.AxiRt) begin i++; ret.axirt = i; r++; ret.map[r] = '{i, 'h020c_0000, 'h0210_0000}; end + if (cfg.Ethernet) begin i++; ret.ethernet = i; r++; ret.map[r] = '{i, 'h0300_c000, 'h0300_d000}; end if (cfg.Clic) for (int j = 0; j < cfg.NumCores; j++) begin i++; ret.clic[j] = i; r++; ret.map[r] = '{i, AmClic + j*'h40000, AmClic + (j+1)*'h40000}; end @@ -569,8 +579,9 @@ package cheshire_pkg; // Interconnect AddrWidth : 48, AxiDataWidth : 64, - AxiUserWidth : 2, // AMO(2) + AxiUserWidth : 2, // Convention: bit 0 for core(s), bit 1 for serial link AxiMstIdWidth : 2, + TFLenWidth : 32, AxiMaxMstTrans : 24, AxiMaxSlvTrans : 24, AxiUserAmoMsb : 1, // Convention: lower AMO bits for cores, MSB for serial link @@ -580,6 +591,7 @@ package cheshire_pkg; AxiUserDefault : 0, RegMaxReadTxns : 8, RegMaxWriteTxns : 8, + AxiToRegCut : 0, RegAmoNumCuts : 1, RegAmoPostCut : 1, RegAdaptMemCut : 1, @@ -589,12 +601,13 @@ package cheshire_pkg; Bootrom : 1, Uart : 1, I2c : 1, + Ethernet : 1, SpiHost : 1, Gpio : 1, - Dma : 1, + Dma : 0, SerialLink : 1, Vga : 1, - AxiRt : 0, + AxiRt : 1, Clic : 0, IrqRouter : 0, BusErr : 1, @@ -608,7 +621,7 @@ package cheshire_pkg; // LLC: 128 KiB, up to 2 GiB DRAM LlcNotBypass : 1, LlcSetAssoc : 8, - LlcNumLines : 256, + LlcNumLines : 128, // from 256 LlcNumBlocks : 8, LlcMaxReadTxns : 16, LlcMaxWriteTxns : 16, diff --git a/hw/cheshire_soc.sv b/hw/cheshire_soc.sv index c8c7f077..2f1db2d5 100644 --- a/hw/cheshire_soc.sv +++ b/hw/cheshire_soc.sv @@ -28,6 +28,9 @@ module cheshire_soc import cheshire_pkg::*; #( input logic test_mode_i, input logic [1:0] boot_mode_i, input logic rtc_i, + input logic eth_clk125_i, + input logic eth_clk125q_i, + input logic eth_clk200_i, // External AXI LLC (DRAM) port output axi_ext_llc_req_t axi_llc_mst_req_o, input axi_ext_llc_rsp_t axi_llc_mst_rsp_i, @@ -74,6 +77,18 @@ module cheshire_soc import cheshire_pkg::*; #( output logic i2c_scl_o, input logic i2c_scl_i, output logic i2c_scl_en_o, + // ETHERNET interface + input logic eth_rxck_i, + input logic [3:0] eth_rxd_i, + input logic eth_rxctl_i, + output logic eth_txck_o, + output logic [3:0] eth_txd_o, + output logic eth_txctl_o, + output logic eth_rstn_o, + input logic eth_mdio_i, + output logic eth_mdio_o, + output logic eth_mdio_oe, + output logic eth_mdc_o, // SPI host interface output logic spih_sck_o, output logic spih_sck_en_o, @@ -492,6 +507,7 @@ module cheshire_soc import cheshire_pkg::*; #( // This is necessary for routing in the LLC-internal interconnect. always_comb begin axi_llc_remap_req = axi_llc_cut_req; + if (axi_llc_cut_req.aw.addr & ~AmSpmRegionMask == AmSpmBaseUncached & ~AmSpmRegionMask) axi_llc_remap_req.aw.addr = AmSpm | (AmSpmRegionMask & axi_llc_cut_req.aw.addr); if (axi_llc_cut_req.ar.addr & ~AmSpmRegionMask == AmSpmBaseUncached & ~AmSpmRegionMask) @@ -1281,6 +1297,60 @@ module cheshire_soc import cheshire_pkg::*; #( end + //////////////// + // ETHERNET // + //////////////// + if (Cfg.Ethernet) begin : gen_ethernet + eth_idma_wrap#( + .DataWidth ( Cfg.AxiDataWidth ), + .AddrWidth ( Cfg.AddrWidth ), + .UserWidth ( Cfg.AxiUserWidth ), + .AxiIdWidth ( Cfg.AxiMstIdWidth ), + .NumAxInFlight ( 32'd15 ), + .BufferDepth ( 32'd2 ), + .TFLenWidth ( 32'd20 ), + .MemSysDepth ( 32'd0 ), + .TxFifoLogDepth ( 32'd5 ), + .RxFifoLogDepth ( 32'd10 ), + .axi_req_t ( axi_mst_req_t ), + .axi_rsp_t ( axi_mst_rsp_t ), + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ) + ) i_tx_eth_idma_wrap ( + .clk_i, + .rst_ni, + .eth_clk125_i ( eth_clk125_i ), + .eth_clk125q_i ( eth_clk125q_i), + .eth_clk200_i ( eth_clk200_i ), + .phy_rx_clk_i ( eth_rxck_i ), + .phy_rxd_i ( eth_rxd_i ), + .phy_rx_ctl_i ( eth_rxctl_i ), + .phy_tx_clk_o ( eth_txck_o ), + .phy_txd_o ( eth_txd_o ), + .phy_tx_ctl_o ( eth_txctl_o ), + .phy_resetn_o ( eth_rstn_o ), + .phy_intn_i ( 1'b1 ), + .phy_pme_i ( 1'b1 ), + .phy_mdio_i ( eth_mdio_i ), + .phy_mdio_o ( eth_mdio_o ), + .phy_mdio_oe ( eth_mdio_oe ), + .phy_mdc_o ( eth_mdc_o ), + .testmode_i ( testmode_i ), + .axi_req_o ( axi_in_req[AxiIn.eth] ), + .axi_rsp_i ( axi_in_rsp[AxiIn.eth] ), + .reg_req_i ( reg_out_req[RegOut.ethernet] ), + .reg_rsp_o ( reg_out_rsp[RegOut.ethernet] ), + .eth_rx_irq_o ( intr.intn.ethernet ) + ); + + end else begin : gen_no_ethernet + assign intr.intn.ethernet = 1'b0; + assign eth_txck_o = 1'b0; + assign eth_rstn_o = 1'b0; + assign eth_txctl_o = 1'b0; + assign eth_txd_o = 4'b0; + end + //////////////// // SPI Host // //////////////// @@ -1418,6 +1488,7 @@ module cheshire_soc import cheshire_pkg::*; #( .AxiIdWidth ( Cfg.AxiMstIdWidth ), .AxiUserWidth ( Cfg.AxiUserWidth ), .AxiSlvIdWidth ( AxiSlvIdWidth ), + .TFLenWidth ( Cfg.TFLenWidth ), .NumAxInFlight ( Cfg.DmaNumAxInFlight ), .MemSysDepth ( Cfg.DmaMemSysDepth ), .JobFifoDepth ( Cfg.DmaJobFifoDepth ), diff --git a/hw/cva6_wrap.sv b/hw/cva6_wrap.sv new file mode 100644 index 00000000..fb1affbf --- /dev/null +++ b/hw/cva6_wrap.sv @@ -0,0 +1,225 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Yvan Tortorella + +`include "axi/assign.svh" + +module cva6_wrap #( + parameter cheshire_pkg::cheshire_cfg_t Cfg = '0, + parameter config_pkg::cva6_cfg_t Cva6Cfg = cva6_config_pkg::cva6_cfg, + parameter int unsigned NumHarts = 1, + parameter int unsigned ClicNumIrqs = $clog2(Cva6Cfg.CLICNumInterruptSrc), + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter type axi_ar_chan_t = logic, + parameter type axi_aw_chan_t = logic, + parameter type axi_w_chan_t = logic, + parameter type b_chan_t = logic, + parameter type r_chan_t = logic, + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic +)( + input logic clk_i, + input logic rstn_i, + input cheshire_pkg::doub_bt bootaddress_i, + input cheshire_pkg::doub_bt hart_id_i, + input logic [31:0] harts_sync_req_i, + input logic [NumHarts-1:0][1:0] irq_i, + input logic [NumHarts-1:0] ipi_i, + input logic [NumHarts-1:0] time_irq_i, + input logic [NumHarts-1:0] debug_req_i, + input logic [NumHarts-1:0] clic_irq_valid_i, + input logic [NumHarts-1:0][ClicNumIrqs-1:0] clic_irq_id_i, + input logic [NumHarts-1:0][7:0] clic_irq_level_i, + input riscv::priv_lvl_t [NumHarts-1:0] clic_irq_priv_i, + input logic [NumHarts-1:0] clic_irq_v_i, + input logic [NumHarts-1:0][5:0] clic_irq_vsid_i, + input logic [NumHarts-1:0] clic_irq_shv_i, + output logic [NumHarts-1:0] clic_irq_ready_o, + input logic [NumHarts-1:0] clic_kill_req_i, + output logic [NumHarts-1:0] clic_kill_ack_o, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + output axi_req_t [NumHarts-1:0] axi_req_o, + input axi_rsp_t [NumHarts-1:0] axi_rsp_i +); + +typedef struct packed { + // cheshire_pkg::doub_bt bootaddress; + cheshire_pkg::doub_bt hart_id; + logic [1:0] irq; + logic ipi; + logic time_irq; + logic debug_req; + logic clic_irq_valid; + logic [ClicNumIrqs-1:0] clic_irq_id; + logic [7:0] clic_irq_level; + riscv::priv_lvl_t clic_irq_priv; + logic clic_irq_v; + logic [5:0] clic_irq_vsid; + logic clic_irq_shv; + logic clic_kill_req; + axi_rsp_t axi_rsp; +} cva6_inputs_t; + +typedef struct packed { + logic clic_irq_ready; + logic clic_kill_ack; + axi_req_t axi_req; +} cva6_outputs_t; + +logic cores_sync; +logic [NumHarts-1:0] core_setback; +cva6_inputs_t [NumHarts-1:0] sys2hmr, hmr2core; +cva6_outputs_t [NumHarts-1:0] hmr2sys, core2hmr; +cheshire_pkg::doub_bt [NumHarts-1:0] core_bootaddress; + +for (genvar i = 0; i < NumHarts; i++) begin: gen_cva6_cores + // Bind system inputs to HMR. + // assign sys2hmr[i].bootaddress = bootaddress_i; // TODO: differentiate? + assign sys2hmr[i].hart_id = hart_id_i + 64'(i); + assign sys2hmr[i].irq = irq_i[i]; + assign sys2hmr[i].ipi = ipi_i[i]; + assign sys2hmr[i].time_irq = time_irq_i[i]; + assign sys2hmr[i].debug_req = debug_req_i[i]; + assign sys2hmr[i].clic_irq_valid = clic_irq_valid_i[i]; + assign sys2hmr[i].clic_irq_id = clic_irq_id_i[i]; + assign sys2hmr[i].clic_irq_level = clic_irq_level_i[i]; + assign sys2hmr[i].clic_irq_priv = clic_irq_priv_i[i]; + assign sys2hmr[i].clic_irq_v = clic_irq_v_i[i]; + assign sys2hmr[i].clic_irq_vsid = clic_irq_vsid_i[i]; + assign sys2hmr[i].clic_irq_shv = clic_irq_shv_i[i]; + assign sys2hmr[i].clic_kill_req = clic_kill_req_i[i]; + `AXI_ASSIGN_RESP_STRUCT(sys2hmr[i].axi_rsp, axi_rsp_i[i]); + + // Bind HMR outputs to system. + assign clic_irq_ready_o[i] = hmr2sys[i].clic_irq_ready; + assign clic_kill_ack_o[i] = hmr2sys[i].clic_kill_ack; + `AXI_ASSIGN_REQ_STRUCT(axi_req_o[i], hmr2sys[i].axi_req); + + cva6 #( + .CVA6Cfg ( Cva6Cfg ), + .axi_ar_chan_t ( axi_ar_chan_t ), + .axi_aw_chan_t ( axi_aw_chan_t ), + .axi_w_chan_t ( axi_w_chan_t ), + .b_chan_t ( b_chan_t ), + .r_chan_t ( r_chan_t ), + .noc_req_t ( axi_req_t ), + .noc_resp_t ( axi_rsp_t ) + ) i_core_cva6 ( + .clk_i ( clk_i ), + .rst_ni ( rstn_i ), + .clear_i ( core_setback[i] ), + // .boot_addr_i ( hmr2core[i].bootaddress ), + .boot_addr_i ( core_bootaddress[i] ), + .hart_id_i ( hmr2core[i].hart_id ), + .irq_i ( hmr2core[i].irq ), + .ipi_i ( hmr2core[i].ipi ), + .time_irq_i ( hmr2core[i].time_irq ), + .debug_req_i ( hmr2core[i].debug_req ), + .clic_irq_valid_i ( hmr2core[i].clic_irq_valid ), + .clic_irq_id_i ( hmr2core[i].clic_irq_id ), + .clic_irq_level_i ( hmr2core[i].clic_irq_level ), + .clic_irq_priv_i ( hmr2core[i].clic_irq_priv ), + .clic_irq_shv_i ( hmr2core[i].clic_irq_shv ), + // Clic support changed in CVA6, probably not all the features + // have already been merged + // .clic_irq_v_i ( hmr2core[i].clic_irq_v ), + // .clic_irq_vsid_i ( hmr2core[i].clic_irq_vsid ), + .clic_irq_ready_o ( core2hmr[i].clic_irq_ready ), + .clic_kill_req_i ( hmr2core[i].clic_kill_req ), + .clic_kill_ack_o ( core2hmr[i].clic_kill_ack ), + .rvfi_probes_o ( ), + .cvxif_req_o ( ), + .cvxif_resp_i ( '0 ), + .noc_req_o ( core2hmr[i].axi_req ), + .noc_resp_i ( hmr2core[i].axi_rsp ) + ); +end + +assign cores_sync = (harts_sync_req_i[NumHarts-1:0] == '1) ? 1'b1 : 1'b0; + +if (NumHarts > 1) begin: gen_multicore_hmr + hmr_unit #( + .NumCores ( NumHarts ), + .DMRSupported ( Cfg.Cva6DMR ), + .DMRFixed ( Cfg.Cva6DMRFixed ), // TODO: make configurable + .TMRSupported ( 0 ), + // .InterleaveGrps ( 0 ), + .RapidRecovery ( Cfg.RapidRecovery ), + .SeparateData ( 0 ), + .RfAddrWidth ( 5 ), + .SysDataWidth ( 64 ), + .all_inputs_t ( cva6_inputs_t ), // Inputs from the system to the HMR + .nominal_outputs_t ( cva6_outputs_t ), + // .core_backup_t ( '0 ), // TODO + // .bus_outputs_t ( '0 ), // TODO + .reg_req_t ( reg_req_t ), // TODO + .reg_rsp_t ( reg_rsp_t ), // TODO + .rapid_recovery_t ( rapid_recovery_pkg::rapid_recovery_t ) // TODO + ) i_cva6_hmr ( + .clk_i ( clk_i ), + .rst_ni ( rstn_i ), + .reg_request_i ( reg_req_i ), + .reg_response_o ( reg_rsp_o ), + .tmr_failure_o ( /* Not used */), + .tmr_error_o ( /* Not used */), // Should this not be NumTMRCores? or NumCores? + .tmr_resynch_req_o ( /* Not used */), + .tmr_sw_synch_req_o ( /* Not used */), + .tmr_cores_synch_i ( '0 ), // Not used + + // DMR signals + .dmr_failure_o ( /* TODO */ ), + .dmr_error_o ( /* TODO */ ), // Should this not be NumDMRCores? or NumCores? + .dmr_resynch_req_o ( /* TODO */ ), + .dmr_sw_synch_req_o ( /* TODO */ ), + // In PULP cluster we connected this to the event unit + // to receive information about cores' synchronization. + // How should we handle it here? We could use Cheshire's + // registers to write that a synchronization completed + // succesfully (??) + .dmr_cores_synch_i ( cores_sync ), + + // Rapid recovery buses + .rapid_recovery_o ( /* TODO */ ), + .core_backup_i ( '0 ), // TODO + + .sys_bootaddress_i ( bootaddress_i ), + .sys_inputs_i ( sys2hmr ), + .sys_nominal_outputs_o ( hmr2sys ), + .sys_bus_outputs_o ( ), + // CVA6 boot does not rely on fetch enable. + .sys_fetch_en_i ( '1 ), + .enable_bus_vote_i ( '0 ), // TODO? + + .core_bootaddress_o ( core_bootaddress ), + .core_setback_o ( core_setback ), + .core_inputs_o ( hmr2core ), + .core_nominal_outputs_i ( core2hmr ), + .core_bus_outputs_i ( '0 ) // TODO? + ); + + /* We temporarily hardcode this for permanent lockstep.*/ + // assign hmr2sys[NumHarts-1] = '0; +end else begin : gen_single_core_binding + assign core_bootaddress = bootaddress_i; + assign core_setback = '0; + assign hmr2core = sys2hmr ; + assign hmr2sys = core2hmr; + + // reg error slave when HMR not supported + reg_err_slv #( + .DW ( 32 ), + .ERR_VAL ( 32'hBADCAB1E ), + .req_t ( reg_req_t ), + .rsp_t ( reg_rsp_t ) + ) i_cva6_hmr_err_slv ( + .req_i ( reg_req_i ), + .rsp_o ( reg_rsp_o ) + ); + +end + +endmodule: cva6_wrap diff --git a/hw/dma_core_wrap.sv b/hw/dma_core_wrap.sv new file mode 100644 index 00000000..07960ac8 --- /dev/null +++ b/hw/dma_core_wrap.sv @@ -0,0 +1,357 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Author: Thomas Benz +// Author: Andreas Kuster +// Author: Paul Scheffler +// Author: Chaoqun Liang + +// Description: DMA core wrapper for the CVA6 integration + +`include "axi/assign.svh" +`include "axi/typedef.svh" +`include "idma/typedef.svh" +`include "register_interface/typedef.svh" + +module dma_core_wrap #( + parameter int unsigned AxiAddrWidth = 32'd0, + parameter int unsigned AxiDataWidth = 32'd0, + parameter int unsigned AxiIdWidth = 32'd0, + parameter int unsigned AxiUserWidth = 32'd0, + parameter int unsigned AxiSlvIdWidth = 32'd0, + parameter int unsigned TFLenWidth = 32'd0, + parameter int unsigned NumAxInFlight = 32'd0, + parameter int unsigned MemSysDepth = 32'd0, + parameter int unsigned JobFifoDepth = 32'd0, + parameter bit EnableAxiCut = 1'b1, + parameter bit RAWCouplingAvail = 32'd0, + parameter bit IsTwoD = 32'd0, + parameter type axi_mst_aw_chan_t = logic, + parameter type axi_mst_ar_chan_t = logic, + parameter type axi_mst_w_chan_t = logic, + parameter type axi_mst_r_chan_t = logic, + parameter type axi_mst_b_chan_t = logic, + parameter type axi_mst_req_t = logic, + parameter type axi_mst_rsp_t = logic, + parameter type axi_slv_req_t = logic, + parameter type axi_slv_rsp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + input logic testmode_i, + output axi_mst_req_t axi_mst_req_o, + input axi_mst_rsp_t axi_mst_rsp_i, + input axi_slv_req_t axi_slv_req_i, + output axi_slv_rsp_t axi_slv_rsp_o +); + // local params + localparam int unsigned IdCounterWidth = 32'd32; + localparam int unsigned NumDim = 32'd2; + localparam int unsigned RepWidth = 32'd32; + + typedef logic [AxiDataWidth-1:0] data_t; + typedef logic [AxiDataWidth/8-1:0] strb_t; + typedef logic [AxiAddrWidth-1:0] addr_t; + typedef logic [AxiIdWidth-1:0] id_t; + typedef logic [AxiSlvIdWidth-1:0] slv_id_t; + typedef logic [AxiUserWidth-1:0] user_t; + typedef logic [TFLenWidth-1:0] tf_len_t; + typedef logic [IdCounterWidth-1:0] tf_id_t; + typedef logic [RepWidth-1:0] reps_t; + typedef logic [RepWidth-1:0] strides_t; + + // AXI4+ATOP typedefs + `AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) + + // iDMA request / response types + `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, id_t, addr_t, tf_len_t) + `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, addr_t) + `IDMA_TYPEDEF_FULL_ND_REQ_T(idma_nd_req_t, idma_req_t, tf_len_t, tf_len_t) + + `REG_BUS_TYPEDEF_ALL(dma_regs, addr_t, data_t, strb_t) + + typedef struct packed { + axi_ar_chan_t ar_chan; + } axi_read_meta_channel_t; + + typedef struct packed { + axi_read_meta_channel_t axi; + } read_meta_channel_t; + + typedef struct packed { + axi_aw_chan_t aw_chan; + } axi_write_meta_channel_t; + + typedef struct packed { + axi_write_meta_channel_t axi; + } write_meta_channel_t; + + dma_regs_req_t dma_reg_req; + dma_regs_rsp_t dma_reg_rsp; + // 1d-fe signals + idma_req_t burst_req_d; + logic be_valid_d; + logic be_ready_d; + // nd-fe signals + idma_nd_req_t idma_nd_req_d; + logic idma_nd_req_valid_d; + logic idma_nd_req_ready_d; + // nd-me signals + idma_nd_req_t idma_nd_req; + logic idma_nd_req_valid; + logic idma_nd_req_ready; + logic idma_nd_rsp_valid; + logic idma_nd_rsp_ready; + // be signals + idma_req_t burst_req; + logic be_valid; + logic be_ready; + idma_rsp_t idma_rsp; + logic idma_rsp_valid; + logic idma_rsp_ready; + // id signals + logic issue_id; + logic retire_id; + logic [IdCounterWidth-1:0] done_id, next_id; + // status signals + idma_pkg::idma_busy_t busy; + logic me_busy; + // internal AXI channels + axi_mst_req_t axi_read_req, axi_write_req, axi_cut_req; + axi_mst_rsp_t axi_read_rsp, axi_write_rsp, axi_cut_rsp; + + axi_to_reg #( + .ADDR_WIDTH( AxiAddrWidth ), + .DATA_WIDTH( AxiDataWidth ), + .ID_WIDTH ( AxiSlvIdWidth ), + .USER_WIDTH( AxiUserWidth ), + .axi_req_t ( axi_slv_req_t ), + .axi_rsp_t ( axi_slv_rsp_t ), + .reg_req_t ( dma_regs_req_t ), + .reg_rsp_t ( dma_regs_rsp_t ) + ) i_axi_translate ( + .clk_i, + .rst_ni, + .testmode_i ( 1'b0 ), + .axi_req_i ( axi_slv_req_i ), + .axi_rsp_o ( axi_slv_rsp_o ), + .reg_req_o ( dma_reg_req ), + .reg_rsp_i ( dma_reg_rsp ) + ); + + if (!IsTwoD) begin : gen_one_d + idma_reg64_1d #( + .NumRegs ( 32'd1 ), + .NumStreams ( 32'd1 ), + .IdCounterWidth ( IdCounterWidth ), + .reg_req_t ( dma_regs_req_t ), + .reg_rsp_t ( dma_regs_rsp_t ), + .dma_req_t ( idma_req_t ) + ) i_dma_frontend_1d ( + .clk_i, + .rst_ni, + .dma_ctrl_req_i ( dma_reg_req ), + .dma_ctrl_rsp_o ( dma_reg_rsp ), + .dma_req_o ( burst_req_d ), + .req_valid_o ( be_valid_d ), + .req_ready_i ( be_ready_d ), + .next_id_i ( next_id ), + .stream_idx_o ( ), + .done_id_i ( done_id ), + .busy_i ( idma_busy ), + .midend_busy_i ( 0 ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( JobFifoDepth ), + .type_t ( idma_req_t ), + .PrintInfo ( 1'b0 ) + ) i_stream_fifo_jobs_1d ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NC */ ), + .data_i ( burst_req_d ), + .valid_i ( be_valid_d ), + .ready_o ( be_ready_d ), + .data_o ( burst_req ), + .valid_o ( be_valid ), + .ready_i ( be_ready ) + ); + + assign retire_id = idma_rsp_valid & idma_rsp_ready; + assign issue_id = be_valid_d & be_ready_d; + assign idma_rsp_ready = 1'b1; + + idma_transfer_id_gen #( + .IdWidth ( IdCounterWidth ) + ) i_transfer_id_gen_1d ( + .clk_i, + .rst_ni, + .issue_i ( issue_id ), + .retire_i ( retire_id ), + .next_o ( next_id ), + .completed_o ( done_id ) + ); + + end else begin : gen_two + idma_reg64_2d #( + .NumRegs ( 32'd1 ), + .NumStreams ( 32'd1 ), + .IdCounterWidth ( IdCounterWidth ), + .reg_req_t ( dma_regs_req_t ), + .reg_rsp_t ( dma_regs_rsp_t ), + .dma_req_t ( idma_nd_req_t ) + ) idma_frontend_2d ( + .clk_i, + .rst_ni, + .dma_ctrl_req_i ( dma_reg_req ), + .dma_ctrl_rsp_o ( dma_reg_rsp ), + .dma_req_o ( idma_nd_req_d ), + .req_valid_o ( idma_nd_req_valid_d ), + .req_ready_i ( idma_nd_req_ready_d ), + .next_id_i ( next_id ), + .stream_idx_o ( ), + .done_id_i ( done_id ), + .busy_i ( busy ), + .midend_busy_i ( me_busy ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( JobFifoDepth ), + .type_t ( idma_nd_req_t ), + .PrintInfo ( 1'b0 ) + ) i_stream_fifo_jobs_2d ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NC */ ), + .data_i ( idma_nd_req_d ), + .valid_i ( idma_nd_req_valid_d ), + .ready_o ( idma_nd_req_ready_d ), + .data_o ( idma_nd_req ), + .valid_o ( idma_nd_req_valid ), + .ready_i ( idma_nd_req_ready ) + ); + + idma_nd_midend #( + .NumDim ( NumDim ), + .addr_t ( addr_t ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_nd_req_t ( idma_nd_req_t ), + .RepWidths ( RepWidth ) + ) i_idma_midend ( + .clk_i, + .rst_ni, + .nd_req_i ( idma_nd_req ), + .nd_req_valid_i ( idma_nd_req_valid ), + .nd_req_ready_o ( idma_nd_req_ready ), + .nd_rsp_o ( ), + .nd_rsp_valid_o ( idma_nd_rsp_valid ), + .nd_rsp_ready_i ( idma_nd_rsp_ready ), + .burst_req_o ( burst_req ), + .burst_req_valid_o ( be_valid ), + .burst_req_ready_i ( be_ready ), + .burst_rsp_i ( idma_rsp ), + .burst_rsp_valid_i ( idma_rsp_valid ), + .burst_rsp_ready_o ( idma_rsp_ready ), + .busy_o ( me_busy ) + ); + + assign retire_id = idma_nd_rsp_valid & idma_nd_rsp_ready; + assign issue_id = idma_nd_req_valid_d & idma_nd_req_ready_d; + assign idma_nd_rsp_ready = 1'b1; + + idma_transfer_id_gen #( + .IdWidth ( IdCounterWidth ) + ) i_transfer_id_gen_2d ( + .clk_i, + .rst_ni, + .issue_i ( issue_id ), + .retire_i ( retire_id ), + .next_o ( next_id ), + .completed_o ( done_id ) + ); + end + + idma_backend_rw_axi #( + .CombinedShifter ( 1'b0 ), + .DataWidth ( AxiDataWidth ), + .AddrWidth ( AxiAddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( AxiUserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( 1 ), + .BufferDepth ( 3 ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( 1 ), + .RejectZeroTransfers ( 1 ), + .ErrorCap ( idma_pkg::NO_ERROR_HANDLING ), + .PrintFifoInfo ( 1 ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_mst_req_t ), + .axi_rsp_t ( axi_mst_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ) + ) i_idma_backend ( + .clk_i, + .rst_ni, + .testmode_i ( 1'b0 ), + .idma_req_i ( burst_req ), + .req_valid_i ( be_valid ), + .req_ready_o ( be_ready ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( idma_rsp_valid ), + .rsp_ready_i ( idma_rsp_ready ), + .idma_eh_req_i ( '0 ), + .eh_req_valid_i ( '0 ), + .eh_req_ready_o ( ), + .axi_read_req_o ( axi_read_req ), + .axi_read_rsp_i ( axi_read_rsp ), + .axi_write_req_o ( axi_write_req ), + .axi_write_rsp_i ( axi_write_rsp ), + .busy_o ( busy ) + ); + + axi_rw_join #( + .axi_req_t ( axi_mst_req_t ), + .axi_resp_t ( axi_mst_rsp_t ) + ) i_axi_rw_join ( + .clk_i, + .rst_ni, + .slv_read_req_i ( axi_read_req ), + .slv_read_resp_o ( axi_read_rsp ), + .slv_write_req_i ( axi_write_req ), + .slv_write_resp_o ( axi_write_rsp ), + .mst_req_o ( axi_cut_req ), + .mst_resp_i ( axi_cut_rsp ) + ); + + axi_cut #( + .Bypass ( ~EnableAxiCut ), + .aw_chan_t ( axi_mst_aw_chan_t ), + .w_chan_t ( axi_mst_w_chan_t ), + .b_chan_t ( axi_mst_b_chan_t ), + .ar_chan_t ( axi_mst_ar_chan_t ), + .r_chan_t ( axi_mst_r_chan_t ), + .axi_req_t ( axi_mst_req_t ), + .axi_resp_t ( axi_mst_rsp_t ) + ) i_axi_cut ( + .clk_i, + .rst_ni, + .slv_req_i ( axi_cut_req ), + .slv_resp_o ( axi_cut_rsp ), + .mst_req_o ( axi_mst_req_o ), + .mst_resp_i ( axi_mst_rsp_i ) + ); +endmodule \ No newline at end of file diff --git a/hw/regs/cheshire_regs.hjson b/hw/regs/cheshire_regs.hjson index e551a945..42091a40 100644 --- a/hw/regs/cheshire_regs.hjson +++ b/hw/regs/cheshire_regs.hjson @@ -132,4 +132,4 @@ } ] -} +} \ No newline at end of file diff --git a/hw/rv_plic.cfg.hjson b/hw/rv_plic.cfg.hjson index 6d16a80c..865be3a9 100644 --- a/hw/rv_plic.cfg.hjson +++ b/hw/rv_plic.cfg.hjson @@ -7,7 +7,7 @@ { instance_name: "rv_plic", param_values: { - src: 57, + src: 58, target: 2, // We need *two targets* per hart: M and S modes prio: 7, nonstd_regs: 0 // Do *not* include these: MSIPs are not used and we use a 64 MiB address space diff --git a/requirements.txt b/requirements.txt index 58ded7d6..dad86bdd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,4 @@ yapf mkdocs mkdocs-material markdown-grid-tables +flatdict diff --git a/sw/boot/cheshire.dtsi b/sw/boot/cheshire.dtsi index 76decc85..39426437 100644 --- a/sw/boot/cheshire.dtsi +++ b/sw/boot/cheshire.dtsi @@ -107,5 +107,13 @@ riscv,ndev = <51>; reg = <0x0 0x4000000 0x0 0x4000000>; }; + #eth: idma-eth@300c000 { + #compatible = "idma-eth"; + #device_type = "network"; + #interrupt-parent = <&PLIC0>; + #interrupts = <19>; + #local-mac-address = [00 18 3e 02 e3 7f]; // This needs to change if more than one GenesysII on a VLAN + #reg = <0x0 0x300c000 0x0 0x1000>; + #}; }; }; diff --git a/sw/deps/cva6-sdk b/sw/deps/cva6-sdk index 1d4ef36b..175b88ba 160000 --- a/sw/deps/cva6-sdk +++ b/sw/deps/cva6-sdk @@ -1 +1 @@ -Subproject commit 1d4ef36baba9ecc63528fa2c0f6fa49db8fb0fbb +Subproject commit 175b88bae504757f93e59d02d437bdfdd886dd2c diff --git a/sw/include/dif/dma.h b/sw/include/dif/dma.h index f48b0a9f..2d37ab09 100644 --- a/sw/include/dif/dma.h +++ b/sw/include/dif/dma.h @@ -1,4 +1,4 @@ -// Copyright 2022 ETH Zurich and University of Bologna. +// Copyright 2024 ETH Zurich and University of Bologna. // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -9,17 +9,16 @@ #include "regs/idma.h" #include "params.h" -#define DMA_SRC_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_SRC_ADDR_REG_OFFSET) -#define DMA_DST_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_DST_ADDR_REG_OFFSET) -#define DMA_NUMBYTES_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_NUM_BYTES_REG_OFFSET) -#define DMA_CONF_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_CONF_REG_OFFSET) -#define DMA_STATUS_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_STATUS_REG_OFFSET) -#define DMA_NEXTID_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_NEXT_ID_REG_OFFSET) -#define DMA_DONE_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_DONE_REG_OFFSET) -#define DMA_SRC_STRIDE_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_STRIDE_SRC_REG_OFFSET) -#define DMA_DST_STRIDE_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_STRIDE_DST_REG_OFFSET) -#define DMA_NUM_REPS_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_FRONTEND_NUM_REPETITIONS_REG_OFFSET) - +#define DMA_SRC_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_SRC_ADDR_LOW_REG_OFFSET) +#define DMA_DST_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_DST_ADDR_LOW_REG_OFFSET) +#define DMA_NUMBYTES_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_LENGTH_LOW_REG_OFFSET) +#define DMA_CONF_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_CONF_REG_OFFSET) +#define DMA_STATUS_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_STATUS_0_REG_OFFSET) +#define DMA_NEXTID_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_NEXT_ID_0_REG_OFFSET) +#define DMA_DONE_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_DONE_ID_0_REG_OFFSET) +#define DMA_SRC_STRIDE_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_SRC_STRIDE_2_LOW_REG_OFFSET) +#define DMA_DST_STRIDE_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_DST_STRIDE_2_LOW_REG_OFFSET) +#define DMA_NUM_REPS_ADDR(BASE) ((void *)BASE + IDMA_REG64_2D_REPS_2_LOW_REG_OFFSET) #define DMA_CONF_DECOUPLE 0 #define DMA_CONF_DEBURST 0 #define DMA_CONF_SERIALIZE 0 @@ -81,10 +80,8 @@ *(NAME##_dma_dst_ptr()) = (uint64_t)dst; \ *(NAME##_dma_num_bytes_ptr()) = size; \ *(NAME##_dma_num_reps_ptr()) = 0; \ - *(NAME##_dma_conf_ptr()) = \ - (DMA_CONF_DECOUPLE << IDMA_REG64_2D_FRONTEND_CONF_DECOUPLE_BIT) | \ - (DMA_CONF_DEBURST << IDMA_REG64_2D_FRONTEND_CONF_DEBURST_BIT) | \ - (DMA_CONF_SERIALIZE << IDMA_REG64_2D_FRONTEND_CONF_SERIALIZE_BIT); \ + *(NAME##_dma_conf_ptr()) = (DMA_CONF_DECOUPLE << IDMA_REG64_2D_CONF_DECOUPLE_AW_BIT) | \ + (DMA_CONF_DEBURST << 0) | (DMA_CONF_SERIALIZE << 0); \ return *(NAME##_dma_nextid_ptr()); \ } \ \ @@ -101,10 +98,8 @@ *(NAME##_dma_src_ptr()) = (uint64_t)src; \ *(NAME##_dma_dst_ptr()) = (uint64_t)dst; \ *(NAME##_dma_num_bytes_ptr()) = size; \ - *(NAME##_dma_conf_ptr()) = \ - (DMA_CONF_DECOUPLE << IDMA_REG64_2D_FRONTEND_CONF_DECOUPLE_BIT) | \ - (DMA_CONF_DEBURST << IDMA_REG64_2D_FRONTEND_CONF_DEBURST_BIT) | \ - (DMA_CONF_SERIALIZE << IDMA_REG64_2D_FRONTEND_CONF_SERIALIZE_BIT); \ + *(NAME##_dma_conf_ptr()) = (DMA_CONF_DECOUPLE << IDMA_REG64_2D_CONF_DECOUPLE_AW_BIT) | \ + (DMA_CONF_DEBURST << 0) | (DMA_CONF_SERIALIZE << 0); \ *(NAME##_dma_src_stride_ptr()) = src_stride; \ *(NAME##_dma_dst_stride_ptr()) = dst_stride; \ *(NAME##_dma_num_reps_ptr()) = num_reps; \ @@ -127,4 +122,4 @@ X(sys, &__base_dma); -#undef X +#undef X \ No newline at end of file diff --git a/sw/include/dif/uart.h b/sw/include/dif/uart.h index 134ec814..15a4731c 100644 --- a/sw/include/dif/uart.h +++ b/sw/include/dif/uart.h @@ -42,6 +42,8 @@ uint8_t uart_read(void *uart_base); void uart_read_str(void *uart_base, void *dst, uint64_t len); // Default UART provides console -void _putchar(char byte); +void uart_open(); + +void _putchar(char character); char _getchar(); diff --git a/sw/include/regs/idma.h b/sw/include/regs/idma.h index 7aa43052..b77785b2 100644 --- a/sw/include/regs/idma.h +++ b/sw/include/regs/idma.h @@ -1,57 +1,302 @@ -// Generated register defines for idma_reg64_2d_frontend +// Generated register defines for idma_reg64_2d // Copyright information found in source file: -// Copyright 2022 ETH Zurich and University of Bologna. +// Copyright 2023 ETH Zurich and University of Bologna. // Licensing information found in source file: -// Licensed under Solderpad Hardware License, Version 0.51 +// // SPDX-License-Identifier: SHL-0.51 -#ifndef _IDMA_REG64_2D_FRONTEND_REG_DEFS_ -#define _IDMA_REG64_2D_FRONTEND_REG_DEFS_ +#ifndef _IDMA_REG64_2D_REG_DEFS_ +#define _IDMA_REG64_2D_REG_DEFS_ #ifdef __cplusplus extern "C" { #endif +// Number of dimensions available +#define IDMA_REG64_2D_PARAM_NUM_DIMS 2 + // Register width -#define IDMA_REG64_2D_FRONTEND_PARAM_REG_WIDTH 64 +#define IDMA_REG64_2D_PARAM_REG_WIDTH 32 -// Source Address -#define IDMA_REG64_2D_FRONTEND_SRC_ADDR_REG_OFFSET 0x0 +// Configuration Register for DMA settings +#define IDMA_REG64_2D_CONF_REG_OFFSET 0x0 +#define IDMA_REG64_2D_CONF_DECOUPLE_AW_BIT 0 +#define IDMA_REG64_2D_CONF_DECOUPLE_RW_BIT 1 +#define IDMA_REG64_2D_CONF_SRC_REDUCE_LEN_BIT 2 +#define IDMA_REG64_2D_CONF_DST_REDUCE_LEN_BIT 3 +#define IDMA_REG64_2D_CONF_SRC_MAX_LLEN_MASK 0x7 +#define IDMA_REG64_2D_CONF_SRC_MAX_LLEN_OFFSET 4 +#define IDMA_REG64_2D_CONF_SRC_MAX_LLEN_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_CONF_SRC_MAX_LLEN_MASK, .index = IDMA_REG64_2D_CONF_SRC_MAX_LLEN_OFFSET }) +#define IDMA_REG64_2D_CONF_DST_MAX_LLEN_MASK 0x7 +#define IDMA_REG64_2D_CONF_DST_MAX_LLEN_OFFSET 7 +#define IDMA_REG64_2D_CONF_DST_MAX_LLEN_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_CONF_DST_MAX_LLEN_MASK, .index = IDMA_REG64_2D_CONF_DST_MAX_LLEN_OFFSET }) +#define IDMA_REG64_2D_CONF_ENABLE_ND_BIT 10 -// Destination Address -#define IDMA_REG64_2D_FRONTEND_DST_ADDR_REG_OFFSET 0x8 +// DMA Status (common parameters) +#define IDMA_REG64_2D_STATUS_BUSY_FIELD_WIDTH 10 +#define IDMA_REG64_2D_STATUS_BUSY_FIELDS_PER_REG 3 +#define IDMA_REG64_2D_STATUS_MULTIREG_COUNT 16 -// Number of bytes -#define IDMA_REG64_2D_FRONTEND_NUM_BYTES_REG_OFFSET 0x10 +// DMA Status +#define IDMA_REG64_2D_STATUS_0_REG_OFFSET 0x4 +#define IDMA_REG64_2D_STATUS_0_BUSY_0_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_0_BUSY_0_OFFSET 0 +#define IDMA_REG64_2D_STATUS_0_BUSY_0_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_0_BUSY_0_MASK, .index = IDMA_REG64_2D_STATUS_0_BUSY_0_OFFSET }) -// Configuration Register for DMA settings -#define IDMA_REG64_2D_FRONTEND_CONF_REG_OFFSET 0x18 -#define IDMA_REG64_2D_FRONTEND_CONF_DECOUPLE_BIT 0 -#define IDMA_REG64_2D_FRONTEND_CONF_DEBURST_BIT 1 -#define IDMA_REG64_2D_FRONTEND_CONF_SERIALIZE_BIT 2 +// DMA Status +#define IDMA_REG64_2D_STATUS_1_REG_OFFSET 0x8 +#define IDMA_REG64_2D_STATUS_1_BUSY_1_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_1_BUSY_1_OFFSET 0 +#define IDMA_REG64_2D_STATUS_1_BUSY_1_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_1_BUSY_1_MASK, .index = IDMA_REG64_2D_STATUS_1_BUSY_1_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_2_REG_OFFSET 0xc +#define IDMA_REG64_2D_STATUS_2_BUSY_2_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_2_BUSY_2_OFFSET 0 +#define IDMA_REG64_2D_STATUS_2_BUSY_2_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_2_BUSY_2_MASK, .index = IDMA_REG64_2D_STATUS_2_BUSY_2_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_3_REG_OFFSET 0x10 +#define IDMA_REG64_2D_STATUS_3_BUSY_3_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_3_BUSY_3_OFFSET 0 +#define IDMA_REG64_2D_STATUS_3_BUSY_3_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_3_BUSY_3_MASK, .index = IDMA_REG64_2D_STATUS_3_BUSY_3_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_4_REG_OFFSET 0x14 +#define IDMA_REG64_2D_STATUS_4_BUSY_4_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_4_BUSY_4_OFFSET 0 +#define IDMA_REG64_2D_STATUS_4_BUSY_4_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_4_BUSY_4_MASK, .index = IDMA_REG64_2D_STATUS_4_BUSY_4_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_5_REG_OFFSET 0x18 +#define IDMA_REG64_2D_STATUS_5_BUSY_5_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_5_BUSY_5_OFFSET 0 +#define IDMA_REG64_2D_STATUS_5_BUSY_5_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_5_BUSY_5_MASK, .index = IDMA_REG64_2D_STATUS_5_BUSY_5_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_6_REG_OFFSET 0x1c +#define IDMA_REG64_2D_STATUS_6_BUSY_6_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_6_BUSY_6_OFFSET 0 +#define IDMA_REG64_2D_STATUS_6_BUSY_6_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_6_BUSY_6_MASK, .index = IDMA_REG64_2D_STATUS_6_BUSY_6_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_7_REG_OFFSET 0x20 +#define IDMA_REG64_2D_STATUS_7_BUSY_7_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_7_BUSY_7_OFFSET 0 +#define IDMA_REG64_2D_STATUS_7_BUSY_7_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_7_BUSY_7_MASK, .index = IDMA_REG64_2D_STATUS_7_BUSY_7_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_8_REG_OFFSET 0x24 +#define IDMA_REG64_2D_STATUS_8_BUSY_8_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_8_BUSY_8_OFFSET 0 +#define IDMA_REG64_2D_STATUS_8_BUSY_8_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_8_BUSY_8_MASK, .index = IDMA_REG64_2D_STATUS_8_BUSY_8_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_9_REG_OFFSET 0x28 +#define IDMA_REG64_2D_STATUS_9_BUSY_9_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_9_BUSY_9_OFFSET 0 +#define IDMA_REG64_2D_STATUS_9_BUSY_9_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_9_BUSY_9_MASK, .index = IDMA_REG64_2D_STATUS_9_BUSY_9_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_10_REG_OFFSET 0x2c +#define IDMA_REG64_2D_STATUS_10_BUSY_10_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_10_BUSY_10_OFFSET 0 +#define IDMA_REG64_2D_STATUS_10_BUSY_10_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_10_BUSY_10_MASK, .index = IDMA_REG64_2D_STATUS_10_BUSY_10_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_11_REG_OFFSET 0x30 +#define IDMA_REG64_2D_STATUS_11_BUSY_11_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_11_BUSY_11_OFFSET 0 +#define IDMA_REG64_2D_STATUS_11_BUSY_11_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_11_BUSY_11_MASK, .index = IDMA_REG64_2D_STATUS_11_BUSY_11_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_12_REG_OFFSET 0x34 +#define IDMA_REG64_2D_STATUS_12_BUSY_12_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_12_BUSY_12_OFFSET 0 +#define IDMA_REG64_2D_STATUS_12_BUSY_12_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_12_BUSY_12_MASK, .index = IDMA_REG64_2D_STATUS_12_BUSY_12_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_13_REG_OFFSET 0x38 +#define IDMA_REG64_2D_STATUS_13_BUSY_13_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_13_BUSY_13_OFFSET 0 +#define IDMA_REG64_2D_STATUS_13_BUSY_13_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_13_BUSY_13_MASK, .index = IDMA_REG64_2D_STATUS_13_BUSY_13_OFFSET }) // DMA Status -#define IDMA_REG64_2D_FRONTEND_STATUS_REG_OFFSET 0x20 -#define IDMA_REG64_2D_FRONTEND_STATUS_BUSY_BIT 0 +#define IDMA_REG64_2D_STATUS_14_REG_OFFSET 0x3c +#define IDMA_REG64_2D_STATUS_14_BUSY_14_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_14_BUSY_14_OFFSET 0 +#define IDMA_REG64_2D_STATUS_14_BUSY_14_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_14_BUSY_14_MASK, .index = IDMA_REG64_2D_STATUS_14_BUSY_14_OFFSET }) + +// DMA Status +#define IDMA_REG64_2D_STATUS_15_REG_OFFSET 0x40 +#define IDMA_REG64_2D_STATUS_15_BUSY_15_MASK 0x3ff +#define IDMA_REG64_2D_STATUS_15_BUSY_15_OFFSET 0 +#define IDMA_REG64_2D_STATUS_15_BUSY_15_FIELD \ + ((bitfield_field32_t) { .mask = IDMA_REG64_2D_STATUS_15_BUSY_15_MASK, .index = IDMA_REG64_2D_STATUS_15_BUSY_15_OFFSET }) + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +// (common parameters) +#define IDMA_REG64_2D_NEXT_ID_NEXT_ID_FIELD_WIDTH 32 +#define IDMA_REG64_2D_NEXT_ID_NEXT_ID_FIELDS_PER_REG 1 +#define IDMA_REG64_2D_NEXT_ID_MULTIREG_COUNT 16 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_0_REG_OFFSET 0x44 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_1_REG_OFFSET 0x48 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_2_REG_OFFSET 0x4c // Next ID, launches transfer, returns 0 if transfer not set up properly. -#define IDMA_REG64_2D_FRONTEND_NEXT_ID_REG_OFFSET 0x28 +#define IDMA_REG64_2D_NEXT_ID_3_REG_OFFSET 0x50 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_4_REG_OFFSET 0x54 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_5_REG_OFFSET 0x58 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_6_REG_OFFSET 0x5c + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_7_REG_OFFSET 0x60 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_8_REG_OFFSET 0x64 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_9_REG_OFFSET 0x68 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_10_REG_OFFSET 0x6c + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_11_REG_OFFSET 0x70 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_12_REG_OFFSET 0x74 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_13_REG_OFFSET 0x78 + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_14_REG_OFFSET 0x7c + +// Next ID, launches transfer, returns 0 if transfer not set up properly. +#define IDMA_REG64_2D_NEXT_ID_15_REG_OFFSET 0x80 + +// Get ID of finished transactions. (common parameters) +#define IDMA_REG64_2D_DONE_ID_DONE_ID_FIELD_WIDTH 32 +#define IDMA_REG64_2D_DONE_ID_DONE_ID_FIELDS_PER_REG 1 +#define IDMA_REG64_2D_DONE_ID_MULTIREG_COUNT 16 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_0_REG_OFFSET 0x84 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_1_REG_OFFSET 0x88 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_2_REG_OFFSET 0x8c + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_3_REG_OFFSET 0x90 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_4_REG_OFFSET 0x94 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_5_REG_OFFSET 0x98 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_6_REG_OFFSET 0x9c // Get ID of finished transactions. -#define IDMA_REG64_2D_FRONTEND_DONE_REG_OFFSET 0x30 +#define IDMA_REG64_2D_DONE_ID_7_REG_OFFSET 0xa0 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_8_REG_OFFSET 0xa4 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_9_REG_OFFSET 0xa8 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_10_REG_OFFSET 0xac + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_11_REG_OFFSET 0xb0 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_12_REG_OFFSET 0xb4 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_13_REG_OFFSET 0xb8 + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_14_REG_OFFSET 0xbc + +// Get ID of finished transactions. +#define IDMA_REG64_2D_DONE_ID_15_REG_OFFSET 0xc0 + +// Low destination address +#define IDMA_REG64_2D_DST_ADDR_LOW_REG_OFFSET 0xd0 + +// High destination address +#define IDMA_REG64_2D_DST_ADDR_HIGH_REG_OFFSET 0xd4 + +// Low source address +#define IDMA_REG64_2D_SRC_ADDR_LOW_REG_OFFSET 0xd8 + +// High source address +#define IDMA_REG64_2D_SRC_ADDR_HIGH_REG_OFFSET 0xdc + +// Low transfer length in byte +#define IDMA_REG64_2D_LENGTH_LOW_REG_OFFSET 0xe0 + +// High transfer length in byte +#define IDMA_REG64_2D_LENGTH_HIGH_REG_OFFSET 0xe4 + +// Low destination stride dimension 2 +#define IDMA_REG64_2D_DST_STRIDE_2_LOW_REG_OFFSET 0xe8 + +// High destination stride dimension 2 +#define IDMA_REG64_2D_DST_STRIDE_2_HIGH_REG_OFFSET 0xec + +// Low source stride dimension 2 +#define IDMA_REG64_2D_SRC_STRIDE_2_LOW_REG_OFFSET 0xf0 -// Source Stride -#define IDMA_REG64_2D_FRONTEND_STRIDE_SRC_REG_OFFSET 0x38 +// High source stride dimension 2 +#define IDMA_REG64_2D_SRC_STRIDE_2_HIGH_REG_OFFSET 0xf4 -// Destination Stride -#define IDMA_REG64_2D_FRONTEND_STRIDE_DST_REG_OFFSET 0x40 +// Low number of repetitions dimension 2 +#define IDMA_REG64_2D_REPS_2_LOW_REG_OFFSET 0xf8 -// Number of 2D repetitions -#define IDMA_REG64_2D_FRONTEND_NUM_REPETITIONS_REG_OFFSET 0x48 +// High number of repetitions dimension 2 +#define IDMA_REG64_2D_REPS_2_HIGH_REG_OFFSET 0xfc #ifdef __cplusplus } // extern "C" #endif -#endif // _IDMA_REG64_2D_FRONTEND_REG_DEFS_ -// End generated register defines for idma_reg64_2d_frontend \ No newline at end of file +#endif // _IDMA_REG64_2D_REG_DEFS_ +// End generated register defines for idma_reg64_2d \ No newline at end of file diff --git a/sw/include/smp.h b/sw/include/smp.h index d13d8757..b6a26f33 100644 --- a/sw/include/smp.h +++ b/sw/include/smp.h @@ -17,11 +17,27 @@ csrr reg2, mhartid; \ bne reg1, reg2, 2f +// If the two harts are lockestepped at reset or peremanetly locked, we must +// see a single Hart ID at boot. Otherwise we see NUM_INT_HARTS. +// The procedure to set/unset the CLINT MSIP registers for the two harts is +// the following: +// 0. We read the number of physical harts (NUM_INT_HARTS) in reg3. +// 1. We read the DMR enabled register from the HMR unit in reg2. +// 2. We compute the number of virtual harts: +// 2a. If reg2=1, we divide NUM_INT_HARTS by 2 (reg3 >> reg2). +// 2b. If reg2=0, we divide NUM_INT_HARTS by 1 (reg3 >> reg2). +// 3. We multiply the number of virtual harts by 4: +// 3a. If reg2=1, the result is 4 (reg3 << 2). +// 3b. If reg2=0, the result is 8 (reg3 << 2). +// 4. Consequently, we compute the MSIP offset to access the CLINT. #define smp_resume(reg1, reg2, reg3) \ la reg1, __base_clint; \ la reg3, __base_regs; \ lw reg3, 76(reg3); /* regs.NUM_INT_HARTS */ \ - slli reg3, reg3, 2; \ + la reg2, __base_hmr; \ + lw reg2, 512(reg2); /* DMR en/dis */ \ + srl reg3, reg3, reg2; \ + sll reg3, reg3, 2; \ add reg3, reg1, reg3; \ 1:; \ li reg2, 1; \ diff --git a/sw/include/util.h b/sw/include/util.h index 46dcedb2..a1a0c9e5 100644 --- a/sw/include/util.h +++ b/sw/include/util.h @@ -80,3 +80,33 @@ static inline void *gprw(void *gp) { if (!(cond)) return (ret); #define MIN(a, b) (((a) <= (b)) ? (a) : (b)) + +// Read hart ID +static inline unsigned int hart_id() { + int hart_id; + asm volatile("csrr %0, mhartid" : "=r"(hart_id) :); + return hart_id; +} + +// Disable data caches +static inline void disable_dcache() { + asm volatile("csrrwi x0, 0x701, 0x0 \n\t" : : : "memory"); +} + +// Enable data caches +static inline void enable_dcache() { + asm volatile("csrrwi x0, 0x701, 0x1 \n\t" : : : "memory"); +} + +// The following is for future DMR support +// Wake up sleeping hart using CLINT +// static inline void wakeup_hart(unsigned int hart_id) { +// *reg32(&__base_clint, 0x4*hart_id) = 0x1; +// *reg32(&__base_clint, 0x4*hart_id) = 0x0; +// } + +// Write synchronization request in dedicated register +// static inline void sync_req(unsigned int hart_id){ +// uint32_t sync_reg = *reg32(&__base_regs, CHESHIRE_HARTS_SYNC_REG_OFFSET); +// *reg32(&__base_regs, CHESHIRE_HARTS_SYNC_REG_OFFSET) = sync_reg | (0x1 << hart_id); +// } diff --git a/sw/lib/crt0.S b/sw/lib/crt0.S index ebf372ad..1f9e0de2 100644 --- a/sw/lib/crt0.S +++ b/sw/lib/crt0.S @@ -176,4 +176,4 @@ _trap_handler_wrap: .global trap_vector .weak trap_vector trap_vector: - j trap_vector + j trap_vector \ No newline at end of file diff --git a/sw/lib/dif/uart.c b/sw/lib/dif/uart.c index 09cef30a..a190af0c 100644 --- a/sw/lib/dif/uart.c +++ b/sw/lib/dif/uart.c @@ -5,6 +5,8 @@ // Nils Wistoff // Paul Scheffler +#include "regs/cheshire.h" +#include "dif/clint.h" #include "dif/uart.h" #include "util.h" #include "params.h" @@ -64,8 +66,15 @@ void uart_read_str(void *uart_base, void *dst, uint64_t len) { } // Default UART provides console -void _putchar(char byte) { - uart_write(&__base_uart, byte); +void uart_open() { + uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); + uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); + uart_init(&__base_uart, reset_freq, 115200); +}; + +void _putchar(char character) { + uart_write(&__base_uart, character); + uart_write_flush(&__base_uart); }; char _getchar() { diff --git a/sw/link/common.ldh b/sw/link/common.ldh index b9bdb43c..f3a9a40c 100644 --- a/sw/link/common.ldh +++ b/sw/link/common.ldh @@ -43,6 +43,7 @@ SECTIONS { __base_gpio = 0x03005000; __base_slink = 0x03006000; __base_vga = 0x03007000; + __base_hmr = 0x0300B000; __base_plic = 0x04000000; __base_spm = ORIGIN(spm); __base_dram = ORIGIN(dram); diff --git a/sw/sw.mk b/sw/sw.mk index 89987310..da518442 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -79,7 +79,7 @@ endef $(eval $(call chs_sw_gen_hdr_rule,clint,$(CLINTROOT)/src/clint.hjson $(CLINTROOT)/.generated)) $(eval $(call chs_sw_gen_hdr_rule,serial_link,$(CHS_ROOT)/hw/serial_link.hjson $(CHS_SLINK_DIR)/.generated)) $(eval $(call chs_sw_gen_hdr_rule,axi_vga,$(AXI_VGA_ROOT)/data/axi_vga.hjson $(AXI_VGA_ROOT)/.generated)) -$(eval $(call chs_sw_gen_hdr_rule,idma,$(IDMA_ROOT)/src/frontends/register_64bit_2d/idma_reg64_2d_frontend.hjson)) +$(eval $(call chs_sw_gen_hdr_rule,idma,$(IDMA_ROOT)/target/rtl/idma_reg64_2d.hjson)) $(eval $(call chs_sw_gen_hdr_rule,axi_llc,$(CHS_LLC_DIR)/data/axi_llc_regs.hjson)) $(eval $(call chs_sw_gen_hdr_rule,cheshire,$(CHS_ROOT)/hw/regs/cheshire_regs.hjson)) $(eval $(call chs_sw_gen_hdr_rule,axi_rt,$(AXIRTROOT)/src/regs/axi_rt.hjson $(AXIRTROOT)/.generated)) diff --git a/sw/tests/axirt_budget.c b/sw/tests/axirt_budget.c index 72ec0281..f36e6b06 100644 --- a/sw/tests/axirt_budget.c +++ b/sw/tests/axirt_budget.c @@ -59,4 +59,4 @@ int main(void) { volatile uint8_t mismatch = read_budget != write_budget; return mismatch | (difference << 1); -} +} \ No newline at end of file diff --git a/sw/tests/ethernet.c b/sw/tests/ethernet.c new file mode 100644 index 00000000..adefe5b1 --- /dev/null +++ b/sw/tests/ethernet.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include "printf.h" +#include "util.h" + +#define ETH_BASE 0x0300c000 + +#define MACLO_OFFSET 0x0 +#define MACHI_OFFSET 0x4 +#define IRQ_OFFSET 0x18 +#define IDMA_SRC_ADDR_OFFSET 0x1c +#define IDMA_DST_ADDR_OFFSET 0x20 +#define IDMA_LENGTH_OFFSET 0x24 +#define IDMA_SRC_PROTO_OFFSET 0x28 +#define IDMA_DST_PROTO_OFFSET 0x2c +#define IDMA_REQ_VALID_OFFSET 0x44 +#define IDMA_REQ_READY_OFFSET 0x48 +#define IDMA_RSP_READY_OFFSET 0x4c +#define IDMA_RSP_VALID_OFFSET 0x50 +#define IDMA_RX_EN_OFFSET 0x54 +#define ETH_MDIO_OFFSET 0x8 + +#define PLIC_BASE 0x04000000 +#define RV_PLIC_PRIO19_REG_OFFSET 0x4c +#define RV_PLIC_IE0_0_REG_OFFSET 0x2000 +#define RV_PLIC_CC0_REG_OFFSET 0x200004 +#define RV_PLIC_IE0_0_E_19_BIT 19 +#define PLIC_ENABLE_REG_BASE PLIC_BASE + RV_PLIC_IE0_0_REG_OFFSET +#define PLIC_CLAIM_COMPLETE_BASE PLIC_BASE + RV_PLIC_CC0_REG_OFFSET + +#define RV_PLIC_IP_0_OFFSET 0x1000 + +#define DATA_CHUNK 8 + +#define BYTE_SIZE 8 + +#define TX_BASE 0x14000000 +#define RX_BASE 0x14001000 + +//#define PRINTF_ON + +int main(void) { + + #ifdef PRINTF_ON + printf ("Start test Ethernet...\n\r"); + #endif + + *reg32(PLIC_BASE, RV_PLIC_PRIO19_REG_OFFSET) = 1; + *reg32(PLIC_BASE, RV_PLIC_IE0_0_REG_OFFSET) |= (1 << (RV_PLIC_IE0_0_E_19_BIT)); // Enable interrupt number ; + + volatile uint64_t data_to_write[DATA_CHUNK] = { + 0x0207230100890702, + 0x3210400020709800, + 0x1716151413121110, + 0x2726252423222120, + 0x3736353433323130, + 0x4746454443424140, + 0x5756555453525150, + 0x6766656463626160 + }; + + // load data into mem + for (int i = 0; i < DATA_CHUNK; ++i) { + volatile uint64_t *tx_addr = (volatile uint64_t*)(TX_BASE + i * sizeof(uint64_t)); + *tx_addr = data_to_write[i]; + } + + *reg32(ETH_BASE, MACLO_OFFSET) = 0x89000123; + // High 16 bit Mac Address + *reg32(ETH_BASE, MACHI_OFFSET) = 0x00800207; + // DMA Source Address + *reg32(ETH_BASE, IDMA_SRC_ADDR_OFFSET) = TX_BASE; + // DMA Destination Address + *reg32(ETH_BASE, IDMA_DST_ADDR_OFFSET) = 0x0; + // Data length + *reg32(ETH_BASE, IDMA_LENGTH_OFFSET) = DATA_CHUNK*BYTE_SIZE; + // Source Protocol + *reg32(ETH_BASE, IDMA_SRC_PROTO_OFFSET) = 0x0; + // Destination Protocol + *reg32(ETH_BASE, IDMA_DST_PROTO_OFFSET) = 0x5; + + while(!(*reg32(ETH_BASE, IDMA_REQ_READY_OFFSET))); + // Validate Request to DMA + *reg32(ETH_BASE, IDMA_REQ_VALID_OFFSET) = 0x1; + // DMA completes data moving + while (!(*reg32(ETH_BASE, IDMA_RSP_VALID_OFFSET))); + + // configure ethernet + *reg32(ETH_BASE, MACLO_OFFSET) = 0x89000123; + *reg32(ETH_BASE, MACHI_OFFSET) = 0x00800207; + // rx irq + while (!((*reg32(PLIC_BASE, RV_PLIC_IP_0_OFFSET)) & (1 << 19) )); + // dma length ready, dma can be configured now + while (!(*reg32(ETH_BASE,IDMA_RX_EN_OFFSET))); + + *reg32(ETH_BASE, IDMA_SRC_ADDR_OFFSET) = 0x0; + *reg32(ETH_BASE, IDMA_DST_ADDR_OFFSET) = RX_BASE; + *reg32(ETH_BASE, IDMA_SRC_PROTO_OFFSET) = 0x5; + *reg32(ETH_BASE, IDMA_DST_PROTO_OFFSET) = 0x0; + + while(!(*reg32(ETH_BASE, IDMA_REQ_READY_OFFSET))); + *reg32(ETH_BASE, IDMA_REQ_VALID_OFFSET) = 0x1; + + // wait until DMA moves all data + while (!(*reg32(ETH_BASE, IDMA_RSP_VALID_OFFSET))); + + volatile uint32_t error = 0; + + for (int i = 0; i < DATA_CHUNK; ++i) { + volatile uint64_t *rx_addr = (volatile uint64_t*)(RX_BASE + i * sizeof(uint64_t)); + volatile uint64_t data_read = *rx_addr; + + if (data_read != data_to_write[i]) { + //printf("Error at index %d: expected 0x%lx, got 0x%lx\n", i, data_to_write[i], data_read); + error++; + } + } + + return error; +} diff --git a/sw/tests/idma.c b/sw/tests/idma.c new file mode 100644 index 00000000..fb0a92b2 --- /dev/null +++ b/sw/tests/idma.c @@ -0,0 +1,54 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Chaoqun Liang +// +// Simple payload to test iDMA + +#include +#include +#include +#include "util.h" +#include "printf.h" + +#define IDMA_BASE 0x01000000 +#define SRC_ADDR 0x14000000 +#define DST_ADDR 0x14000100 + +#define IDMA_SRC_ADDR_OFFSET 0x000000d8 +#define IDMA_DST_ADDR_OFFSET 0x000000d0 +#define IDMA_LENGTH_OFFSET 0x000000e0 +#define IDMA_NEXT_ID_OFFSET 0x00000044 +#define IDMA_REPS_2 0x000000f8 +#define IDMA_CONF 0x00000000 + +int main(void) { + int err = 0; + volatile uint64_t src_data[8] = {0x1032207098001032, 0x3210E20020709800, 0x1716151413121110, + 0x2726252423222120, 0x3736353433323130, 0x4746454443424140, + 0x5756555453525150, 0x6766656463626160}; + // load data into src address + for (int i = 0; i < 8; ++i) { + volatile uint64_t *src_addr = (volatile uint64_t *)(SRC_ADDR + i * sizeof(uint64_t)); + *src_addr = src_data[i]; + } + *reg32(IDMA_BASE, IDMA_SRC_ADDR_OFFSET) = SRC_ADDR; + *reg32(IDMA_BASE, IDMA_DST_ADDR_OFFSET) = DST_ADDR; + *reg32(IDMA_BASE, IDMA_LENGTH_OFFSET) = 0x00000040; + *reg32(IDMA_BASE, IDMA_CONF) = 0x1 << 10; + *reg32(IDMA_BASE, IDMA_REPS_2) = 0x00000001; + // ID has to be read to make it work + uint32_t id = *reg32(IDMA_BASE, IDMA_NEXT_ID_OFFSET); + for (int i = 0; i < 8; ++i) { + volatile uint64_t *dst_addr = (volatile uint64_t *)(DST_ADDR + i * sizeof(uint64_t)); + uint64_t dst_data = *dst_addr; + if (dst_data != src_data[i]) { + err++; + } + } + if (err != 0) { + printf("idma failed\n"); + } else + return 0; +} diff --git a/target/sim/src/fixture_cheshire_soc.sv b/target/sim/src/fixture_cheshire_soc.sv index 00f0c493..e0fa0a93 100644 --- a/target/sim/src/fixture_cheshire_soc.sv +++ b/target/sim/src/fixture_cheshire_soc.sv @@ -49,6 +49,20 @@ module fixture_cheshire_soc #( logic i2c_scl_i; logic i2c_scl_en; + logic eth_clk125; + logic eth_clk125q; + logic eth_rxck; + logic [3:0] eth_rxd; + logic eth_rxctl; + logic eth_txck; + logic [3:0] eth_txd; + logic eth_txctl; + logic eth_rstn; + logic eth_mdio_i; + logic eth_mdio_o; + logic eth_mdio_en; + logic eth_mdc; + logic spih_sck_o; logic spih_sck_en; logic [SpihNumCs-1:0] spih_csb_o; @@ -115,6 +129,19 @@ module fixture_cheshire_soc #( .i2c_scl_o ( i2c_scl_o ), .i2c_scl_i ( i2c_scl_i ), .i2c_scl_en_o ( i2c_scl_en ), + .eth_clk125_i ( eth_clk125 ), + .eth_clk125q_i ( eth_clk125q ), + .eth_rxck_i ( eth_rxck ), + .eth_rxd_i ( eth_rxd ), + .eth_rxctl_i ( eth_rxctl ), + .eth_txck_o ( eth_txck ), + .eth_txd_o ( eth_txd ), + .eth_txctl_o ( eth_txctl ), + .eth_rstn_o ( eth_rstn ), + .eth_mdio_i ( 1'b0 ),// eth_mdio_i + .eth_mdio_o ( eth_mdio_o ), + .eth_mdio_oe ( eth_mdio_en ), + .eth_mdc_o ( eth_mdc ), .spih_sck_o ( spih_sck_o ), .spih_sck_en_o ( spih_sck_en ), .spih_csb_o ( spih_csb_o ), @@ -147,6 +174,8 @@ module fixture_cheshire_soc #( wire [SpihNumCs-1:0] spih_csb; wire [ 3:0] spih_sd; + wire eth_mdio; + vip_cheshire_soc_tristate vip_tristate (.*); /////////// diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index cfdc05f4..dae761b0 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -8,6 +8,7 @@ // Collects all existing verification IP (VIP) in one module for use in testbenches of // Cheshire-based SoCs and Chips. IOs are of inout direction where applicable. +`include "register_interface/assign.svh" module vip_cheshire_soc import cheshire_pkg::*; #( // DUT (must be set) @@ -20,6 +21,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( parameter time ClkPeriodSys = 5ns, parameter time ClkPeriodJtag = 20ns, parameter time ClkPeriodRtc = 30518ns, + parameter time ClkPeriodEth = 8ns, parameter int unsigned RstCycles = 5, parameter real TAppl = 0.1, parameter real TTest = 0.9, @@ -67,6 +69,18 @@ module vip_cheshire_soc import cheshire_pkg::*; #( inout wire spih_sck, inout wire [SpihNumCs-1:0] spih_csb, inout wire [ 3:0] spih_sd, + // Ethernet interface + output logic eth_clk125, + output logic eth_clk125q, + input logic [ 3:0] eth_txd, + output logic [ 3:0] eth_rxd, + input logic eth_txck, + output logic eth_rxck, + input logic eth_txctl, + output logic eth_rxctl, + input logic eth_rstn, + inout logic eth_mdio, + input logic eth_mdc, // Serial link interface output logic [SlinkNumChan-1:0] slink_rcv_clk_i, input logic [SlinkNumChan-1:0] slink_rcv_clk_o, @@ -592,6 +606,199 @@ module vip_cheshire_soc import cheshire_pkg::*; #( $readmemh(image, i_spi_norflash.Mem); endtask + /////////////////// + // Ethernet // + /////////////////// + import idma_pkg::*; + localparam REG_BUS_AW = 32; + localparam REG_BUS_DW = 32; + + typedef reg_test::reg_driver #( + .AW(REG_BUS_AW), + .DW(REG_BUS_DW), + .TT(ClkPeriodSys * TTest), + .TA(ClkPeriodSys * TAppl) + ) reg_bus_drv_t; + + REG_BUS #( + .DATA_WIDTH(REG_BUS_DW), + .ADDR_WIDTH(REG_BUS_AW) + ) reg_bus_rx ( + .clk_i(clk) + ); + + logic reg_error, eth_rx_irq; + logic dma_en; + logic [REG_BUS_DW-1:0] rx_rsp_valid; + + reg_bus_drv_t reg_drv_rx = new(reg_bus_rx); + + reg_req_t reg_bus_rx_req; + reg_rsp_t reg_bus_rx_rsp; + + `REG_BUS_ASSIGN_TO_REQ (reg_bus_rx_req, reg_bus_rx) + `REG_BUS_ASSIGN_FROM_RSP (reg_bus_rx, reg_bus_rx_rsp) + + axi_mst_req_t axi_req_mem; + axi_mst_rsp_t axi_rsp_mem; + + eth_idma_wrap#( + .DataWidth ( DutCfg.AxiDataWidth ), + .AddrWidth ( DutCfg.AddrWidth ), + .UserWidth ( DutCfg.AxiUserWidth ), + .AxiIdWidth ( DutCfg.AxiMstIdWidth ), + .NumAxInFlight ( 32'd15 ), + .BufferDepth ( 32'd2 ), + .TFLenWidth ( 32'd20 ), + .MemSysDepth ( 32'd0 ), + .TxFifoLogDepth ( 32'd2 ), + .RxFifoLogDepth ( 32'd3 ), + .axi_req_t ( axi_mst_req_t ), + .axi_rsp_t ( axi_mst_rsp_t ), + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ) + ) i_rx_eth_idma_wrap ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .eth_clk125_i ( eth_clk125 ), + .eth_clk125q_i ( eth_clk125q ), + .phy_rx_clk_i ( eth_txck ), + .phy_rxd_i ( eth_txd ), + .phy_rx_ctl_i ( eth_txctl ), + .phy_tx_clk_o ( eth_rxck ), + .phy_txd_o ( eth_rxd ), + .phy_tx_ctl_o ( eth_rxctl ), + .phy_resetn_o ( eth_rstn ), + .phy_intn_i ( 1'b1 ), + .phy_pme_i ( 1'b1 ), + .phy_mdio_i ( 1'b0 ), + .phy_mdio_o ( eth_mdio_o ), + .phy_mdio_oe ( eth_mdio_oe ), + .phy_mdc_o ( eth_mdc ), + .reg_req_i ( reg_bus_rx_req ), + .reg_rsp_o ( reg_bus_rx_rsp ), + .testmode_i ( 1'b0 ), + .axi_req_o ( axi_req_mem ), + .axi_rsp_i ( axi_rsp_mem ), + .eth_rx_irq_o ( eth_rx_irq ) + ); + + axi_sim_mem #( + .AddrWidth ( DutCfg.AddrWidth ), + .DataWidth ( DutCfg.AxiDataWidth ), + .IdWidth ( DutCfg.AxiMstIdWidth ), + .UserWidth ( DutCfg.AxiUserWidth ), + .axi_req_t ( axi_mst_req_t ), + .axi_rsp_t ( axi_mst_rsp_t ), + .WarnUninitialized ( 1'b0 ), + .ClearErrOnAccess ( 1'b1 ), + .ApplDelay ( ClkPeriodSys * TAppl ), + .AcqDelay ( ClkPeriodSys * TTest ), + .UninitializedData ( "zeros" ) + ) i_rx_axi_sim_mem ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .axi_req_i ( axi_req_mem ), + .axi_rsp_o ( axi_rsp_mem ) + ); + + initial begin + forever begin + eth_clk125 <= 1; + #(ClkPeriodEth/2); + eth_clk125 <= 0; + #(ClkPeriodEth/2); + end + end + + initial begin + forever begin + eth_clk125q <= 0; + #(ClkPeriodEth/4); + eth_clk125q <= 1; + #(ClkPeriodEth/2); + eth_clk125q <= 0; + #(ClkPeriodEth/4); + end + end + + initial begin + + wait_for_reset(); + + @(posedge clk) + + reg_drv_rx.send_write( 'h0300c000, 32'h89000123, 'hf, reg_error); //lower 32bits of MAC address + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c004, 32'h00800207, 'hf, reg_error); //upper 16bits of MAC address + other configuration set to false/0 + @(posedge clk); + + @(posedge eth_rx_irq); + + while(1) begin + reg_drv_rx.send_read( 'h0300c054, dma_en, reg_error); // req ready with packet length + if( dma_en ) + break; + @(posedge clk); + end + + reg_drv_rx.send_write( 'h0300c01c, 32'h0, 'hf, reg_error ); // SRC_ADDR + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c020, 32'h0, 'hf, reg_error); // DST_ADDR + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c028, 32'h5,'hf , reg_error); // src protocol + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c02c, 32'h0,'hf , reg_error); // dst protocol + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c044, 'h1, 'hf , reg_error); // req valid + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c044, 'h0, 'hf , reg_error); // req valid + @(posedge clk); + + //wait till all data written into rx_axi_sim_mem + while(1) begin + reg_drv_rx.send_read( 'h0300c050, rx_rsp_valid, reg_error); + if( rx_rsp_valid ) begin + break; + end + @(posedge clk); + end + + // Tx test starts here: external back to core + reg_drv_rx.send_write( 'h0300c000, 32'h89000123, 'hf, reg_error); //lower 32bits of MAC address + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c004, 32'h00800207, 'hf, reg_error); //upper 16bits of MAC address + other configuration set to false/0 + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c01c, 32'h0, 'hf, reg_error ); // SRC_ADDR + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c020, 32'h0, 'hf, reg_error); // DST_ADDR + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c024, 32'h40,'hf , reg_error); // Size in bytes + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c028, 32'h0,'hf , reg_error); // src protocol + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c02c, 32'h5,'hf , reg_error); // dst protocol + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c044, 'h1, 'hf , reg_error); // req valid + @(posedge clk); + + reg_drv_rx.send_write( 'h0300c044, 'h0, 'hf , reg_error); // req valid + @(posedge clk); + end + /////////////////// // Serial Link // /////////////////// @@ -930,13 +1137,19 @@ module vip_cheshire_soc_tristate import cheshire_pkg::*; ( output logic [ 3:0] spih_sd_i, input logic [ 3:0] spih_sd_o, input logic [ 3:0] spih_sd_en, + // Ethernet pad IO + input logic eth_mdio_o, + output logic eth_mdio_i, + input logic eth_mdio_en, // I2C wires inout wire i2c_sda, inout wire i2c_scl, // SPI host wires inout wire spih_sck, inout wire [SpihNumCs-1:0] spih_csb, - inout wire [ 3:0] spih_sd + inout wire [ 3:0] spih_sd, + // Ethernet wires + inout wire eth_mdio ); // I2C @@ -962,4 +1175,8 @@ module vip_cheshire_soc_tristate import cheshire_pkg::*; ( pullup (spih_csb[i]); end + // Ethernet + bufif1 (eth_mdio_i, eth_mdio, ~eth_mdio_en); + bufif1 (eth_mdio, eth_mdio_o, eth_mdio_en); + endmodule diff --git a/target/sim/vsim/start.cheshire_soc.tcl b/target/sim/vsim/start.cheshire_soc.tcl index f9d6cad2..91082a27 100644 --- a/target/sim/vsim/start.cheshire_soc.tcl +++ b/target/sim/vsim/start.cheshire_soc.tcl @@ -12,7 +12,7 @@ set TESTBENCH tb_cheshire_soc # Set voptargs only if not already set to make overridable. # Default on fast simulation flags. if {![info exists VOPTARGS]} { - set VOPTARGS "-O5 +acc=p+tb_cheshire_soc. +noacc=p+cheshire_soc. +acc=r+stream_xbar" + set VOPTARGS "-O5 +acc" } set flags "-permissive -suppress 3009 -suppress 8386 -error 7 " diff --git a/target/xilinx/constraints/genesys2.xdc b/target/xilinx/constraints/genesys2.xdc index 18debabc..e5bf3098 100644 --- a/target/xilinx/constraints/genesys2.xdc +++ b/target/xilinx/constraints/genesys2.xdc @@ -14,6 +14,8 @@ # 200 MHz input clock set SYS_TCK 5 create_clock -period $SYS_TCK -name sys_clk [get_ports sys_clk_p] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets sys_clk] + # SoC clock is generated by clock wizard and its constraints set SOC_TCK 20.0 @@ -54,6 +56,9 @@ set MIG_RST_O [get_pins i_dram_wrapper/i_dram/ui_clk_sync_rst] set_false_path -hold -through $MIG_RST_O set_max_delay -through $MIG_RST_O $MIG_TCK +set_false_path -from [get_pins i_vio/inst/PROBE_OUT_ALL_INST/G_PROBE_OUT[0].PROBE_OUT0_INST/Probe_out_reg[*]/C] -to [get_pins i_dram_wrapper/i_dram/u_mig7s_mig/u_ddr3_infrastructure/rstdiv0_sync_r*_reg_rep__*/PRE] + + # Limit delay across DRAM CDC (hold already false-pathed) set_max_delay -datapath_only \ -from [get_pins i_dram_wrapper/gen_cdc.i_axi_cdc_mig/i_axi_cdc_*/i_cdc_fifo_gray_*/*reg*/C] \ @@ -104,14 +109,15 @@ set_property -dict { PACKAGE_PIN AD12 IOSTANDARD LVDS } [get_ports { sys_cl set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports { sys_resetn }]; #IO_0_14 Sch=cpu_resetn ## Switches -set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS12 } [get_ports { boot_mode_i[0] }]; #IO_0_17 Sch=sw[0] -set_property -dict { PACKAGE_PIN G25 IOSTANDARD LVCMOS12 } [get_ports { boot_mode_i[1] }]; #IO_25_16 Sch=sw[1] -set_property -dict { PACKAGE_PIN H24 IOSTANDARD LVCMOS12 } [get_ports { fan_sw[0] }]; #IO_L19P_T3_16 Sch=sw[2] -set_property -dict { PACKAGE_PIN K19 IOSTANDARD LVCMOS12 } [get_ports { fan_sw[1] }]; #IO_L6P_T0_17 Sch=sw[3] -set_property -dict { PACKAGE_PIN N19 IOSTANDARD LVCMOS12 } [get_ports { fan_sw[2] }]; #IO_L19P_T3_A22_15 Sch=sw[4] -set_property -dict { PACKAGE_PIN P19 IOSTANDARD LVCMOS12 } [get_ports { fan_sw[3] }]; #IO_25_15 Sch=sw[5] +set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS18 } [get_ports { boot_mode_i[0] }]; #IO_0_17 Sch=sw[0] +set_property -dict { PACKAGE_PIN G25 IOSTANDARD LVCMOS18 } [get_ports { boot_mode_i[1] }]; #IO_25_16 Sch=sw[1] +set_property -dict { PACKAGE_PIN H24 IOSTANDARD LVCMOS18 } [get_ports { fan_sw[0] }]; #IO_L19P_T3_16 Sch=sw[2] +set_property -dict { PACKAGE_PIN K19 IOSTANDARD LVCMOS18 } [get_ports { fan_sw[1] }]; #IO_L6P_T0_17 Sch=sw[3] +set_property -dict { PACKAGE_PIN N19 IOSTANDARD LVCMOS18 } [get_ports { fan_sw[2] }]; #IO_L19P_T3_A22_15 Sch=sw[4] +set_property -dict { PACKAGE_PIN P19 IOSTANDARD LVCMOS18 } [get_ports { fan_sw[3] }]; #IO_25_15 Sch=sw[5] set_property -dict { PACKAGE_PIN P27 IOSTANDARD LVCMOS33 } [get_ports { test_mode_i }]; #IO_L8P_T1_D11_14 Sch=sw[7] + # UART set_property -dict { PACKAGE_PIN Y23 IOSTANDARD LVCMOS33 } [get_ports { uart_tx_o }]; #IO_L1P_T0_12 Sch=uart_rx_out set_property -dict { PACKAGE_PIN Y20 IOSTANDARD LVCMOS33 } [get_ports { uart_rx_i }]; #IO_0_12 Sch=uart_tx_in @@ -126,6 +132,36 @@ set_property -dict { PACKAGE_PIN T30 IOSTANDARD LVCMOS33 } [get_ports { sd_d_i set_property -dict { PACKAGE_PIN AE24 IOSTANDARD LVCMOS33 } [get_ports { sd_reset_o }]; #IO_L12N_T1_MRCC_12 Sch=sd_reset set_property -dict { PACKAGE_PIN R28 IOSTANDARD LVCMOS33 } [get_ports { sd_sclk_o }]; #IO_L11P_T1_SRCC_14 Sch=sd_sclk +# Ethernet +set_property -dict {PACKAGE_PIN A25 IOSTANDARD LVCMOS18} [get_ports { eth_rxd[0] }]; #IO_L21N_T3_DQS_33 Sch=eth_rx_d[0] +set_property -dict {PACKAGE_PIN E26 IOSTANDARD LVCMOS18} [get_ports { eth_rxd[1] }]; #IO_L21P_T3_DQS_33 Sch=eth_rx_d[1] +set_property -dict {PACKAGE_PIN F26 IOSTANDARD LVCMOS18} [get_ports { eth_rxd[2] }]; #IO_L20N_T3_33 Sch=eth_rx_d[2] +set_property -dict {PACKAGE_PIN E25 IOSTANDARD LVCMOS18} [get_ports { eth_rxd[3] }]; #IO_L22P_T3_33 Sch=eth_rx_d[3] +set_property -dict {PACKAGE_PIN A26 IOSTANDARD LVCMOS18} [get_ports { eth_rxctl }]; #IO_L18P_T2_33 Sch=eth_rx_ctl +set_property -dict {PACKAGE_PIN F25 IOSTANDARD LVCMOS18} [get_ports { eth_rxck }]; #IO_L13P_T2_MRCC_33 Sch=eth_rx_clk +set_property -dict {PACKAGE_PIN H27 IOSTANDARD LVCMOS18} [get_ports { eth_txd[0] }]; #IO_L22N_T3_33 Sch=eth_tx_d[0] +set_property -dict {PACKAGE_PIN H26 IOSTANDARD LVCMOS18} [get_ports { eth_txd[1] }]; #IO_L17P_T2_33 Sch=eth_tx_d[1] +set_property -dict {PACKAGE_PIN E30 IOSTANDARD LVCMOS18} [get_ports { eth_txd[2] }]; #IO_L18N_T2_33 Sch=eth_tx_d[2] +set_property -dict {PACKAGE_PIN E29 IOSTANDARD LVCMOS18} [get_ports { eth_txd[3] }]; #IO_L17N_T2_33 Sch=eth_tx_d[3] +set_property -dict {PACKAGE_PIN G30 IOSTANDARD LVCMOS18} [get_ports { eth_txctl }]; #IO_L20P_T3_33 Sch=eth_tx_en +set_property -dict {PACKAGE_PIN C29 IOSTANDARD LVCMOS18} [get_ports { eth_txck }]; #IO_L14P_T2_SRCC_33 Sch=eth_tx_clk +set_property -dict {PACKAGE_PIN C27 IOSTANDARD LVCMOS18} [get_ports { eth_mdio }]; #IO_L23N_T3_33 Sch=eth_mdio +set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS18} [get_ports { eth_mdc }]; #IO_L23P_T3_33 Sch=eth_mdc +#set_property -dict {PACKAGE_PIN H30 IOSTANDARD LVCMOS18} [get_ports { eth_int_b }]; #IO_L1P_T0_32 Sch=eth_intb +#set_property -dict {PACKAGE_PIN B29 IOSTANDARD LVCMOS18} [get_ports { eth_pme_b }]; #IO_L1N_T0_32 Sch=eth_pmeb +set_property -dict {PACKAGE_PIN D27 IOSTANDARD LVCMOS18} [get_ports { eth_rst_n }]; #IO_L14N_T2_SRCC_12 Sch=eth_phyrst_n + +############################################# +# Ethernet Constraints for 1Gb/s +############################################# +# Modified for 125MHz receive clock +create_clock -period 8.000 -name eth_rxck [get_ports eth_rxck] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets eth_rxck_IBUF] + +set_clock_groups -asynchronous -group [get_clocks eth_rxck -include_generated_clocks] +set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins i_clkwiz/clk_125]] + + # VGA Connector set_property -dict { PACKAGE_PIN AH20 IOSTANDARD LVCMOS33 } [get_ports { vga_blue_o[0] }]; #IO_L22N_T3_12 Sch=vga_b[3] set_property -dict { PACKAGE_PIN AG20 IOSTANDARD LVCMOS33 } [get_ports { vga_blue_o[1] }]; #IO_L22P_T3_12 Sch=vga_b[4] diff --git a/target/xilinx/scripts/impl_ip.tcl b/target/xilinx/scripts/impl_ip.tcl index 474787fe..1dc82bec 100644 --- a/target/xilinx/scripts/impl_ip.tcl +++ b/target/xilinx/scripts/impl_ip.tcl @@ -24,13 +24,15 @@ switch $proj { CONFIG.CLKOUT2_USED {true} \ CONFIG.CLKOUT3_USED {true} \ CONFIG.CLKOUT4_USED {true} \ - CONFIG.CLK_OUT1_PORT {clk_100} \ + CONFIG.CLK_OUT1_PORT {clk_200} \ CONFIG.CLK_OUT2_PORT {clk_50} \ - CONFIG.CLK_OUT3_PORT {clk_20} \ - CONFIG.CLK_OUT4_PORT {clk_10} \ + CONFIG.CLK_OUT3_PORT {clk_125} \ + CONFIG.CLK_OUT4_PORT {clk_125_90} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {200.000} \ CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {50.000} \ - CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20.000} \ - CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {10.000} \ + CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {125.000} \ + CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {125.000} \ + CONFIG.CLKOUT4_REQUESTED_PHASE {90.000} \ CONFIG.CLKIN1_JITTER_PS {50.0} \ CONFIG.MMCM_CLKFBOUT_MULT_F {5.000} \ CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ diff --git a/target/xilinx/src/cheshire_top_xilinx.sv b/target/xilinx/src/cheshire_top_xilinx.sv index 4e93b2bc..03938d7f 100644 --- a/target/xilinx/src/cheshire_top_xilinx.sv +++ b/target/xilinx/src/cheshire_top_xilinx.sv @@ -48,6 +48,18 @@ module cheshire_top_xilinx ( inout wire i2c_sda_io, `endif +`ifdef USE_ETHERNET + input wire eth_rxck, + input wire [3:0] eth_rxd, + input wire eth_rxctl, + output wire eth_txck, + output wire [3:0] eth_txd, + output wire eth_txctl, + output wire eth_rst_n, + output wire eth_mdc, + inout wire eth_mdio, +`endif + `ifdef USE_SD input logic sd_cd_i, output logic sd_cmd_o, @@ -101,6 +113,7 @@ module cheshire_top_xilinx ( endfunction // Configure cheshire for FPGA mapping + localparam cheshire_cfg_t FPGACfg = gen_cheshire_xilinx_cfg(); `CHESHIRE_TYPEDEF_ALL(, FPGACfg) @@ -110,6 +123,9 @@ module cheshire_top_xilinx ( wire sys_clk; wire soc_clk; + logic eth_clk_125; + logic eth_clk_90; + logic eth_clk_200; IBUFDS #( .IBUF_LOW_PWR ("FALSE") @@ -120,13 +136,13 @@ module cheshire_top_xilinx ( ); clkwiz i_clkwiz ( - .clk_in1 ( sys_clk ), - .reset ( '0 ), - .locked ( ), - .clk_100 ( ), - .clk_50 ( soc_clk ), - .clk_20 ( ), - .clk_10 ( ) + .clk_in1 ( sys_clk ), + .reset ( '0 ), + .locked ( ), + .clk_200 ( eth_clk_200 ), + .clk_50 ( soc_clk ), + .clk_125 ( eth_clk_125 ), + .clk_125_90 ( eth_clk_90 ) ); ///////////////////// @@ -236,8 +252,33 @@ module cheshire_top_xilinx ( .I ( i2c_sda_soc_out ), .T ( ~i2c_sda_en ) ); + `endif + + /////////////////////// + // Ethernet Adaption // + ////////////////////// + logic eth_mdio_i; + logic eth_mdio_o; + logic eth_mdio_oe; + + //`ifdef USE_ETHERNET + + IOBUF #( + .DRIVE ( 12 ), // Specify the output drive strength + .IBUF_LOW_PWR ( "FALSE" ), // Low Power - "TRUE", High Performance = "FALSE" + .IOSTANDARD ( "DEFAULT" ), // Specify the I/O standard + .SLEW ( "FAST" ) // Specify the output slew rate + ) i_md_iobuf ( + .O ( eth_mdio_i ), // Buffer output + .IO ( eth_mdio ), // Buffer inout port (connect directly to top-level port) + .I ( eth_mdio_o ), // Buffer input + .T ( ~eth_mdio_oe ) // 3-state enable input, high=input, low=output + ); + + //`endif + /////////////// // SPI to SD // /////////////// @@ -446,6 +487,20 @@ module cheshire_top_xilinx ( .i2c_scl_o ( i2c_scl_soc_out ), .i2c_scl_i ( i2c_scl_soc_in ), .i2c_scl_en_o ( i2c_scl_en ), + .eth_clk125_i ( eth_clk_125 ), + .eth_clk125q_i ( eth_clk_90 ), + .eth_clk200_i ( eth_clk_200 ), + .eth_rxck_i ( eth_rxck ), + .eth_rxd_i ( eth_rxd ), + .eth_rxctl_i ( eth_rxctl ), + .eth_txck_o ( eth_txck ), + .eth_txd_o ( eth_txd ), + .eth_txctl_o ( eth_txctl ), + .eth_rstn_o ( eth_rstn ), + .eth_mdio_i ( eth_mdio_i ), + .eth_mdio_o ( eth_mdio_o ), + .eth_mdio_oe ( eth_mdio_oe ), + .eth_mdc_o ( eth_mdc ), .spih_sck_o ( spi_sck_soc ), .spih_sck_en_o ( spi_sck_en ), .spih_csb_o ( spi_cs_soc ), diff --git a/target/xilinx/src/phy_definitions.svh b/target/xilinx/src/phy_definitions.svh index a4d7798d..bd14caf3 100644 --- a/target/xilinx/src/phy_definitions.svh +++ b/target/xilinx/src/phy_definitions.svh @@ -25,6 +25,7 @@ `define USE_VIO `define USE_I2C `define USE_VGA + `define USE_ETHERNET `endif `ifdef TARGET_ZCU102 diff --git a/target/xilinx/xilinx.mk b/target/xilinx/xilinx.mk index be35b5a9..465448e2 100644 --- a/target/xilinx/xilinx.mk +++ b/target/xilinx/xilinx.mk @@ -41,7 +41,7 @@ CHS_XILINX_IPS_genesys2 := clkwiz vio mig7s CHS_XILINX_IPS_vcu128 := clkwiz vio ddr4 $(CHS_XILINX_DIR)/scripts/add_sources.%.tcl: $(CHS_ROOT)/Bender.yml - $(BENDER) script vivado -t fpga -t cv64a6_imafdcsclic_sv39 -t cva6 -t $* > $@ + $(BENDER) script vivado -t fpga -t cv64a6_imafdcsclic_sv39 -t cva6 -t rtl -t snitch_cluster -t $* > $@ define chs_xilinx_bit_rule $$(CHS_XILINX_DIR)/out/%.$(1).bit: \