From 1584a8bdb8314f86f3218a9b17db257452872386 Mon Sep 17 00:00:00 2001 From: Ella Schwarz Date: Fri, 2 Oct 2026 10:24:58 -0700 Subject: [PATCH 1/5] Get ucie digital loopback test passing --- software/Makefile | 4 +- software/ucie-digital-loopback.c | 76 ++++++++++++++++++++++++++++++++ test/src/IrisSpec.scala | 22 ++++++++- 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 software/ucie-digital-loopback.c diff --git a/software/Makefile b/software/Makefile index 2606cc4..573ca08 100644 --- a/software/Makefile +++ b/software/Makefile @@ -33,10 +33,10 @@ ARCHFLAGS = -march=$(ARCH) -mabi=$(ABI) # vector extension. Kept separate so it doesn't force V onto every program. VEC_ARCHFLAGS = -march=rv64gcv_zfh_zvfh -mabi=$(ABI) -CFLAGS = -std=gnu99 -O2 -fno-common -fno-builtin-printf -Wall -specs=htif_nano.specs +CFLAGS = -std=gnu99 -O2 -fno-common -fno-builtin-printf -Wall -specs=htif_nano.specs -Iinclude LDFLAGS = -specs=htif_nano.specs -PROGRAMS = hello hello0 hello1 router ring-hello ucie-loopback tacit-always tacit-dma ucie-vec-memcpy +PROGRAMS = hello hello0 hello1 router ring-hello ucie-loopback ucie-digital-loopback tacit-always tacit-dma ucie-vec-memcpy .DEFAULT_GOAL := default diff --git a/software/ucie-digital-loopback.c b/software/ucie-digital-loopback.c new file mode 100644 index 0000000..942af0c --- /dev/null +++ b/software/ucie-digital-loopback.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include "marchid.h" +#include "mmio.h" +#include "router.h" +#include "ucie.h" + +#define UCIE0_REG_BASE 0x200000UL +#define UCIE1_REG_BASE 0x208000UL +#define ROUTER_MMIO 0x4000 +#define CHIP_ID_ADDR 0x4080 +#define OFFCHIP_OFFSET 0x800000000L + +uint32_t src[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; +uint32_t dest[10]; +uint32_t test[10]; + +int rw_mem(uint64_t offset) { + // remote = dest on the other chip: same local address as our dest, tagged with target chip ID. + // offset = OFFCHIP_OFFSET * target_chipId (a byte offset, added via uint8_t* cast). + void *remote = (void *)((uint8_t *)dest + offset); + + size_t write_start = rdcycle(); + memcpy(remote, src, sizeof(src)); + size_t write_end = rdcycle(); + + printf("Wrote %ld bytes in %ld cycles\n", sizeof(src), write_end - write_start); + + size_t read_start = rdcycle(); + memcpy(test, remote, sizeof(src)); + size_t read_end = rdcycle(); + + for (int i = 0; i < 10; i++) { + if (src[i] != test[i]) { + printf("Remote write/read failed at index %d: wrote %x, read %x\n", i, src[i], test[i]); + exit(1); + } + } + + printf("Read %ld bytes in %ld cycles\n", sizeof(src), read_end - read_start); + + return 0; +} + +int main(void) { + + int chip_id = reg_read64(CHIP_ID_ADDR); + + printf("Got chip ID: %d\n", chip_id); + + // setup_ucie_digital() brings up the PHY, hands both bands to the real + // UCIe digital controller (controllerSel = ucie), and blocks until spec + // link training completes. Unlike ucie-loopback.c's setup_ucie() + + // UCIE_BAND_MODE_TL, which bypasses UcieDigitalTop and frames TileLink + // directly onto the mainband, requests here are carried by the trained + // link through the real protocol layer/D2D adapter/logical PHY stack. + printf("Setting up UCIe0 (digital controller)\n"); + setup_ucie_digital(UCIE0_REG_BASE); + printf("Setting up UCIe1 (digital controller)\n"); + setup_ucie_digital(UCIE1_REG_BASE); + + printf("Testing UCIe at port 0\n"); + program_router(0, 1, 0); + rw_mem(OFFCHIP_OFFSET); + + printf("Testing UCIe at port 1\n"); + program_router(0, 1, 1); + rw_mem(OFFCHIP_OFFSET); + + printf("UCIe digital loopback test complete\n"); + + return 0; +} diff --git a/test/src/IrisSpec.scala b/test/src/IrisSpec.scala index 01ca0c0..1e59c12 100644 --- a/test/src/IrisSpec.scala +++ b/test/src/IrisSpec.scala @@ -152,7 +152,7 @@ class TestHarness(nChips: Int, binaryPaths: Seq[Path], plusArgs: Seq[Seq[String] val digitalFreqMHz = 500 val digitalClock = freeRunningClock(digitalFreqMHz) val ucieBypassClock = freeRunningClock(8000) - val ucieDigitalBypassClock = freeRunningClock(800) + val ucieDigitalBypassClock = freeRunningClock(500) // previously was 800 val ucieSidebandBypassClock = freeRunningClock(800) // The clocking tile's PLL reference, as in the UCIe repo's own harness. val ucieRefClock = freeRunningClock(100) @@ -435,6 +435,26 @@ class IrisSpec extends AnyFunSpec { ) } + it("should run ucie digital loopback test") { + implicit val p = new IrisConfig(sim = true) + val workDir = Utils.buildRoot / "Iris_should_run_ucie_digital_loopback_test" + + val chipid0 = 1 + val chipidReg = p(ChipletRoutingKey).get.routerParams.tableAddress + p(ChipletRoutingKey).get.routerParams.tableEntries * 32 + val chip0PlusArgs = Seq( + f"+init_write=0x${chipidReg}%08x:0x${chipid0}%08x", + ) + + Utils.simulateTopWithBinaries( + workDir, + nChips = 1, + binaryPaths = Seq(Utils.root / "software/ucie-digital-loopback.riscv"), + plusArgs = Seq(chip0PlusArgs), + fast = true, + debug = true + ) + } + it("should run tacit always trace workload") { implicit val p = new IrisConfig(sim = true) val workDir = Utils.buildRoot / "Iris_should_run_tacit_always_trace" From f139eb7ebe3556f19822e3df920021f050f3dfab Mon Sep 17 00:00:00 2001 From: Ella Schwarz Date: Fri, 2 Oct 2026 16:56:01 -0700 Subject: [PATCH 2/5] Clocking hacks to get ucie digital tests passing --- software/ucie-digital-loopback.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/software/ucie-digital-loopback.c b/software/ucie-digital-loopback.c index 942af0c..ca6dbfb 100644 --- a/software/ucie-digital-loopback.c +++ b/software/ucie-digital-loopback.c @@ -58,8 +58,22 @@ int main(void) { // directly onto the mainband, requests here are carried by the trained // link through the real protocol layer/D2D adapter/logical PHY stack. printf("Setting up UCIe0 (digital controller)\n"); + // TEMP: the clock registers reset with the global delay line at max; + // zero it so the bump QuarterDelay alone gives the quarter shift, and + // reset the dividers while gated so TX and RX word framing line up. + set_clk_gate(UCIE0_REG_BASE, 0); + set_global_delay(UCIE0_REG_BASE, 0); + reset_dividers(UCIE0_REG_BASE); + set_clk_gate(UCIE0_REG_BASE, 1); setup_ucie_digital(UCIE0_REG_BASE); printf("Setting up UCIe1 (digital controller)\n"); + // TEMP: the clock registers reset with the global delay line at max; + // zero it so the bump QuarterDelay alone gives the quarter shift, and + // reset the dividers while gated so TX and RX word framing line up. + set_clk_gate(UCIE1_REG_BASE, 0); + set_global_delay(UCIE1_REG_BASE, 0); + reset_dividers(UCIE1_REG_BASE); + set_clk_gate(UCIE1_REG_BASE, 1); setup_ucie_digital(UCIE1_REG_BASE); printf("Testing UCIe at port 0\n"); From 035b8507cd429c4767e83a4c28ed8b58c1f33d4c Mon Sep 17 00:00:00 2001 From: Ella Schwarz Date: Fri, 2 Oct 2026 17:53:35 -0700 Subject: [PATCH 3/5] Move clock setup code to ucie setup function --- software/ucie-digital-loopback.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/software/ucie-digital-loopback.c b/software/ucie-digital-loopback.c index ca6dbfb..942af0c 100644 --- a/software/ucie-digital-loopback.c +++ b/software/ucie-digital-loopback.c @@ -58,22 +58,8 @@ int main(void) { // directly onto the mainband, requests here are carried by the trained // link through the real protocol layer/D2D adapter/logical PHY stack. printf("Setting up UCIe0 (digital controller)\n"); - // TEMP: the clock registers reset with the global delay line at max; - // zero it so the bump QuarterDelay alone gives the quarter shift, and - // reset the dividers while gated so TX and RX word framing line up. - set_clk_gate(UCIE0_REG_BASE, 0); - set_global_delay(UCIE0_REG_BASE, 0); - reset_dividers(UCIE0_REG_BASE); - set_clk_gate(UCIE0_REG_BASE, 1); setup_ucie_digital(UCIE0_REG_BASE); printf("Setting up UCIe1 (digital controller)\n"); - // TEMP: the clock registers reset with the global delay line at max; - // zero it so the bump QuarterDelay alone gives the quarter shift, and - // reset the dividers while gated so TX and RX word framing line up. - set_clk_gate(UCIE1_REG_BASE, 0); - set_global_delay(UCIE1_REG_BASE, 0); - reset_dividers(UCIE1_REG_BASE); - set_clk_gate(UCIE1_REG_BASE, 1); setup_ucie_digital(UCIE1_REG_BASE); printf("Testing UCIe at port 0\n"); From e442896c4057b45f61beba7ef2995037e34861ec Mon Sep 17 00:00:00 2001 From: Ella Schwarz Date: Thu, 8 Oct 2026 10:28:47 -0700 Subject: [PATCH 4/5] Use ucie sim param --- src/Iris.scala | 4 +++- src/TinyIris.scala | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Iris.scala b/src/Iris.scala index e6b9c34..273268c 100644 --- a/src/Iris.scala +++ b/src/Iris.scala @@ -512,13 +512,15 @@ class IrisConfig(sim: Boolean = false) address = 0x200000, managerWhere = SBUS, numLanes = 16, - includeDefaultModels = true + includeDefaultModels = true, + sim = sim )), UcieComplexPort(edu.berkeley.cs.uciedigital.tilelink.UcieTLParams( address = 0x208000, managerWhere = SBUS, numLanes = 16, includeDefaultModels = true, + sim = sim, moduleId = 1 )) ))) ++ diff --git a/src/TinyIris.scala b/src/TinyIris.scala index 6243c35..f4a68fe 100644 --- a/src/TinyIris.scala +++ b/src/TinyIris.scala @@ -258,13 +258,15 @@ class TinyIrisConfig(sim: Boolean = false) address = 0x200000, managerWhere = SBUS, numLanes = 16, - includeDefaultModels = true + includeDefaultModels = true, + sim = sim ), edu.berkeley.cs.uciedigital.tilelink.UcieTLParams( address = 0x208000, managerWhere = SBUS, numLanes = 16, - includeDefaultModels = true + includeDefaultModels = true, + sim = sim ) ))) ++ From 6d1da71c5ab1bdc957e018ed0d1eaf5a76f7a555 Mon Sep 17 00:00:00 2001 From: Ella Schwarz Date: Fri, 16 Oct 2026 15:52:26 -0700 Subject: [PATCH 5/5] Remove pointless comment --- software/ucie-digital-loopback.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/software/ucie-digital-loopback.c b/software/ucie-digital-loopback.c index 942af0c..379ca75 100644 --- a/software/ucie-digital-loopback.c +++ b/software/ucie-digital-loopback.c @@ -51,12 +51,6 @@ int main(void) { printf("Got chip ID: %d\n", chip_id); - // setup_ucie_digital() brings up the PHY, hands both bands to the real - // UCIe digital controller (controllerSel = ucie), and blocks until spec - // link training completes. Unlike ucie-loopback.c's setup_ucie() + - // UCIE_BAND_MODE_TL, which bypasses UcieDigitalTop and frames TileLink - // directly onto the mainband, requests here are carried by the trained - // link through the real protocol layer/D2D adapter/logical PHY stack. printf("Setting up UCIe0 (digital controller)\n"); setup_ucie_digital(UCIE0_REG_BASE); printf("Setting up UCIe1 (digital controller)\n");