From c2b174371b754bdf91608751420dbfeeda65aa06 Mon Sep 17 00:00:00 2001 From: Rahul Kumar Date: Thu, 24 Sep 2026 16:21:42 -0700 Subject: [PATCH 1/5] ucie clk dist --- src/GenUcieHeader.scala | 12 +++++++----- src/Iris.scala | 19 +++++++++++++------ ucie | 2 +- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/GenUcieHeader.scala b/src/GenUcieHeader.scala index cba06f1..12c67d8 100644 --- a/src/GenUcieHeader.scala +++ b/src/GenUcieHeader.scala @@ -29,19 +29,21 @@ object GenUcieHeader { def render(): String = { val ports = uciePorts // The header holds one register layout, so every port has to agree on - // everything that layout depends on. Address and moduleId do not reach it: - // the offsets are relative to each port's own MMIO base, and the moduleId - // only names modules. + // everything that layout depends on. Address, moduleId and the clock + // distribution netlist do not reach it: the offsets are relative to each + // port's own MMIO base, the moduleId only names modules, and the netlist is + // physical design. val canonical = ports.map( _.copy( address = ports.head.address, - moduleId = ports.head.moduleId + moduleId = ports.head.moduleId, + clkDistLayout = ports.head.clkDistLayout ) ) require( canonical.forall(_ == canonical.head), "UCIe ports must share a register layout, but their parameters differ " + - s"beyond address and moduleId: ${canonical.distinct.mkString("\n")}" + s"beyond address, moduleId and clock distribution: ${canonical.distinct.mkString("\n")}" ) edu.berkeley.cs.uciedigital.tilelink.GenUcieHeader .render(ports.head, regenCommand) diff --git a/src/Iris.scala b/src/Iris.scala index 73ef937..04740f3 100644 --- a/src/Iris.scala +++ b/src/Iris.scala @@ -478,21 +478,28 @@ class IrisConfig(sim: Boolean = false) routerParams = testchipip.soc.OffchipRouterParams(tableEntries = 4), ports = Seq( // PD hardens the two UCIe links together, so UcieComplexPort puts - // both instances inside one UcieComplex module. They are identical - // logic and share a `moduleId`, so they dedup into a single UcieTL - // underneath it; splitting them again is a matter of giving one its - // own `moduleId`. + // both instances inside one UcieComplex module. Their PHYs differ + // in their lane clock distribution: link 0's bump field is the + // canonical orientation, which the analog IP's clock DEF gives a + // buffered clock tree, and the netlist of that tree is what its PHY + // instantiates outside simulation. Link 1's field is turned 90 + // degrees and keeps the behavioral network until the DEF has a tree + // for it. So each link is its own module, `moduleId` 0 and 1. UcieComplexPort(edu.berkeley.cs.uciedigital.tilelink.UcieTLParams( address = 0x200000, managerWhere = SBUS, numLanes = 16, - includeDefaultModels = true + includeDefaultModels = true, + clkDistLayout = + if (sim) edu.berkeley.cs.uciedigital.phy.macros.clocking.ClkDistLayout.Behavioral + else edu.berkeley.cs.uciedigital.phy.macros.clocking.ClkDistLayout.Buffered("r0") )), UcieComplexPort(edu.berkeley.cs.uciedigital.tilelink.UcieTLParams( address = 0x208000, managerWhere = SBUS, numLanes = 16, - includeDefaultModels = true + includeDefaultModels = true, + moduleId = 1 )) ))) ++ new WithIrisUncore(sim) diff --git a/ucie b/ucie index caf0daf..344f92f 160000 --- a/ucie +++ b/ucie @@ -1 +1 @@ -Subproject commit caf0daf1135f5b87225fa4903fcc3dfb87863de5 +Subproject commit 344f92ff58806e0f5feef811bf5a1559fcce021f From 34f60660db113cce7534d3e7728ae234956006e6 Mon Sep 17 00:00:00 2001 From: Rahul Kumar Date: Fri, 2 Oct 2026 11:44:54 -0700 Subject: [PATCH 2/5] add clk regs --- src/Iris.scala | 19 ++++++++++++------- src/UcieComplex.scala | 43 +++++++++++++++++++++++++++++++++++++++++-- ucie | 2 +- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/Iris.scala b/src/Iris.scala index 04740f3..e4efc47 100644 --- a/src/Iris.scala +++ b/src/Iris.scala @@ -44,6 +44,7 @@ class JTAGChipIO(hasReset: Boolean) extends Bundle { class IrisSystem(implicit p: Parameters) extends edu.berkeley.cs.chippy.ChippySystem with testchipip.soc.CanHaveChipletRouting + with CanHaveUcieClkRegs // UCIe clock registers, which the router can't attach with testchipip.soc.CanHaveSubsystemInjectors // Enables the subsystem injector API with testchipip.soc.CanHaveSwitchableOffchipBus // Enables optional off-chip-bus with interface-switch with testchipip.serdes.CanHavePeripheryTLSerial @@ -479,12 +480,13 @@ class IrisConfig(sim: Boolean = false) ports = Seq( // PD hardens the two UCIe links together, so UcieComplexPort puts // both instances inside one UcieComplex module. Their PHYs differ - // in their lane clock distribution: link 0's bump field is the - // canonical orientation, which the analog IP's clock DEF gives a - // buffered clock tree, and the netlist of that tree is what its PHY - // instantiates outside simulation. Link 1's field is turned 90 - // degrees and keeps the behavioral network until the DEF has a tree - // for it. So each link is its own module, `moduleId` 0 and 1. + // in their lane clock distribution: the analog IP's clock DEF gives + // each link a buffered clock tree laid out for its own bump field -- + // link 0's in the canonical orientation, link 1's turned 90 degrees + // -- and the netlist of that tree is what its PHY instantiates + // outside simulation. So each link is its own module, `moduleId` 0 + // and 1. Each link also has its own high-speed and digital bypass + // clock bumps. UcieComplexPort(edu.berkeley.cs.uciedigital.tilelink.UcieTLParams( address = 0x200000, managerWhere = SBUS, @@ -499,7 +501,10 @@ class IrisConfig(sim: Boolean = false) managerWhere = SBUS, numLanes = 16, includeDefaultModels = true, - moduleId = 1 + moduleId = 1, + clkDistLayout = + if (sim) edu.berkeley.cs.uciedigital.phy.macros.clocking.ClkDistLayout.Behavioral + else edu.berkeley.cs.uciedigital.phy.macros.clocking.ClkDistLayout.Buffered("r90") )) ))) ++ new WithIrisUncore(sim) diff --git a/src/UcieComplex.scala b/src/UcieComplex.scala index 820782f..e758e99 100644 --- a/src/UcieComplex.scala +++ b/src/UcieComplex.scala @@ -2,9 +2,11 @@ package edu.berkeley.cs.iris import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.subsystem.TLBusWrapperLocation -import edu.berkeley.cs.uciedigital.tilelink.UcieTLParams +import freechips.rocketchip.subsystem.{BaseSubsystem, TLBusWrapperLocation} +import freechips.rocketchip.tilelink.{TLBuffer, TLWidthWidget} +import edu.berkeley.cs.uciedigital.tilelink.{UcieChipletLink, UcieTLParams} import testchipip.soc.{ + CanHaveChipletRouting, ChipletLinkParams, ChipletLinkWrapper, ChipletLinkWrapperInstantiationLike, @@ -81,3 +83,40 @@ object UciePort { .map(_.ports.collect { case UciePort(u) => u }) .getOrElse(Nil) } + +/** Attaches the part of each UCIe link that the chiplet router can't. + * + * The router gives every port one control node, coupled to its control bus, + * and one clock. A UCIe link has two register blocks: the main one, on the + * clock its PHY makes, and the clock register block, which sets that clock up + * and so runs on the chip's. Only the main one goes through the router. This + * couples the clock register block to the same bus the same way, and clocks it + * from that bus, so its register port needs no crossing. + * + * The links are found by walking the subsystem's children, since the router + * keeps its ports to itself. Extending [[CanHaveChipletRouting]] makes sure + * they exist by the time this runs. + */ +trait CanHaveUcieClkRegs extends CanHaveChipletRouting { this: BaseSubsystem => + p(ChipletRoutingKey).foreach { params => + def links(lm: LazyModule): Seq[UcieChipletLink] = + lm.getChildren.reverse.flatMap { + case link: UcieChipletLink => Seq(link) + case child => links(child) + } + val ucieLinks = links(this) + require( + ucieLinks.size == UciePort.all(p).size, + s"found ${ucieLinks.size} UCIe links under the subsystem, but the " + + s"chiplet router has ${UciePort.all(p).size} UCIe ports" + ) + + val cbus = locateTLBusWrapper(params.controlBusWhere) + ucieLinks.foreach { link => + link.ucie.chipDigitalClockNode := cbus.fixedClockNode + cbus.coupleTo(s"${link.name}_clk_control") { + link.ucie.clkRegNode := TLWidthWidget(cbus.beatBytes) := TLBuffer() := _ + } + } + } +} diff --git a/ucie b/ucie index 344f92f..3fbc560 160000 --- a/ucie +++ b/ucie @@ -1 +1 @@ -Subproject commit 344f92ff58806e0f5feef811bf5a1559fcce021f +Subproject commit 3fbc560b3c6060a69b1052603d8c2105e40edcae From 170149ee1f20cbf0a2e0654e47b7df1739584511 Mon Sep 17 00:00:00 2001 From: Rahul Kumar Date: Tue, 13 Oct 2026 12:24:00 -0700 Subject: [PATCH 3/5] ucie clk distribution --- src/Iris.scala | 25 ++++++----------- src/TinyIris.scala | 1 + src/UcieComplex.scala | 64 ++++++++++++++++++++++--------------------- ucie | 2 +- 4 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/Iris.scala b/src/Iris.scala index e4efc47..d8a8e9e 100644 --- a/src/Iris.scala +++ b/src/Iris.scala @@ -44,7 +44,6 @@ class JTAGChipIO(hasReset: Boolean) extends Bundle { class IrisSystem(implicit p: Parameters) extends edu.berkeley.cs.chippy.ChippySystem with testchipip.soc.CanHaveChipletRouting - with CanHaveUcieClkRegs // UCIe clock registers, which the router can't attach with testchipip.soc.CanHaveSubsystemInjectors // Enables the subsystem injector API with testchipip.soc.CanHaveSwitchableOffchipBus // Enables optional off-chip-bus with interface-switch with testchipip.serdes.CanHavePeripheryTLSerial @@ -54,6 +53,7 @@ class IrisSystem(implicit p: Parameters) class IrisTop(implicit p: Parameters) extends LazyModule with BindingScope { val system = LazyModule(new IrisSystem) + UcieControl.connect(system) val clockGroupsSourceNode = ClockGroupSourceNode( Seq(ClockGroupSourceParameters()) ) @@ -479,32 +479,23 @@ class IrisConfig(sim: Boolean = false) routerParams = testchipip.soc.OffchipRouterParams(tableEntries = 4), ports = Seq( // PD hardens the two UCIe links together, so UcieComplexPort puts - // both instances inside one UcieComplex module. Their PHYs differ - // in their lane clock distribution: the analog IP's clock DEF gives - // each link a buffered clock tree laid out for its own bump field -- - // link 0's in the canonical orientation, link 1's turned 90 degrees - // -- and the netlist of that tree is what its PHY instantiates - // outside simulation. So each link is its own module, `moduleId` 0 - // and 1. Each link also has its own high-speed and digital bypass - // clock bumps. + // both instances inside one UcieComplex module. Each link is still + // its own module, `moduleId` 0 and 1, so that a physical design can + // give each the lane clock distribution network laid out for its + // own bump field (see `ClkDistLayout`). Each link also has its own + // high-speed and digital bypass clock bumps. UcieComplexPort(edu.berkeley.cs.uciedigital.tilelink.UcieTLParams( address = 0x200000, managerWhere = SBUS, numLanes = 16, - includeDefaultModels = true, - clkDistLayout = - if (sim) edu.berkeley.cs.uciedigital.phy.macros.clocking.ClkDistLayout.Behavioral - else edu.berkeley.cs.uciedigital.phy.macros.clocking.ClkDistLayout.Buffered("r0") + includeDefaultModels = true )), UcieComplexPort(edu.berkeley.cs.uciedigital.tilelink.UcieTLParams( address = 0x208000, managerWhere = SBUS, numLanes = 16, includeDefaultModels = true, - moduleId = 1, - clkDistLayout = - if (sim) edu.berkeley.cs.uciedigital.phy.macros.clocking.ClkDistLayout.Behavioral - else edu.berkeley.cs.uciedigital.phy.macros.clocking.ClkDistLayout.Buffered("r90") + moduleId = 1 )) ))) ++ new WithIrisUncore(sim) diff --git a/src/TinyIris.scala b/src/TinyIris.scala index 94a0de6..ccc05ed 100644 --- a/src/TinyIris.scala +++ b/src/TinyIris.scala @@ -34,6 +34,7 @@ import sifive.blocks.inclusivecache.{InclusiveCachePortParameters} class TinyIrisTop(implicit p: Parameters) extends LazyModule with BindingScope { val system = LazyModule(new IrisSystem) + UcieControl.connect(system) val clockGroupsSourceNode = ClockGroupSourceNode( Seq(ClockGroupSourceParameters()) ) diff --git a/src/UcieComplex.scala b/src/UcieComplex.scala index e758e99..2a6cab9 100644 --- a/src/UcieComplex.scala +++ b/src/UcieComplex.scala @@ -3,10 +3,9 @@ package edu.berkeley.cs.iris import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.diplomacy._ import freechips.rocketchip.subsystem.{BaseSubsystem, TLBusWrapperLocation} -import freechips.rocketchip.tilelink.{TLBuffer, TLWidthWidget} +import freechips.rocketchip.tilelink.{TLBuffer, TLFragmenter, TLWidthWidget} import edu.berkeley.cs.uciedigital.tilelink.{UcieChipletLink, UcieTLParams} import testchipip.soc.{ - CanHaveChipletRouting, ChipletLinkParams, ChipletLinkWrapper, ChipletLinkWrapperInstantiationLike, @@ -84,39 +83,42 @@ object UciePort { .getOrElse(Nil) } -/** Attaches the part of each UCIe link that the chiplet router can't. +/** Attaches each UCIe link's register port, which the chiplet router can't. * - * The router gives every port one control node, coupled to its control bus, - * and one clock. A UCIe link has two register blocks: the main one, on the - * clock its PHY makes, and the clock register block, which sets that clock up - * and so runs on the chip's. Only the main one goes through the router. This - * couples the clock register block to the same bus the same way, and clocks it - * from that bus, so its register port needs no crossing. + * The router couples a port's control node to its control bus only when the + * port hands it a bare `TLRegisterNode`. A UCIe link's register port is a + * crossbar in front of its three register blocks -- PhyTest, controller and + * clocking -- so `UcieChipletLink` hands the router none and leaves the port + * to the top. This couples it to the router's control bus the way the router + * couples its own control nodes, with the fragmenter in front that the port + * needs. The router clocks the link, from a clock group the top drives off the + * same clock as the bus, so the port needs no crossing. * - * The links are found by walking the subsystem's children, since the router - * keeps its ports to itself. Extending [[CanHaveChipletRouting]] makes sure - * they exist by the time this runs. + * Each top calls this on its system once the system is built. The router keeps + * its ports to itself, so the links are found by walking the system's + * children. */ -trait CanHaveUcieClkRegs extends CanHaveChipletRouting { this: BaseSubsystem => - p(ChipletRoutingKey).foreach { params => - def links(lm: LazyModule): Seq[UcieChipletLink] = - lm.getChildren.reverse.flatMap { - case link: UcieChipletLink => Seq(link) - case child => links(child) - } - val ucieLinks = links(this) - require( - ucieLinks.size == UciePort.all(p).size, - s"found ${ucieLinks.size} UCIe links under the subsystem, but the " + - s"chiplet router has ${UciePort.all(p).size} UCIe ports" - ) +object UcieControl { + def connect(system: BaseSubsystem)(implicit p: Parameters): Unit = + p(ChipletRoutingKey).foreach { params => + def links(lm: LazyModule): Seq[UcieChipletLink] = + lm.getChildren.reverse.flatMap { + case link: UcieChipletLink => Seq(link) + case child => links(child) + } + val ucieLinks = links(system) + require( + ucieLinks.size == UciePort.all(p).size, + s"found ${ucieLinks.size} UCIe links under the system, but the " + + s"chiplet router has ${UciePort.all(p).size} UCIe ports" + ) - val cbus = locateTLBusWrapper(params.controlBusWhere) - ucieLinks.foreach { link => - link.ucie.chipDigitalClockNode := cbus.fixedClockNode - cbus.coupleTo(s"${link.name}_clk_control") { - link.ucie.clkRegNode := TLWidthWidget(cbus.beatBytes) := TLBuffer() := _ + val cbus = system.locateTLBusWrapper(params.controlBusWhere) + ucieLinks.foreach { link => + cbus.coupleTo(s"${link.name}_control") { + link.regNode := TLWidthWidget(cbus.beatBytes) := TLBuffer() := + TLFragmenter(cbus.beatBytes, cbus.blockBytes) := TLBuffer() := _ + } } } - } } diff --git a/ucie b/ucie index 3fbc560..4db6449 160000 --- a/ucie +++ b/ucie @@ -1 +1 @@ -Subproject commit 3fbc560b3c6060a69b1052603d8c2105e40edcae +Subproject commit 4db6449716976a79765828a6dc27547c6a0c6366 From 0633c21fdc6f3fd9ef38e2ad4c7908971f65f544 Mon Sep 17 00:00:00 2001 From: Rahul Kumar Date: Wed, 14 Oct 2026 06:38:37 -0700 Subject: [PATCH 4/5] bump submodules --- saturn-vectors | 2 +- tacit | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/saturn-vectors b/saturn-vectors index 4956f75..f716212 160000 --- a/saturn-vectors +++ b/saturn-vectors @@ -1 +1 @@ -Subproject commit 4956f75a04e9740df3edea1857fdc9960501d26a +Subproject commit f7162129179a22e49f1f6b7781d311fbfa563ce6 diff --git a/tacit b/tacit index 8e9db5b..8ca1841 160000 --- a/tacit +++ b/tacit @@ -1 +1 @@ -Subproject commit 8e9db5bc4d7b07f727368055115e57f192dbc798 +Subproject commit 8ca1841d4752c2b6e6942682bfb3f323417d71fd From 3689e7eeec8d9c6c71ec7971883c8d9985b56b1c Mon Sep 17 00:00:00 2001 From: Rahul Kumar Date: Thu, 15 Oct 2026 16:38:29 -0700 Subject: [PATCH 5/5] work on ucie pd --- .github/workflows/ci.yml | 18 +++++++++------- saturn-vectors | 2 +- src/Iris.scala | 1 - src/TinyIris.scala | 1 - src/UcieComplex.scala | 45 ++-------------------------------------- tacit | 2 +- 6 files changed, 14 insertions(+), 55 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa03246..029d405 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,16 +120,18 @@ jobs: -- -t "TinyIris should generate valid System Verilog for TinyIris" # PD hardens the two UCIe blocks as one hierarchical block, so both links - # have to sit inside a single UcieComplex module and share one UcieTL. - # Giving a port its own UcieTLParams.moduleId splits them again, and - # nothing else in the flow would notice. - - name: Check the UCIe blocks are grouped and deduped + # have to sit inside a single UcieComplex module. Each link is still its + # own UcieTL -- UcieTLParams.moduleId 0 and 1 -- so that PD can give each + # the lane clock distribution network laid out for its own bump field. + # Dropping a port's moduleId folds them back into one module, and nothing + # else in the flow would notice. + - name: Check the UCIe blocks are grouped, with one UcieTL per link run: | out=build/Iris_should_generate_valid_System_Verilog - n=$(grep -lE '^module UcieTL(_[A-Za-z0-9]+)?\(' "$out"/*.sv | wc -l) - if [ "$n" -ne 1 ]; then - echo "::error::expected 1 UcieTL module in $out, found $n" - grep -hE '^module UcieTL(_[A-Za-z0-9]+)?\(' "$out"/*.sv || true + tls=$(grep -hoE '^module UcieTL(_[A-Za-z0-9]+)?\(' "$out"/*.sv \ + | sed -E 's/^module //; s/\($//' | sort | paste -sd' ' -) + if [ "$tls" != "UcieTL UcieTL_1" ]; then + echo "::error::expected UcieTL modules UcieTL and UcieTL_1 in $out, found: ${tls:-none}" exit 1 fi if [ ! -f "$out/UcieComplex.sv" ]; then diff --git a/saturn-vectors b/saturn-vectors index f716212..4956f75 160000 --- a/saturn-vectors +++ b/saturn-vectors @@ -1 +1 @@ -Subproject commit f7162129179a22e49f1f6b7781d311fbfa563ce6 +Subproject commit 4956f75a04e9740df3edea1857fdc9960501d26a diff --git a/src/Iris.scala b/src/Iris.scala index 3ff3611..e6b9c34 100644 --- a/src/Iris.scala +++ b/src/Iris.scala @@ -55,7 +55,6 @@ class IrisSystem(implicit p: Parameters) class IrisTop(implicit p: Parameters) extends LazyModule with BindingScope { val system = LazyModule(new IrisSystem) - UcieControl.connect(system) val clockGroupsSourceNode = ClockGroupSourceNode( Seq(ClockGroupSourceParameters()) ) diff --git a/src/TinyIris.scala b/src/TinyIris.scala index daecb8d..6243c35 100644 --- a/src/TinyIris.scala +++ b/src/TinyIris.scala @@ -36,7 +36,6 @@ import sifive.blocks.inclusivecache.{InclusiveCachePortParameters} class TinyIrisTop(implicit p: Parameters) extends LazyModule with BindingScope { val system = LazyModule(new IrisSystem) - UcieControl.connect(system) val clockGroupsSourceNode = ClockGroupSourceNode( Seq(ClockGroupSourceParameters()) ) diff --git a/src/UcieComplex.scala b/src/UcieComplex.scala index 2a6cab9..820782f 100644 --- a/src/UcieComplex.scala +++ b/src/UcieComplex.scala @@ -2,9 +2,8 @@ package edu.berkeley.cs.iris import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.subsystem.{BaseSubsystem, TLBusWrapperLocation} -import freechips.rocketchip.tilelink.{TLBuffer, TLFragmenter, TLWidthWidget} -import edu.berkeley.cs.uciedigital.tilelink.{UcieChipletLink, UcieTLParams} +import freechips.rocketchip.subsystem.TLBusWrapperLocation +import edu.berkeley.cs.uciedigital.tilelink.UcieTLParams import testchipip.soc.{ ChipletLinkParams, ChipletLinkWrapper, @@ -82,43 +81,3 @@ object UciePort { .map(_.ports.collect { case UciePort(u) => u }) .getOrElse(Nil) } - -/** Attaches each UCIe link's register port, which the chiplet router can't. - * - * The router couples a port's control node to its control bus only when the - * port hands it a bare `TLRegisterNode`. A UCIe link's register port is a - * crossbar in front of its three register blocks -- PhyTest, controller and - * clocking -- so `UcieChipletLink` hands the router none and leaves the port - * to the top. This couples it to the router's control bus the way the router - * couples its own control nodes, with the fragmenter in front that the port - * needs. The router clocks the link, from a clock group the top drives off the - * same clock as the bus, so the port needs no crossing. - * - * Each top calls this on its system once the system is built. The router keeps - * its ports to itself, so the links are found by walking the system's - * children. - */ -object UcieControl { - def connect(system: BaseSubsystem)(implicit p: Parameters): Unit = - p(ChipletRoutingKey).foreach { params => - def links(lm: LazyModule): Seq[UcieChipletLink] = - lm.getChildren.reverse.flatMap { - case link: UcieChipletLink => Seq(link) - case child => links(child) - } - val ucieLinks = links(system) - require( - ucieLinks.size == UciePort.all(p).size, - s"found ${ucieLinks.size} UCIe links under the system, but the " + - s"chiplet router has ${UciePort.all(p).size} UCIe ports" - ) - - val cbus = system.locateTLBusWrapper(params.controlBusWhere) - ucieLinks.foreach { link => - cbus.coupleTo(s"${link.name}_control") { - link.regNode := TLWidthWidget(cbus.beatBytes) := TLBuffer() := - TLFragmenter(cbus.beatBytes, cbus.blockBytes) := TLBuffer() := _ - } - } - } -} diff --git a/tacit b/tacit index 8ca1841..8e9db5b 160000 --- a/tacit +++ b/tacit @@ -1 +1 @@ -Subproject commit 8ca1841d4752c2b6e6942682bfb3f323417d71fd +Subproject commit 8e9db5bc4d7b07f727368055115e57f192dbc798