diff --git a/Bender.local b/Bender.local index e89e2063..24076262 100644 --- a/Bender.local +++ b/Bender.local @@ -3,19 +3,10 @@ # SPDX-License-Identifier: SHL-0.51 overrides: - axi: { git: https://github.com/pulp-platform/axi.git , version: 0.39.1 } - axi_riscv_atomics: { git: https://github.com/pulp-platform/axi_riscv_atomics.git , version: 0.8.2 } - apb: { git: "https://github.com/pulp-platform/apb.git" , version: 0.2.3 } - register_interface: { git: "https://github.com/pulp-platform/register_interface.git" , version: 0.4.1 } redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git" , rev: astral-v0 } tech_cells_generic: { git: "https://github.com/pulp-platform/tech_cells_generic.git" , version: =0.2.13 } - riscv-dbg: { git: "https://github.com/pulp-platform/riscv-dbg.git" , version: =0.8.0 } - idma: { git: "https://github.com/pulp-platform/idma.git" , version: 0.5.1 } scm: { git: "https://github.com/pulp-platform/scm.git" , rev: 74426dee36f28ae1c02f7635cf844a0156145320 } - clic: { git: "https://github.com/pulp-platform/clic.git" , rev: 0ff9f07e0a492bff046dfe24399b1e1e82d557b7 } # branch: balasr/dev-2 - fpnew: { git: "https://github.com/pulp-platform/cvfpu.git" , rev: pulp-v0.1.3 } cv32e40p: { git: "https://github.com/pulp-platform/cv32e40p.git" , rev: e863f576699815b38cc9d80dbdede8ed5efd5991 } - axi_rt: { git: "https://github.com/pulp-platform/axi_rt.git" , version: =0.0.0-alpha.4 } serial_link: { git: "https://github.com/pulp-platform/serial_link.git" , rev: 4024f01b1d67cdf1cf9486467d0f2e2f407aa372 } neureka: { git: "https://github.com/pulp-platform/neureka.git" , rev: f6b9a014c7ff4c536865c8ad376b383d4026f286 } softex: { git: "https://github.com/belanoa/softex.git" , rev: a93ddff106ca3596660584ce6c7f77fb2a8475e3 } diff --git a/Bender.lock b/Bender.lock index 5be2b7b8..db38e527 100644 --- a/Bender.lock +++ b/Bender.lock @@ -24,8 +24,8 @@ packages: - obi_peripherals - register_interface axi: - revision: fccffb5953ec8564218ba05e20adbedec845e014 - version: 0.39.1 + revision: 78831b6feba265d5ee2683bbf42b4150f8a35c43 + version: 0.39.8 source: Git: https://github.com/pulp-platform/axi.git dependencies: @@ -48,10 +48,10 @@ packages: dependencies: - axi_slice axi_llc: - revision: 7d7fc1349d4915a657de535a491bc26fbf0d2cfa + revision: d8d41097c43e1bf8448bd40f258fdeb8482a9a8c version: null source: - Git: https://github.com/pulp-platform/axi_llc + Git: https://github.com/pulp-platform/axi_llc.git dependencies: - axi - common_cells @@ -77,8 +77,8 @@ packages: - common_cells - common_verification axi_rt: - revision: 2be9d4028cd3fd6617a0302a53212495a4c4e3fa - version: 0.0.0-alpha.4 + revision: 50153a346b753dc2bc7723c446656a43db35d02d + version: 0.0.0-alpha.10 source: Git: https://github.com/pulp-platform/axi_rt.git dependencies: @@ -92,6 +92,13 @@ packages: Git: https://github.com/pulp-platform/axi_slice.git dependencies: - common_cells + axi_stream: + revision: 54891ff40455ca94a37641b9da4604647878cc07 + version: 0.1.1 + source: + Git: https://github.com/pulp-platform/axi_stream.git + dependencies: + - common_cells axi_vga: revision: 4d3e70d4f47bb74edc1ab68d99ffc02382e0fb9e version: 0.1.4 @@ -108,7 +115,7 @@ packages: Git: git@github.com:AlSaqr-platform/can_bus.git dependencies: [] cheshire: - revision: 0c95210cf242c384fafe3019e84b8974c3ff1e92 + revision: ce7b0270e1bbce8bb0fe5b006115bbf03a423670 version: null source: Git: https://github.com/pulp-platform/cheshire.git @@ -124,6 +131,7 @@ packages: - common_cells - common_verification - cva6 + - dram_rtl_sim - idma - irq_router - opentitan_peripherals @@ -133,8 +141,8 @@ packages: - tagger - unbent clic: - revision: 0ff9f07e0a492bff046dfe24399b1e1e82d557b7 - version: 3.0.0-for-carfield + revision: 72472df17362734e4d2ac2bcb8c80a452fba9808 + version: 3.0.0-rc5 source: Git: https://github.com/pulp-platform/clic.git dependencies: @@ -196,7 +204,7 @@ packages: - fpnew - tech_cells_generic cva6: - revision: ec242579ea25a1f6bef7235591814dd1e475f90c + revision: 39e65c9918423ba20985771a0fbd8ad93f18c802 version: null source: Git: https://github.com/pulp-platform/cva6.git @@ -205,6 +213,13 @@ packages: - common_cells - fpnew - tech_cells_generic + dram_rtl_sim: + revision: 2cac4a9e12a60537567276b539ab6c919c87b5dc + version: 0.1.1 + source: + Git: https://github.com/pulp-platform/dram_rtl_sim.git + dependencies: + - axi dyn_mem: revision: 480590062742230dc9bd4050358a15b4747bdf34 version: null @@ -234,7 +249,7 @@ packages: - fpnew - tech_cells_generic fpnew: - revision: a8e0cba6dd50f357ece73c2c955d96efc3c6c315 + revision: e5aa6a01b5bbe1675c3aa8872e1203413ded83d1 version: null source: Git: https://github.com/pulp-platform/cvfpu.git @@ -287,8 +302,8 @@ packages: dependencies: - tech_cells_generic hyperbus: - revision: 2a14bd8f9a985b488ee23d240764f52f129f7729 - version: 0.0.9 + revision: 841deb9d821b63bf05a1c85d3a4746352a8bcae2 + version: null source: Git: https://github.com/pulp-platform/hyperbus.git dependencies: @@ -310,14 +325,16 @@ packages: Git: https://github.com/pulp-platform/icache-intc.git dependencies: [] idma: - revision: ca1b28816a3706be0bf9ce01378246d5346384f0 - version: 0.5.1 + revision: ff5d56fffb3767814db88d6bf8f381974ea33aa5 + version: 0.6.4 source: - Git: https://github.com/pulp-platform/idma.git + Git: https://github.com/pulp-platform/iDMA.git dependencies: - axi + - axi_stream - common_cells - common_verification + - obi - register_interface irq_router: revision: d1d31350b24f3965b3a51e1bc96c71eb34e94db3 @@ -473,15 +490,15 @@ packages: - common_cells - common_verification riscv-dbg: - revision: 138d74bcaa90c70180c12215db3776813d2a95f2 - version: 0.8.0 + revision: 358f90110220adf7a083f8b65d157e836d706236 + version: 0.8.1 source: Git: https://github.com/pulp-platform/riscv-dbg.git dependencies: - common_cells - tech_cells_generic safety_island: - revision: aaef55c798ab53560faaf451a86668fa1e6d0f3b + revision: d9feaedcec1d2fa09fbb57cd1c910fa9a821a0de version: null source: Git: https://github.com/pulp-platform/safety_island.git @@ -530,7 +547,7 @@ packages: - hwpe-stream - ibex spatz: - revision: b8fea8f2386f837a0854ad4e84f25b70a3a430e0 + revision: b7474288e3945305b5b1c0e7300cc9ad17a222be version: null source: Git: https://github.com/pulp-platform/spatz.git diff --git a/Bender.yml b/Bender.yml index 92762aa6..6dea3ae5 100644 --- a/Bender.yml +++ b/Bender.yml @@ -12,11 +12,11 @@ package: dependencies: register_interface: { git: https://github.com/pulp-platform/register_interface.git, version: 0.4.2 } - axi: { git: https://github.com/pulp-platform/axi.git, version: 0.39.1 } - cheshire: { git: https://github.com/pulp-platform/cheshire.git, rev: 0c95210cf242c384fafe3019e84b8974c3ff1e92 } # branch: aottaviano/carfield - hyperbus: { git: https://github.com/pulp-platform/hyperbus.git, version: 0.0.9 } + axi: { git: https://github.com/pulp-platform/axi.git, version: 0.39.8 } + cheshire: { git: https://github.com/pulp-platform/cheshire.git, rev: ce7b0270e1bbce8bb0fe5b006115bbf03a423670 } # branch: carfield + hyperbus: { git: https://github.com/pulp-platform/hyperbus.git, rev: 841deb9d821b63bf05a1c85d3a4746352a8bcae2 } # branch: aottaviano/nonfree dyn_mem: { git: https://github.com/pulp-platform/dyn_spm.git, rev: 480590062742230dc9bd4050358a15b4747bdf34 } # branch: main - safety_island: { git: https://github.com/pulp-platform/safety_island.git, rev: aaef55c798ab53560faaf451a86668fa1e6d0f3b } # branch: carfield + safety_island: { git: https://github.com/pulp-platform/safety_island.git, rev: d9feaedcec1d2fa09fbb57cd1c910fa9a821a0de } # branch: carfield pulp_cluster: { git: https://github.com/pulp-platform/pulp_cluster.git, version: 3.0.3 } opentitan: { git: https://github.com/pulp-platform/opentitan.git, rev: 48595339c9bea8eddf7cc799bb74e6af5ec5d846 } # branch: carfield-soc mailbox_unit: { git: git@github.com:pulp-platform/mailbox_unit.git, version: 1.1.0 } @@ -24,7 +24,7 @@ dependencies: timer_unit: { git: https://github.com/pulp-platform/timer_unit.git, version: 1.0.2 } apb_adv_timer: { git: https://github.com/pulp-platform/apb_adv_timer.git, version: 1.0.4 } can_bus: { git: git@github.com:AlSaqr-platform/can_bus.git, rev: 0ec0bf8b7dab6d5e4b3f7ec58338a8efee066379 } # branch: pulp - spatz: { git: https://github.com/pulp-platform/spatz.git, rev: b8fea8f2386f837a0854ad4e84f25b70a3a430e0 } # branch: main + spatz: { git: https://github.com/pulp-platform/spatz.git, rev: b7474288e3945305b5b1c0e7300cc9ad17a222be } # branch: main common_cells: { git: https://github.com/pulp-platform/common_cells.git, version: 1.31.1 } pulp-ethernet: { git: https://github.com/pulp-platform/pulp-ethernet.git, rev: bdc8031ab270a49da28df269266ce9ab9a133636 } # branch: carfield riscv-dbg: { git: https://github.com/pulp-platform/riscv-dbg.git, version: =0.8.0 } diff --git a/bender-common.mk b/bender-common.mk index 3a688e48..3d3c7ad0 100644 --- a/bender-common.mk +++ b/bender-common.mk @@ -15,7 +15,7 @@ common_targs += -t spatz common_targs += -t integer_cluster common_targs += -t cv32e40p_use_ff_regfile common_targs += -t scm_use_fpga_scm -common_targs += -t cv64a6_imafdcsclic_sv39 +common_targs += -t cv64a6_carfield common_targs += -t rtl common_targs += -t deprecated # Carfield config target. diff --git a/carfield.mk b/carfield.mk index dddfab0b..f09f4b86 100644 --- a/carfield.mk +++ b/carfield.mk @@ -127,9 +127,14 @@ PLIC_NUM_INTRS := 89 SERIAL_LINK_NUM_BITS := 16 # AXI Real-Time unit configuration in Carfield +# CVA60, CVA61, DBG, SYSDMA, SL, USB, SAFED, SECD, SPATZD, PULPD AXIRT_NUM_MGRS := 10 AXIRT_NUM_SUBS := 2 +# LLC partitioning configuration +CHS_LLC_PARTITION := 1 +CHS_LLC_MAXPARTITIONS := 16 + ########################## # Dependency maintenance # ########################## diff --git a/hw/carfield_pkg.sv b/hw/carfield_pkg.sv index 9fd14db2..02cef8c7 100644 --- a/hw/carfield_pkg.sv +++ b/hw/carfield_pkg.sv @@ -591,13 +591,34 @@ typedef struct packed { // Cheshire configuration localparam cheshire_cfg_t CheshireCfg = '{ // CVA6 parameters - Cva6RASDepth : ariane_pkg::ArianeDefaultConfig.RASDepth, - Cva6BTBEntries : ariane_pkg::ArianeDefaultConfig.BTBEntries, - Cva6BHTEntries : ariane_pkg::ArianeDefaultConfig.BHTEntries, + Cva6RASDepth : 2, + Cva6BTBEntries : 32, + Cva6BHTEntries : 128, Cva6NrPMPEntries : 0, Cva6ExtCieLength : 'h1000_0000, // [0x2000_0000, 0x7000_0000) is non-CIE, // [0x7000_0000, 0x8000_0000) is CIE Cva6ExtCieOnTop : 1, + Cva6NrScoreboardEntries : 8, + Cva6MaxOutstandingStores : 7, + Cva6IcacheByteSize : 16384, + Cva6IcacheSetAssoc : 4, + Cva6IcacheLineWidth : 128, + Cva6DCacheType : config_pkg::WB, + Cva6DcacheByteSize : 32768, + Cva6DcacheSetAssoc : 8, + Cva6DcacheLineWidth : 128, + Cva6DcacheFlushOnFence : 1, + Cva6DcacheInvalidateOnFlush : 0, + Cva6InstrTlbEntries : 16, + Cva6DataTlbEntries : 16, + Cva6LockableTlbWays : 8, + Cva6NumTlbColors : 4, + Cva6UseSharedTlb : 0, + Cva6SharedTlbDepth : 64, + Cva6NrLoadPipeRegs : 1, + Cva6NrStorePipeRegs : 0, + Cva6DcacheIdWidth : 1, + Cva6SuperscalarEn : 0, // Harts NumCores : 2, CoreMaxTxns : 8, @@ -610,11 +631,6 @@ localparam cheshire_cfg_t CheshireCfg = '{ NumExtOutIntrTgts : CarfieldNumRouterTargets, NumExtOutIntrs : CarfieldNumExtIntrs+$bits(cheshire_int_intr_t), ClicIntCtlBits : 8, - ClicUseSMode : 1, - ClicUseUMode : 0, - ClicUseVsMode : 1, - ClicUseVsModePrio : 1, - ClicNumVsCtxts : 2, // TODO: choose appropriately NumExtIntrSyncs : SyncStages, // Interconnect AddrWidth : 48, @@ -631,6 +647,7 @@ localparam cheshire_cfg_t CheshireCfg = '{ RegMaxWriteTxns : 8, RegAmoNumCuts : 1, RegAmoPostCut : 1, + RegAdaptMemCut : 1, // External AXI ports (at most 8 ports and rules) AxiExtNumMst : CarfieldAxiNumMasters, AxiExtNumSlv : CarfieldAxiNumSlaves, @@ -658,6 +675,7 @@ localparam cheshire_cfg_t CheshireCfg = '{ Dma : 1, SerialLink : 1, Vga : 0, + Usb : 1, AxiRt : 1, Clic : 1, IrqRouter : 1, @@ -691,29 +709,37 @@ localparam cheshire_cfg_t CheshireCfg = '{ LlcCachePartition : 1, LlcMaxPartition : 16, LlcRemapHash : axi_llc_pkg::Modulo, - // VGA: RGB332; carfield doesn't have a vga, but widths are required for top-level pins anyway. - VgaRedWidth : 3, - VgaGreenWidth : 3, - VgaBlueWidth : 2, + // VGA: RGB565; carfield doesn't have a vga, but widths are required for top-level pins anyway. + VgaRedWidth : 5, + VgaGreenWidth : 6, + VgaBlueWidth : 5, + VgaHCountWidth : 24, // TODO: Default is 32; is this needed? + VgaVCountWidth : 24, // TODO: See above + VgaBufferDepth : 16, + VgaMaxReadTxns : 24, // Serial Link: map other chip's lower 32bit to 'h1_000_0000 SlinkMaxTxnsPerId : 4, SlinkMaxUniqIds : 4, SlinkMaxClkDiv : 1024, - SlinkRegionStart : 'h1_0000_0000, - SlinkRegionEnd : 'h2_0000_0000, + SlinkRegionStart : 64'h1_0000_0000, + SlinkRegionEnd : 64'h2_0000_0000, SlinkTxAddrMask : 'hFFFF_FFFF, SlinkTxAddrDomain : 'h0000_0000, SlinkUserAmoBit : 3, // Convention: lower AMO bits for cores, MSB for serial link + // USB config + UsbDmaMaxReads : 16, + UsbAddrMask : 'hFFFF_FFFF, + UsbAddrDomain : 'h0000_0000, // DMA config DmaConfMaxReadTxns : 4, DmaConfMaxWriteTxns : 4, DmaConfAmoNumCuts : 1, + DmaConfAmoPostCut : 1, + DmaConfEnableTwoD : 1, DmaNumAxInFlight : 24, DmaMemSysDepth : 16, DmaJobFifoDepth : 4, DmaRAWCouplingAvail : 1, - DmaConfAmoPostCut : 1, - DmaConfEnableTwoD : 1, // GPIOs GpioInputSyncs : 1, // AXI RT @@ -722,6 +748,11 @@ localparam cheshire_cfg_t CheshireCfg = '{ AxiRtNumAddrRegions : 2, AxiRtCutPaths : 1, AxiRtEnableChecks : 0, + // CLIC + ClicVsclic : 0, + ClicVsprio : 0, + ClicNumVsctxts : 4, + ClicPrioWidth : 1, // All non-set values should be zero default: '0 }; diff --git a/requirements.txt b/requirements.txt index 404a13f6..492aff95 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,3 +14,4 @@ mkdocs-material mkdocs-glightbox dataclasses jstyleson +flatdict diff --git a/sw/tests/bare-metal/hostd/axirt_budget.c b/sw/tests/bare-metal/hostd/axirt_budget.c index 4eca0527..7133ec8e 100644 --- a/sw/tests/bare-metal/hostd/axirt_budget.c +++ b/sw/tests/bare-metal/hostd/axirt_budget.c @@ -3,61 +3,109 @@ // SPDX-License-Identifier: Apache-2.0 // // Thomas Benz +// Alessandro Ottaviano // -// Validate the budget functionality of AXI RT +// Validate the budget functionality of AXI-REALM #include "axirt.h" #include "dif/dma.h" -#include "regs/axi_rt.h" #include "params.h" +#include "regs/axi_rt.h" +#include "regs/cheshire.h" #include "util.h" -#include "car_util.h" - -// transfer -#define SIZE_BYTES 256 -#define SRC_STRIDE 0 -#define DST_STRIDE 0 -#define NUM_REPS 8 -#define SRC_ADDR 0x0000000010000000 // LLC SPM -#define DST_ADDR 0x0000000080000000 // DRAM -#define TOTAL_SIZE (SIZE_BYTES * NUM_REPS) +#define CVA6_BASE_MGR_ID 0 +#define CVA6_ALLOCATED_BUDGET 0x10000000 +#define CVA6_ALLOCATED_PERIOD 0x10000000 +#define DMA_NUM_BEATS 128 // We assume 64b AXI data width here +#define DMA_ALLOCATED_BUDGET 0x10000000 +#define DMA_ALLOCATED_PERIOD 0x10000000 +#define FRAGMENTATION_SIZE_BEATS 0 // Max fragmentation applied to bursts int main(void) { + // Immediately return an error if AXI_REALM or DMA are not present + CHECK_ASSERT(-1, chs_hw_feature_present(CHESHIRE_HW_FEATURES_AXIRT_BIT)); + CHECK_ASSERT(-2, chs_hw_feature_present(CHESHIRE_HW_FEATURES_DMA_BIT)); + + // This test requires at least two subordinate regions + CHECK_ASSERT(-3, AXI_RT_PARAM_NUM_SUB >= 2); + + // Get internal hart count + int num_int_harts = *reg32(&__base_regs, CHESHIRE_NUM_INT_HARTS_REG_OFFSET); - // enable and configure axi rt with fragmentation of 8 beats + // Allocate DMA buffers + volatile uint64_t dma_src_cached[DMA_NUM_BEATS]; + volatile uint64_t dma_dst_cached[DMA_NUM_BEATS]; + + // Use pointers to uncached buffers allocated in SPM + volatile uint64_t *dma_src = dma_src_cached + (0x04000000 / sizeof(uint64_t)); + volatile uint64_t *dma_dst = dma_dst_cached + (0x04000000 / sizeof(uint64_t)); + + // Declare non-volatile array for golden values + uint64_t golden[DMA_NUM_BEATS]; + + // Enable and configure axi rt __axirt_claim(1, 1); - __axirt_set_len_limit_group(7, 0); - - // configure CVA6 - __axirt_set_region(0, 0xffffffff, 0, 0); - __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, 0); - __axirt_set_budget(0x10000000, 0, 0); - __axirt_set_budget(0x10000000, 1, 0); - __axirt_set_period(0x10000000, 0, 0); - __axirt_set_period(0x10000000, 1, 0); - - // configure DMA - __axirt_set_region(0, 0xffffffff, 0, 2); - __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, 2); - __axirt_set_budget(0x10000000, 0, 2); - __axirt_set_budget(0x10000000, 1, 2); - __axirt_set_period(0x10000000, 0, 2); - __axirt_set_period(0x10000000, 1, 2); - - // enable RT unit for DMA and CVA6 - __axirt_enable(0x5); - - // launch DMA transfer - sys_dma_2d_blk_memcpy(DST_ADDR, SRC_ADDR, SIZE_BYTES, DST_STRIDE, SRC_STRIDE, NUM_REPS); - - // read budget registers and compare - volatile uint32_t read_budget = *reg32(&__base_axirt, AXI_RT_READ_BUDGET_LEFT_2_REG_OFFSET); - volatile uint32_t write_budget = *reg32(&__base_axirt, AXI_RT_WRITE_BUDGET_LEFT_2_REG_OFFSET); - - // check - volatile uint8_t difference = (TOTAL_SIZE - read_budget) + (TOTAL_SIZE - write_budget); - volatile uint8_t mismatch = read_budget != write_budget; - - return mismatch | (difference << 1); + __axirt_set_len_limit_group(FRAGMENTATION_SIZE_BEATS, 0); + __axirt_set_len_limit_group(FRAGMENTATION_SIZE_BEATS, 1); + fence(); + + // Configure RT unit for all the CVA6 cores + for (int id = CVA6_BASE_MGR_ID; id < num_int_harts; id++) { + __axirt_set_region(0, 0xffffffff, 0, id); + __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, id); + __axirt_set_budget(CVA6_ALLOCATED_BUDGET, 0, id); + __axirt_set_budget(CVA6_ALLOCATED_BUDGET, 1, id); + __axirt_set_period(CVA6_ALLOCATED_PERIOD, 0, id); + __axirt_set_period(CVA6_ALLOCATED_PERIOD, 1, id); + fence(); + } + + // Configure RT unit for the DMA + int chs_dma_id = CVA6_BASE_MGR_ID + num_int_harts + 1; + __axirt_set_region(0, 0xffffffff, 0, chs_dma_id); + __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, chs_dma_id); + __axirt_set_budget(DMA_ALLOCATED_BUDGET, 0, chs_dma_id); + __axirt_set_budget(DMA_ALLOCATED_BUDGET, 1, chs_dma_id); + __axirt_set_period(DMA_ALLOCATED_PERIOD, 0, chs_dma_id); + __axirt_set_period(DMA_ALLOCATED_PERIOD, 1, chs_dma_id); + fence(); + + // Enable RT unit for all the cores + __axirt_enable(BIT_MASK(num_int_harts)); + + // Enable RT unit for the DMA + __axirt_enable(BIT(chs_dma_id)); + fence(); + + // Initialize src region and golden values + for (int i = 0; i < DMA_NUM_BEATS; i++) { + golden[i] = 0xcafedeadbaadf00dULL + i; // Compute golden values + dma_src[i] = golden[i]; // Initialize source memory + } + + // Wait for writes, then launch blocking DMA transfer + fence(); + sys_dma_blk_memcpy((uintptr_t)(void *)dma_dst, (uintptr_t)(void *)dma_src, sizeof(golden), + DMA_CONF_DECOUPLE_ALL); + + // Check DMA transfers against gold. + for (int i = 0; i < DMA_NUM_BEATS; i++) CHECK_ASSERT(20 + i, dma_dst[i] == golden[i]); + + // Read budget registers for dma and compare + int dma_read_budget_left = + *reg32(&__base_axirt, AXI_RT_READ_BUDGET_LEFT_0_REG_OFFSET + + AXI_RT_PARAM_NUM_SUB * chs_dma_id * sizeof(uint32_t)); + int dma_write_budget_left = + *reg32(&__base_axirt, AXI_RT_WRITE_BUDGET_LEFT_0_REG_OFFSET + + AXI_RT_PARAM_NUM_SUB * chs_dma_id * sizeof(uint32_t)); + + // Check budget: return 0 if (initial budget - final budget) matches the + // number of transferred bytes, otherwise return 1 + int dma_r_difference = (DMA_ALLOCATED_BUDGET - dma_read_budget_left) != sizeof(golden); + int dma_w_difference = (DMA_ALLOCATED_BUDGET - dma_write_budget_left) != sizeof(golden); + // W and R are symmetric on the dma: left budgets should be equal + int dma_rw_mismatch = dma_read_budget_left != dma_write_budget_left; + + return dma_rw_mismatch + dma_r_difference + dma_w_difference; } diff --git a/sw/tests/bare-metal/hostd/axirt_budget_isolate.c b/sw/tests/bare-metal/hostd/axirt_budget_isolate.c new file mode 100644 index 00000000..03149531 --- /dev/null +++ b/sw/tests/bare-metal/hostd/axirt_budget_isolate.c @@ -0,0 +1,99 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Alessandro Ottaviano +// +// Validate the isolation functionality of AXI-REALM. + +#include "axirt.h" +#include "dif/dma.h" +#include "params.h" +#include "regs/axi_rt.h" +#include "regs/cheshire.h" +#include "util.h" + +#define CVA6_BASE_MGR_ID 0 +#define CVA6_ALLOCATED_BUDGET 0x10000000 +#define CVA6_ALLOCATED_PERIOD 0x10000000 +#define DMA_NUM_BEATS 32 // We assume 64b AXI data width here +#define DMA_NUM_REPS 8 +// Set DMA budget as half of the number of bytes to transfer. +// This is done intentionally to test isolation capabilities. +#define DMA_ALLOCATED_BUDGET (8 * DMA_NUM_BEATS * DMA_NUM_REPS / 2) +#define DMA_ALLOCATED_PERIOD 0x10000000 +#define FRAGMENTATION_SIZE_BEATS 0 // Max fragmentation applied to bursts + +int main(void) { + // Immediately return an error if AXI_REALM or DMA are not present + CHECK_ASSERT(-1, chs_hw_feature_present(CHESHIRE_HW_FEATURES_AXIRT_BIT)); + CHECK_ASSERT(-2, chs_hw_feature_present(CHESHIRE_HW_FEATURES_DMA_BIT)); + + // This test requires at least two subordinate regions + CHECK_ASSERT(-3, AXI_RT_PARAM_NUM_SUB >= 2); + + // Get internal hart count + int num_int_harts = *reg32(&__base_regs, CHESHIRE_NUM_INT_HARTS_REG_OFFSET); + + // Allocate DMA buffers + volatile uint64_t dma_src_cached[DMA_NUM_BEATS]; + volatile uint64_t dma_dst_cached[DMA_NUM_BEATS]; + + // Use pointers to uncached buffers allocated in SPM + volatile uint64_t *dma_src = dma_src_cached + (0x04000000 / sizeof(uint64_t)); + volatile uint64_t *dma_dst = dma_dst_cached + (0x04000000 / sizeof(uint64_t)); + + // Enable and configure axi rt + __axirt_claim(1, 1); + __axirt_set_len_limit_group(FRAGMENTATION_SIZE_BEATS, 0); + __axirt_set_len_limit_group(FRAGMENTATION_SIZE_BEATS, 1); + fence(); + + // Configure RT unit for all the CVA6 cores (adapt ID if needed). + for (int id = CVA6_BASE_MGR_ID; id < num_int_harts; id++) { + __axirt_set_region(0, 0xffffffff, 0, id); + __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, id); + __axirt_set_budget(CVA6_ALLOCATED_BUDGET, 0, id); + __axirt_set_budget(CVA6_ALLOCATED_BUDGET, 1, id); + __axirt_set_period(CVA6_ALLOCATED_PERIOD, 0, id); + __axirt_set_period(CVA6_ALLOCATED_PERIOD, 1, id); + fence(); + } + + // Configure RT unit for the DMA + int chs_dma_id = CVA6_BASE_MGR_ID + num_int_harts + 1; + __axirt_set_region(0, 0xffffffff, 0, chs_dma_id); + __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, chs_dma_id); + __axirt_set_budget(DMA_ALLOCATED_BUDGET, 0, chs_dma_id); + __axirt_set_budget(DMA_ALLOCATED_BUDGET, 1, chs_dma_id); + __axirt_set_period(DMA_ALLOCATED_PERIOD, 0, chs_dma_id); + __axirt_set_period(DMA_ALLOCATED_PERIOD, 1, chs_dma_id); + fence(); + + // Enable RT unit for all the cores + __axirt_enable(BIT_MASK(num_int_harts)); + + // Enable RT unit for the DMA + __axirt_enable(BIT(chs_dma_id)); + fence(); + + // Initialize src region and golden values + for (int i = 0; i < DMA_NUM_BEATS; i++) dma_src[i] = 0xcafedeadbaadf00dULL + i; + + // Wait for writes, then launch non-blocking DMA transfer + fence(); + sys_dma_2d_memcpy((uintptr_t)(void *)dma_dst, (uintptr_t)(void *)dma_src, + sizeof(dma_src_cached), 0, 0, DMA_NUM_REPS, DMA_CONF_DECOUPLE_ALL); + + // Wait 5000 cycles for isolation to kick in + uint64_t end_wait_cycles = get_mcycle() + 5000; + while (end_wait_cycles > get_mcycle()) + ; + + // Check isolate to check if AXI-REALM isolates the dma when the budget is + // exceeded. Should return 1 if dma is isolated. + int isolate_status = (*reg32(&__base_axirt, AXI_RT_ISOLATED_REG_OFFSET) >> chs_dma_id) & 1; + + // Return 0 if manager was correctly isolated + return !isolate_status; +} diff --git a/sw/tests/bare-metal/hostd/axirt_hello.c b/sw/tests/bare-metal/hostd/axirt_hello.c index 89714ef0..12dd3823 100644 --- a/sw/tests/bare-metal/hostd/axirt_hello.c +++ b/sw/tests/bare-metal/hostd/axirt_hello.c @@ -15,22 +15,25 @@ #include "regs/axi_rt.h" #include "params.h" #include "util.h" -#include "car_util.h" int main(void) { + // Immediately return an error if AXI_REALM, DMA, or UART are not present + CHECK_ASSERT(-1, chs_hw_feature_present(CHESHIRE_HW_FEATURES_AXIRT_BIT)); + CHECK_ASSERT(-2, chs_hw_feature_present(CHESHIRE_HW_FEATURES_DMA_BIT)); + CHECK_ASSERT(-3, chs_hw_feature_present(CHESHIRE_HW_FEATURES_UART_BIT)); - // Init the HW - car_init_start(); + // This test requires at least two subordinate regions + CHECK_ASSERT(-4, AXI_RT_PARAM_NUM_SUB >= 2); char str[] = "Hello AXI-RT!\r\n"; uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); - // enable and configure axi rt + // Enable and configure AXI REALM __axirt_claim(1, 1); __axirt_set_len_limit_group(2, 0); - // configure CVA6 + // Configure CVA6 core 0 __axirt_set_region(0, 0xffffffff, 0, 0); __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, 0); __axirt_set_budget(8, 0, 0); @@ -38,20 +41,21 @@ int main(void) { __axirt_set_period(100, 0, 0); __axirt_set_period(100, 1, 0); - // configure DMA - __axirt_set_region(0, 0xffffffff, 0, 2); - __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, 2); - __axirt_set_budget(0x10000000, 0, 2); - __axirt_set_budget(0x10000000, 1, 2); - __axirt_set_period(0x10000000, 0, 2); - __axirt_set_period(0x10000000, 1, 2); + // Configure DMA + int chs_dma_id = *reg32(&__base_regs, CHESHIRE_NUM_INT_HARTS_REG_OFFSET) + 1; + __axirt_set_region(0, 0xffffffff, 0, chs_dma_id); + __axirt_set_region(0x100000000, 0xffffffffffffffff, 1, chs_dma_id); + __axirt_set_budget(0x10000000, 0, chs_dma_id); + __axirt_set_budget(0x10000000, 1, chs_dma_id); + __axirt_set_period(0x10000000, 0, chs_dma_id); + __axirt_set_period(0x10000000, 1, chs_dma_id); - // enable RT unit for DMA and CVA6 + // Enable RT unit for DMA and CVA6 core 0 __axirt_enable(0x5); - // configure uart and write msg - uart_init(&__base_uart, reset_freq, 115200); - uart_write_str(&__base_uart, str, sizeof(str)); + // Configure UART and write message + uart_init(&__base_uart, reset_freq, __BOOT_BAUDRATE); + uart_write_str(&__base_uart, str, sizeof(str) - 1); uart_write_flush(&__base_uart); return 0; } diff --git a/sw/tests/bare-metal/hostd/clic_basic.S b/sw/tests/bare-metal/hostd/clic_basic.S new file mode 100644 index 00000000..7abda439 --- /dev/null +++ b/sw/tests/bare-metal/hostd/clic_basic.S @@ -0,0 +1,172 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Nils Wistoff +// +// Basic CLIC test. Based on https://github.com/pulp-platform/safety_island/blob/main/sw/tests/runtime_clic_basic/clic-basic.c + +#define xstr(s) str(s) +#define str(s) s +#define CLIC_BASE 0x08000000 +#define CLIC_CLICCFG_REG (CLIC_BASE + 0x0) +#define CLIC_CLICINT_REG(id) (CLIC_BASE + 0x1000 + 0x4 * id) +#define CLIC_CLICINT_IP_OFFSET (0) +#define CLIC_CLICINT_IP_MASK (1) +#define CLIC_CLICINT_IE_OFFSET (8) +#define CLIC_CLICINT_IE_MASK (1) +#define CLIC_CLICINT_ATTR_SHV_OFFSET (16) +#define CLIC_CLICINT_ATTR_SHV_MASK (1) +#define CLIC_CLICINT_ATTR_TRIG_OFFSET (17) +#define CLIC_CLICINT_ATTR_TRIG_MASK (0x3) +#define CLIC_CLICINT_ATTR_MODE_OFFSET (22) +#define CLIC_CLICINT_ATTR_MODE_MASK (0x3) +#define CLIC_CLICINT_CTL_OFFSET (24) +#define CLIC_CLICINT_CTL_MASK (0xff) + +.align +.option norvc +.global main +main: + // Enable interrupts (set mstatus.mie) + csrsi mstatus, 0x8 + + // Activate CLIC mode + la t0, mtvec_handler_fail + ori t0, t0, 0x3 + csrrw s0, mtvec, t0 + + // Write mtvt base + la t0, mtvt_handler + csrw 0x307, t0 // mtvt + + // Set shv of irq 31 + li t0, CLIC_CLICINT_REG(31) + li t1, 1 << CLIC_CLICINT_ATTR_SHV_OFFSET + sw t1, 0(t0) + + // set trigger type to edge-triggered + li t0, CLIC_CLICINT_REG(31) + lw t1, 0(t0) + li t2, 1 << CLIC_CLICINT_ATTR_TRIG_OFFSET + or t1, t1, t2 + sw t1, 0(t0) + + // enable irq31 via SW by writing to clicintip31 + li t0, CLIC_CLICINT_REG(31) + lw t1, 0(t0) + li t2, 1 << CLIC_CLICINT_IP_OFFSET + or t1, t1, t2 + sw t1, 0(t0) + + // set number of bits for level encoding + li t0, CLIC_CLICCFG_REG + li t1, 0x4 << 1 + sw t1, 0(t0) + + // set interrupt level and priority for interrupt 31 + li t0, CLIC_CLICINT_REG(31) + lw t1, 0(t0) + li t2, 0xaa << CLIC_CLICINT_CTL_OFFSET + or t1, t1, t2 + sw t1, 0(t0) + + // raise interrupt threshold to max and check that the interrupt doesn't fire yet + li a0, 0x1 + li t0, 0xff + csrw 0x347, t0 // mintthresh + li t0, CLIC_CLICINT_REG(31) + lw t1, 0(t0) + li t2, 1 << CLIC_CLICINT_IE_OFFSET + or t1, t1, t2 + sw t1, 0(t0) + + // wait + li t0, 500 +1: + addi t0, t0, -1 + bnez t0, 1b + + // lower interrupt threshold (interrupt should happen) + li a0, 0x0 + li t0, 0x0 + csrw 0x347, t0 // mintthresh + + // wait + li t0, 500 +2: + addi t0, t0, -1 + bnez t0, 2b + + j fail_restore + +pass_restore: + csrw mtvec, s0 + li a0, 0 + ret + +fail_restore: + csrw mtvec, s0 + li a0, 1 + ret + +thirtyone: + // a0=0: we should not get here, fail. else: we expect to get here, pass. + beqz a0, pass_restore + j fail_restore + + .align 8 + .global mtvt_handler +mtvt_handler: + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j thirtyone + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + + + .align 8 + .global mtvec_handler_fail +mtvec_handler_fail: + // Restore mtvec and fail + csrw mtvec, s0 + li a0, 1 + ret + +.data diff --git a/sw/tests/bare-metal/hostd/clic_multiple.S b/sw/tests/bare-metal/hostd/clic_multiple.S new file mode 100644 index 00000000..3c77267a --- /dev/null +++ b/sw/tests/bare-metal/hostd/clic_multiple.S @@ -0,0 +1,214 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Nils Wistoff +// +// Test clic. +// +// Queues two software interrupts with different interrupt levels. The lower +// level interrupt is queued first. Then raises the threshold to a level which is +// between those two interrupts. Only the latter interrupt should fire and be +// handled. + +#define xstr(s) str(s) +#define str(s) s +#define CLIC_BASE 0x08000000 +#define CLIC_CLICCFG_REG (CLIC_BASE + 0x0) +#define CLIC_CLICINT_REG(id) (CLIC_BASE + 0x1000 + 0x4 * id) +#define CLIC_CLICINT_IP_OFFSET (0) +#define CLIC_CLICINT_IP_MASK (1) +#define CLIC_CLICINT_IE_OFFSET (8) +#define CLIC_CLICINT_IE_MASK (1) +#define CLIC_CLICINT_ATTR_SHV_OFFSET (16) +#define CLIC_CLICINT_ATTR_SHV_MASK (1) +#define CLIC_CLICINT_ATTR_TRIG_OFFSET (17) +#define CLIC_CLICINT_ATTR_TRIG_MASK (0x3) +#define CLIC_CLICINT_ATTR_MODE_OFFSET (22) +#define CLIC_CLICINT_ATTR_MODE_MASK (0x3) +#define CLIC_CLICINT_CTL_OFFSET (24) +#define CLIC_CLICINT_CTL_MASK (0xff) + +#define MINTTHRESH (0x347) +#define MTVT (0x307) + +.align +.option norvc +.global main +main: + .macro clic_enable_irq id ctl + + // Set shv of irq + li t0, CLIC_CLICINT_REG(\id) + li t1, 1 << CLIC_CLICINT_ATTR_SHV_OFFSET + sw t1, 0(t0) + + // set trigger type to edge-triggered of irq + li t0, CLIC_CLICINT_REG(\id) + lw t1, 0(t0) + li t2, 1 << CLIC_CLICINT_ATTR_TRIG_OFFSET + or t1, t1, t2 + sw t1, 0(t0) + + // enable irq via SW by writing to clicintip + li t0, CLIC_CLICINT_REG(\id) + lw t1, 0(t0) + li t2, 1 << CLIC_CLICINT_IP_OFFSET + or t1, t1, t2 + sw t1, 0(t0) + + // set interrupt level and priority for interrupt + li t0, CLIC_CLICINT_REG(\id) + lw t1, 0(t0) + li t2, \ctl << CLIC_CLICINT_CTL_OFFSET + or t1, t1, t2 + sw t1, 0(t0) + + // enable interrupt + li t0, CLIC_CLICINT_REG(\id) + lw t1, 0(t0) + li t2, 1 << CLIC_CLICINT_IE_OFFSET + or t1, t1, t2 + sw t1, 0(t0) + + .endm + + +.align 2 +.option norvc +1: + // Enable interrupts (set mstatus.mie) + csrsi mstatus, 0x8 + + // Activate CLIC mode + la t0, mtvec_handler_fail + ori t0, t0, 0x3 + csrrw s0, mtvec, t0 + + // Write mtvt base + la t0, mtvt_handler + csrw MTVT, t0 + + // set number of bits for level encoding + li t0, CLIC_CLICCFG_REG + li t1, 0x4 << 1 + sw t1, 0(t0) + + // raise interrupt threshold to max and check that the interrupt doesn't fire yet + li a0, 0x1 + li t0, 0xff + csrw MINTTHRESH, t0 + + clic_enable_irq 31 0xaa + + clic_enable_irq 30 0xcc + + // wait + li t0, 500 +1: + addi t0, t0, -1 + bnez t0, 1b + + // lower interrupt threshold (interrupt 30 should happen) + li a0, 30 + li t0, 0xbb + csrw MINTTHRESH, t0 + + // wait + li t0, 500 +2: + addi t0, t0, -1 + bnez t0, 2b + + // lower interrupt threshold (interrupt 31 should happen) + li a0, 31 + li t0, 0x0 + csrw MINTTHRESH, t0 + + // wait + li t0, 500 +3: + addi t0, t0, -1 + bnez t0, 3b + + j fail_restore + +pass_restore: + csrw mtvec, s0 + li a0, 0 + ret + +fail_restore: + csrw mtvec, s0 + li a0, 1 + ret + +thirty: + // a0!=30: we should not get here, fail. else: we expect to get here, pass. + addi a0, a0, -30 + bnez a0, fail_restore + li a0, 0 + mret + +thirtyone: + // a0!=31: we should not get here, fail. else: we expect to get here, pass. + addi a0, a0, -31 + bnez a0, fail_restore + li a0, 0 + j pass_restore + + .align 8 + .global mtvt_handler +mtvt_handler: + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j thirty + j thirtyone + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + j fail_restore + + +.align 8 +.global mtvec_handler_fail +mtvec_handler_fail: + // Restore mtvec and fail + csrw mtvec, s0 + li a0, 1 + ret + + .data diff --git a/sw/tests/bare-metal/hostd/dma_1d.c b/sw/tests/bare-metal/hostd/dma_1d.c new file mode 100644 index 00000000..00d76a35 --- /dev/null +++ b/sw/tests/bare-metal/hostd/dma_1d.c @@ -0,0 +1,43 @@ +// 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 +// +// Alessandro Ottaviano +// +// Simple 1D test for iDMA. This is intended *only for execution from SPM*. + +#include "util.h" +#include "dif/clint.h" +#include "dif/dma.h" + +int main(void) { + // Immediately return an error if DMA is not present + CHECK_ASSERT(-1, chs_hw_feature_present(CHESHIRE_HW_FEATURES_DMA_BIT)); + + volatile char src_cached[] = "This is a DMA test"; + volatile char gold[] = "This is a DMA test!"; + + // Allocate destination memory in SPM + volatile char dst_cached[sizeof(gold)]; + + // Get pointer to uncached SPM source and destination + volatile char *src = src_cached + 0x04000000; + volatile char *dst = dst_cached + 0x04000000; + + // Copy from cached to uncached source to ensure it is DMA-accessible + for (unsigned i = 0; i < sizeof(src_cached); ++i) src[i] = src_cached[i]; + + // Pre-write finishing "!\0" to guard against overlength transfers + dst[sizeof(gold) - 2] = '!'; + dst[sizeof(gold) - 1] = '\0'; + + // Issue blocking memcpy (exclude null terminator from source) + sys_dma_blk_memcpy((uintptr_t)(void *)dst, (uintptr_t)(void *)src, sizeof(src_cached) - 1, + DMA_CONF_DECOUPLE_NONE); + + // Check destination string + int errors = sizeof(gold); + for (unsigned i = 0; i < sizeof(gold); ++i) errors -= (dst[i] == gold[i]); + + return errors; +} diff --git a/sw/tests/bare-metal/hostd/dma_2d.c b/sw/tests/bare-metal/hostd/dma_2d.c new file mode 100644 index 00000000..469d1f47 --- /dev/null +++ b/sw/tests/bare-metal/hostd/dma_2d.c @@ -0,0 +1,43 @@ +// 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 +// +// Paul Scheffler +// +// Simple 2D test for iDMA. This is intended *only for execution from SPM*. + +#include "util.h" +#include "dif/clint.h" +#include "dif/dma.h" + +int main(void) { + // Immediately return an error if DMA is not present + CHECK_ASSERT(-1, chs_hw_feature_present(CHESHIRE_HW_FEATURES_DMA_BIT)); + + volatile char src_cached[] = "This is a DMA test"; + volatile char gold[] = "This ishis is is is as is a DMA test!"; + + // Allocate destination memory in SPM + volatile char dst_cached[sizeof(gold)]; + + // Get pointer to uncached SPM source and destination + volatile char *src = src_cached + 0x04000000; + volatile char *dst = dst_cached + 0x04000000; + + // Copy from cached to uncached source to ensure it is DMA-accessible + for (unsigned i = 0; i < sizeof(src_cached); ++i) src[i] = src_cached[i]; + + // Pre-write finishing "!\0" to guard against overlength transfers + dst[sizeof(gold) - 2] = '!'; + dst[sizeof(gold) - 1] = '\0'; + + // Issue blocking 2D memcpy (exclude null terminator from source) + sys_dma_2d_blk_memcpy((uintptr_t)(void *)dst, (uintptr_t)(void *)src, sizeof(src_cached) - 4, 7, + 1, 4, DMA_CONF_DECOUPLE_NONE); + + // Check destination string + int errors = sizeof(gold); + for (unsigned i = 0; i < sizeof(gold); ++i) errors -= (dst[i] == gold[i]); + + return errors; +} diff --git a/sw/tests/bare-metal/hostd/dma_slink.c b/sw/tests/bare-metal/hostd/dma_slink.c new file mode 100644 index 00000000..b3aa6183 --- /dev/null +++ b/sw/tests/bare-metal/hostd/dma_slink.c @@ -0,0 +1,47 @@ +// 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 +// +// Paul Scheffler +// +// Simple 1D test for iDMA accessing a remote memory over the serial link. +// This is intended *only for execution from SPM*. + +#include "util.h" +#include "dif/clint.h" +#include "dif/dma.h" + +int main(void) { + // Immediately return an error if DMA or Serial Link are not present + CHECK_ASSERT(-1, chs_hw_feature_present(CHESHIRE_HW_FEATURES_DMA_BIT)); + CHECK_ASSERT(-2, chs_hw_feature_present(CHESHIRE_HW_FEATURES_SERIAL_LINK_BIT)); + + volatile char src_cached[] = "This is a DMA test"; + volatile char gold[] = "This is a DMA test!"; + + // Allocate destination memory in SPM + volatile char dst_cached[sizeof(gold)]; + + // Get pointer to uncached SPM destination + volatile char *dst = dst_cached + 0x04000000; + + // Remote pointer to other device on serial link (assume Cheshire-like, with SPM) + volatile char *rem = dst + 0x100000000; + + // Copy from cached source to uncached remote using core + for (unsigned i = 0; i < sizeof(src_cached); ++i) rem[i] = src_cached[i]; + + // Pre-write finishing "!\0" to guard against overlength transfers + dst[sizeof(gold) - 2] = '!'; + dst[sizeof(gold) - 1] = '\0'; + + // Issue blocking memcpy from rem to dst (exclude null terminator from source) + sys_dma_blk_memcpy((uintptr_t)(void *)dst, (uintptr_t)(void *)rem, sizeof(src_cached) - 1, + DMA_CONF_DECOUPLE_NONE); + + // Check destination string + int errors = sizeof(gold); + for (unsigned i = 0; i < sizeof(gold); ++i) errors -= (dst[i] == gold[i]); + + return errors; +} diff --git a/target/sim/src/carfield_tb.sv b/target/sim/src/carfield_tb.sv index 9d11161a..255ff808 100644 --- a/target/sim/src/carfield_tb.sv +++ b/target/sim/src/carfield_tb.sv @@ -336,14 +336,14 @@ module tb_carfield_soc; // Write bootaddress to each core $display("[JTAG PULPD] Write PULP cluster boot address for each core"); for (int c = 0; c < PulpdNumCores; c++) begin - fix.chs_vip.jtag_write_reg32(PulpdBootAddr + c*32'h4, PulpdBootAddrL2); + fix.chs_vip.jtag_write_reg32(PulpdBootAddr + c*32'h4, PulpdBootAddrL2, 1, 20); end // Write boot enable $display("[JTAG PULPD] Write PULP cluster boot enable"); - fix.chs_vip.jtag_write_reg32(CarSocCtrlPulpdBootEnAddr, 32'h1); + fix.chs_vip.jtag_write_reg32(CarSocCtrlPulpdBootEnAddr, 32'h1, 1, 20); // Write fetch enable $display("[JTAG PULPD] Write PULP cluster fetch enable"); - fix.chs_vip.jtag_write_reg32(CarSocCtrlPulpdFetchEnAddr, 32'h1); + fix.chs_vip.jtag_write_reg32(CarSocCtrlPulpdFetchEnAddr, 32'h1, 1, 20); // Poll memory address for PULP EOC fix.chs_vip.jtag_poll_bit0(CarSocCtrlPulpdEocAddr, pulpd_exit_code, 20); @@ -480,22 +480,23 @@ module tb_carfield_soc; // write start address into the csr $display("[JTAG SPATZD] write the CSR %x of spatz with the entry point %x", spatz_cluster_pkg::PeriStartAddr + spatz_cluster_peripheral_reg_pkg::SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_OFFSET, spatzd_binary_entry); - fix.chs_vip.jtag_write_reg(spatz_cluster_pkg::PeriStartAddr + spatz_cluster_peripheral_reg_pkg::SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_OFFSET, spatzd_binary_entry ); + fix.chs_vip.jtag_write_reg32(spatz_cluster_pkg::PeriStartAddr + spatz_cluster_peripheral_reg_pkg::SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_OFFSET, spatzd_binary_entry[63:32], 1, 20); + fix.chs_vip.jtag_write_reg32(spatz_cluster_pkg::PeriStartAddr + spatz_cluster_peripheral_reg_pkg::SPATZ_CLUSTER_PERIPHERAL_CLUSTER_BOOT_CONTROL_OFFSET, spatzd_binary_entry[31:0], 1, 20); // Set interrupt on mailbox mailbox id MBOX_SPATZD_CORE0_ID and MBOX_SPATZD_CORE1_ID spatzd_reg_value = 64'h1; $display("[JTAG SPATZD] Set mailbox interrupt ID %x at %x ",MBOX_SPATZ_CORE0_ID, CAR_MBOX_BASE + MBOX_INT_SND_SET_OFFSET + (MBOX_SPATZ_CORE0_ID*32'h100)); - fix.chs_vip.jtag_write_reg32(CAR_MBOX_BASE + MBOX_INT_SND_SET_OFFSET + (MBOX_SPATZ_CORE0_ID*32'h100) , spatzd_reg_value); + fix.chs_vip.jtag_write_reg32(CAR_MBOX_BASE + MBOX_INT_SND_SET_OFFSET + (MBOX_SPATZ_CORE0_ID*32'h100) , spatzd_reg_value, 1, 20); $display("[JTAG SPATZD] Set mailbox interrupt ID %x at %x ",MBOX_SPATZ_CORE1_ID, CAR_MBOX_BASE + MBOX_INT_SND_SET_OFFSET + (MBOX_SPATZ_CORE1_ID*32'h100)); - fix.chs_vip.jtag_write_reg32(CAR_MBOX_BASE + MBOX_INT_SND_SET_OFFSET + (MBOX_SPATZ_CORE1_ID*32'h100) , spatzd_reg_value); + fix.chs_vip.jtag_write_reg32(CAR_MBOX_BASE + MBOX_INT_SND_SET_OFFSET + (MBOX_SPATZ_CORE1_ID*32'h100) , spatzd_reg_value, 1, 20); // Enable interrupt on mailbox id MBOX_SPATZ_CORE0_ID and MBOX_SPATZ_CORE1_ID $display("[JTAG SPATZD] Enable mailbox interrupt ID %x at %x ",MBOX_SPATZ_CORE0_ID, CAR_MBOX_BASE + MBOX_INT_SND_EN_OFFSET + (MBOX_SPATZ_CORE0_ID*32'h100) ,spatzd_reg_value); - fix.chs_vip.jtag_write_reg32(CAR_MBOX_BASE + MBOX_INT_SND_EN_OFFSET + (MBOX_SPATZ_CORE0_ID*32'h100) , spatzd_reg_value); + fix.chs_vip.jtag_write_reg32(CAR_MBOX_BASE + MBOX_INT_SND_EN_OFFSET + (MBOX_SPATZ_CORE0_ID*32'h100) , spatzd_reg_value, 1, 20); $display("[JTAG SPATZD] Enable mailbox interrupt ID %x at %x ",MBOX_SPATZ_CORE1_ID, CAR_MBOX_BASE + MBOX_INT_SND_EN_OFFSET + (MBOX_SPATZ_CORE1_ID*32'h100) ,spatzd_reg_value); - fix.chs_vip.jtag_write_reg32(CAR_MBOX_BASE + MBOX_INT_SND_EN_OFFSET + (MBOX_SPATZ_CORE1_ID*32'h100) , spatzd_reg_value); + fix.chs_vip.jtag_write_reg32(CAR_MBOX_BASE + MBOX_INT_SND_EN_OFFSET + (MBOX_SPATZ_CORE1_ID*32'h100) , spatzd_reg_value, 1, 20); // Poll memory address for Spatz EOC fix.chs_vip.jtag_poll_bit0(spatz_cluster_pkg::PeriStartAddr + spatz_cluster_peripheral_reg_pkg::SPATZ_CLUSTER_PERIPHERAL_CLUSTER_EOC_EXIT_OFFSET, spatzd_exit_code, 20);