diff --git a/src/main/scala/channel/Parameters.scala b/src/main/scala/channel/Parameters.scala index 6a03e9a..b9a5577 100644 --- a/src/main/scala/channel/Parameters.scala +++ b/src/main/scala/channel/Parameters.scala @@ -12,7 +12,8 @@ import constellation.noc.{HasNoCParams} case class FlowParams( ingressId: Int, egressId: Int, - vNetId: Int + vNetId: Int, + fifo: Boolean = false ) // END: FlowParams diff --git a/src/main/scala/noc/Parameters.scala b/src/main/scala/noc/Parameters.scala index cc1124d..a1cf48f 100644 --- a/src/main/scala/noc/Parameters.scala +++ b/src/main/scala/noc/Parameters.scala @@ -112,7 +112,8 @@ object InternalNoCParams { ingressNode=ingressNode, egressNode=egressNode, ingressNodeId=nocParams.ingresses.take(f.ingressId).count(_.destId == ingressNode), - egressNodeId=nocParams.egresses.take(f.egressId).count(_.srcId == egressNode) + egressNodeId=nocParams.egresses.take(f.egressId).count(_.srcId == egressNode), + fifo = f.fifo ) } val ingressParams = nocParams.ingresses.zipWithIndex.map { case (u,i) => { @@ -174,6 +175,8 @@ object InternalNoCParams { s"Failed to route $flow at $head \n $stack \n ${nextChannelParamMap(head.dst)}") require((nexts.toSet & stack.toSet).size == 0, s"$flow, $nexts, $stack") + require(!(flow.fifo && nexts.map(_.dst).distinct.size != 1), + s"FIFO flow $flow at $head routes to multiple possible next-nodes \n $nexts") stack = Seq(nexts.head) ++ stack unexplored = nexts.tail.filter(n => !unexplored.contains(n)) ++ unexplored } else { diff --git a/src/main/scala/router/InputUnit.scala b/src/main/scala/router/InputUnit.scala index 9224187..97a006b 100644 --- a/src/main/scala/router/InputUnit.scala +++ b/src/main/scala/router/InputUnit.scala @@ -175,6 +175,7 @@ class InputUnit(cParam: ChannelParams, outParams: Seq[ChannelParams], val g = UInt(3.W) val vc_sel = MixedVec(allOutParams.map { u => Vec(u.nVirtualChannels, Bool()) }) val flow = new FlowRoutingBundle + val fifo_deps = UInt(nVirtualChannels.W) } val input_buffer = Module(new InputBuffer(cParam)) @@ -190,6 +191,16 @@ class InputUnit(cParam: ChannelParams, outParams: Seq[ChannelParams], val states = Reg(Vec(nVirtualChannels, new InputState)) + val anyFifo = cParam.possibleFlows.map(_.fifo).reduce(_||_) + val allFifo = cParam.possibleFlows.map(_.fifo).reduce(_&&_) + + if (anyFifo) { + val idle_mask = VecInit(states.map(_.g === g_i)).asUInt + for (s <- states) + for (i <- 0 until nVirtualChannels) + s.fifo_deps := s.fifo_deps & ~idle_mask + } + for (i <- 0 until cParam.srcSpeedup) { when (io.in.flit(i).fire() && io.in.flit(i).bits.head) { val id = io.in.flit(i).bits.virt_channel_id @@ -204,6 +215,12 @@ class InputUnit(cParam: ChannelParams, outParams: Seq[ChannelParams], } } states(id).flow := io.in.flit(i).bits.flow + if (anyFifo) { + val fifo = cParam.possibleFlows.filter(_.fifo).map(_.isFlow(io.in.flit(i).bits.flow)).toSeq.orR + states(id).fifo_deps := VecInit(states.zipWithIndex.map { case (s, j) => + s.g =/= g_i && s.flow.asUInt === io.in.flit(i).bits.flow.asUInt && j.U =/= id + }).asUInt + } } } @@ -246,7 +263,7 @@ class InputUnit(cParam: ChannelParams, outParams: Seq[ChannelParams], states.zipWithIndex.map { case (s,idx) => if (virtualChannelParams(idx).traversable) { - vcalloc_vals(idx) := s.g === g_v + vcalloc_vals(idx) := s.g === g_v && s.fifo_deps === 0.U vcalloc_reqs(idx).in_vc := idx.U vcalloc_reqs(idx).vc_sel := s.vc_sel vcalloc_reqs(idx).flow := s.flow @@ -298,6 +315,7 @@ class InputUnit(cParam: ChannelParams, outParams: Seq[ChannelParams], r.bits := DontCare } } + io.debug.sa_stall := PopCount(salloc_arb.io.in.map(r => r.valid && !r.ready)) io.salloc_req <> salloc_arb.io.out when (io.block) { diff --git a/src/main/scala/routing/Types.scala b/src/main/scala/routing/Types.scala index 3ce9bd5..d244cf7 100644 --- a/src/main/scala/routing/Types.scala +++ b/src/main/scala/routing/Types.scala @@ -46,7 +46,8 @@ case class FlowRoutingInfo( ingressNode: Int, ingressNodeId: Int, egressNode: Int, - egressNodeId: Int + egressNodeId: Int, + fifo: Boolean ) { // END: FlowRoutingInfo def isFlow(f: FlowRoutingBundle): Bool = { diff --git a/src/main/scala/test/Configs.scala b/src/main/scala/test/Configs.scala index 534f68c..5dac02e 100644 --- a/src/main/scala/test/Configs.scala +++ b/src/main/scala/test/Configs.scala @@ -53,7 +53,7 @@ class TestConfig02 extends NoCTesterConfig(NoCTesterParams(NoCParams( ), ingresses = Seq(0, 0).map { i => UserIngressParams(i) }, egresses = Seq(1, 1).map { i => UserEgressParams(1) }, - flows = Seq.tabulate(2, 2) { (s, d) => FlowParams(s, d, 0) }.flatten, + flows = Seq.tabulate(2, 2) { (s, d) => FlowParams(s, d, 0, fifo=true) }.flatten, routingRelation = UnidirectionalLineRouting() ))) class TestConfig03 extends NoCTesterConfig(NoCTesterParams(NoCParams( @@ -155,7 +155,7 @@ class TestConfig14 extends NoCTesterConfig(NoCTesterParams(NoCParams( channelParamGen = (a, b) => UserChannelParams(Seq.fill(4) { UserVirtualChannelParams(5) }), ingresses = Seq(0, 2).map { i => UserIngressParams(i) }, egresses = Seq(1, 3).map { i => UserEgressParams(i) }, - flows = Seq.tabulate(2, 2) { (s, d) => FlowParams(s, d, 0) }.flatten, + flows = Seq.tabulate(2, 2) { (s, d) => FlowParams(s, d, 0, fifo=true) }.flatten, routingRelation = UnidirectionalTorus1DDatelineRouting() ))) class TestConfig15 extends NoCTesterConfig(NoCTesterParams( @@ -216,7 +216,7 @@ class TestConfig20 extends NoCTesterConfig(NoCTesterParams( flows = Seq.tabulate(10, 10) { (s, d) => FlowParams(s, d, 0) }.flatten, routingRelation = BidirectionalTorus1DRandomRouting() ), - inputFlitStallProbability = 0.9 + inputPacketStallProbability = 0.90 )) class TestConfig21 extends NoCTesterConfig(NoCTesterParams( NoCParams( @@ -330,7 +330,7 @@ class TestConfig31 extends NoCTesterConfig(NoCTesterParams(NoCParams( channelParamGen = (a, b) => UserChannelParams(Seq.fill(4) { UserVirtualChannelParams(5) }), ingresses = (0 until 18).map { i => UserIngressParams(i) }, egresses = (0 until 18).map { i => UserEgressParams(i) }, - flows = Seq.tabulate(18, 18) { (s, d) => FlowParams(s, d, 0) }.flatten, + flows = Seq.tabulate(18, 18) { (s, d) => FlowParams(s, d, 0, fifo=true) }.flatten, routingRelation = Mesh2DDimensionOrderedRouting() ))) class TestConfig32 extends NoCTesterConfig(NoCTesterParams(NoCParams( @@ -619,7 +619,7 @@ class TestConfig61 extends NoCTesterConfig(NoCTesterParams(NoCParams( channelParamGen = (a, b) => UserChannelParams(Seq.fill(4) { UserVirtualChannelParams(5) }), ingresses = (0 until 25).map { i => UserIngressParams(i) }, egresses = (0 until 25).map { i => UserEgressParams(i) }, - flows = Seq.tabulate(25, 25) { (s, d) => FlowParams(s, d, 0) }.flatten, + flows = Seq.tabulate(25, 25) { (s, d) => FlowParams(s, d, 0, fifo=true) }.flatten, routingRelation = TerminalRouterRouting(Mesh2DDimensionOrderedRouting()) ))) class TestConfig62 extends NoCTesterConfig(NoCTesterParams(NoCParams( diff --git a/src/main/scala/test/TestHarness.scala b/src/main/scala/test/TestHarness.scala index 7914852..0e4c0f9 100644 --- a/src/main/scala/test/TestHarness.scala +++ b/src/main/scala/test/TestHarness.scala @@ -49,7 +49,8 @@ case object NoCTesterKey extends Field[NoCTesterParams](NoCTesterParams()) class Payload extends Bundle { val tsc = UInt(32.W) - val rob_idx = UInt(16.W) + val rob_idx = UInt(8.W) + val flow_idx = UInt(8.W) val flits_fired = UInt(16.W) } @@ -71,6 +72,7 @@ class InputGen(idx: Int, cParams: IngressChannelParams) val flits_left = RegInit(0.U(flitIdBits.W)) val flits_fired = RegInit(0.U(flitIdBits.W)) val egress = Reg(UInt(log2Ceil(nEgresses).W)) + val flow = Reg(UInt(log2Ceil(cParams.possibleFlows.size).W)) val payload = Reg(new Payload) val can_fire = (flits_left === 0.U) && io.rob_ready @@ -78,14 +80,17 @@ class InputGen(idx: Int, cParams: IngressChannelParams) val packet_remaining = if (p(NoCTesterKey).constPacketSize) maxFlits.U else (LFSR(20) % maxFlits.U) val random_flit_delay = (LFSR(20) < (inputFlitStallProbability * (1 << 20)).toInt.U) val random_packet_delay = (LFSR(20) < (inputPacketStallProbability * (1 << 20)).toInt.U) + val flow_idx = LFSR(20) % cParams.possibleFlows.size.U + val flow_ctrs = RegInit(VecInit.fill(cParams.possibleFlows.size) { 0.U(8.W) }) io.out.valid := !random_packet_delay && flits_left === 0.U && io.rob_ready io.out.bits.head := true.B io.out.bits.tail := packet_remaining === 0.U - io.out.bits.egress_id := VecInit(cParams.possibleFlows.toSeq.map(_.egressId.U))(LFSR(20) % cParams.possibleFlows.size.U) + io.out.bits.egress_id := VecInit(cParams.possibleFlows.toSeq.map(_.egressId.U))(flow_idx) val out_payload = Wire(new Payload) io.out.bits.payload := out_payload.asUInt out_payload.tsc := io.tsc out_payload.rob_idx := io.rob_idx + out_payload.flow_idx := flow_ctrs(flow_idx) out_payload.flits_fired := 0.U io.n_flits := packet_remaining + 1.U @@ -95,6 +100,7 @@ class InputGen(idx: Int, cParams: IngressChannelParams) flits_left := packet_remaining payload := out_payload egress := io.out.bits.egress_id + flow := flow_idx flits_fired := 1.U } when (flits_left =/= 0.U) { @@ -110,7 +116,10 @@ class InputGen(idx: Int, cParams: IngressChannelParams) flits_left := flits_left - 1.U } } - + when (io.out.fire && io.out.bits.tail) { + val idx = Mux(io.out.bits.head, flow_idx, flow) + flow_ctrs(idx) := flow_ctrs(idx) + 1.U + } } class NoCTester(inputParams: Seq[IngressChannelParams], outputParams: Seq[EgressChannelParams])(implicit val p: Parameters) extends Module with HasNoCParams { @@ -196,7 +205,13 @@ class NoCTester(inputParams: Seq[IngressChannelParams], outputParams: Seq[Egress val packet_valid = RegInit(false.B) val packet_rob_idx = Reg(UInt(log2Ceil(robSz).W)) + val flow_ctrs = RegInit(VecInit.fill(outputParams(i).possibleFlows.size) { 0.U(8.W) }) when (o.flit.fire()) { + val flows = outputParams(i).possibleFlows.toSeq + val fifo = flows.filter(_.fifo).map(_.ingressId.U === o.flit.bits.ingress_id).orR + val flow_id = flows.zipWithIndex.map { case (f, fid) => + Mux(f.ingressId.U === o.flit.bits.ingress_id, fid.U, 0.U) + }.reduce(_|_) assert(rob_valids(rob_idx), cf"out[${i.toString}] unexpected response") assert(rob_payload(rob_idx).asUInt === o.flit.bits.payload.asUInt, cf"out[${i.toString}] incorrect payload"); @@ -204,6 +219,12 @@ class NoCTester(inputParams: Seq[IngressChannelParams], outputParams: Seq[Egress assert(i.U === rob_egress_id(rob_idx), cf"out[${i.toString}] incorrect destination") assert(rob_flits_returned(rob_idx) < rob_n_flits(rob_idx), cf"out[${i.toString}] too many flits returned") assert((!packet_valid && o.flit.bits.head) || rob_idx === packet_rob_idx) + when (fifo && o.flit.bits.tail) { + assert(flow_ctrs(flow_id) === o.flit.bits.payload.asTypeOf(new Payload).flow_idx, + cf"out[${i.toString}] not fifo") + flow_ctrs(flow_id) := flow_ctrs(flow_id) + 1.U + } + when (o.flit.bits.head && enable_print_latency) { val fmtStr = s"%d, $i, %d\n"