tilelink2 SourceShrinker: a concurrency reducing adapter
This commit is contained in:
		| @@ -72,7 +72,6 @@ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4) | |||||||
|       mem.write(memAddress, wdata, in.a.bits.mask.toBools) |       mem.write(memAddress, wdata, in.a.bits.mask.toBools) | ||||||
|     } |     } | ||||||
|     val ren = in.a.fire() && read |     val ren = in.a.fire() && read | ||||||
|     def holdUnless[T <: Data](in : T, enable: Bool): T = Mux(!enable, RegEnable(in, enable), in) |  | ||||||
|     rdata := holdUnless(mem.read(memAddress, ren), RegNext(ren)) |     rdata := holdUnless(mem.read(memAddress, ren), RegNext(ren)) | ||||||
|  |  | ||||||
|     // Tie off unused channels |     // Tie off unused channels | ||||||
|   | |||||||
							
								
								
									
										79
									
								
								src/main/scala/uncore/tilelink2/SourceShrinker.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/main/scala/uncore/tilelink2/SourceShrinker.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | // See LICENSE for license details. | ||||||
|  |  | ||||||
|  | package uncore.tilelink2 | ||||||
|  |  | ||||||
|  | import Chisel._ | ||||||
|  | import chisel3.internal.sourceinfo.SourceInfo | ||||||
|  | import diplomacy._ | ||||||
|  | import scala.math.{min,max} | ||||||
|  |  | ||||||
|  | class TLSourceShrinker(maxInFlight: Int) extends LazyModule | ||||||
|  | { | ||||||
|  |   private val client = TLClientParameters(sourceId = IdRange(0, maxInFlight)) | ||||||
|  |   val node = TLAdapterNode( | ||||||
|  |     // We erase all client information since we crush the source Ids | ||||||
|  |     clientFn  = { case _ => TLClientPortParameters(clients = Seq(client)) }, | ||||||
|  |     managerFn = { case Seq(mp) => mp }) | ||||||
|  |  | ||||||
|  |   lazy val module = new LazyModuleImp(this) { | ||||||
|  |     val io = new Bundle { | ||||||
|  |       val in  = node.bundleIn | ||||||
|  |       val out = node.bundleOut | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     val edgeIn = node.edgesIn(0) | ||||||
|  |     val edgeOut = node.edgesOut(0) | ||||||
|  |     val in = io.in(0) | ||||||
|  |     val out = io.out(0) | ||||||
|  |  | ||||||
|  |     // Acquires cannot pass this adapter; it makes Probes impossible | ||||||
|  |     require (!edgeIn.client.anySupportProbe ||  | ||||||
|  |              !edgeOut.manager.anySupportAcquire) | ||||||
|  |  | ||||||
|  |     out.b.ready := Bool(true) | ||||||
|  |     out.c.valid := Bool(false) | ||||||
|  |     out.e.valid := Bool(false) | ||||||
|  |     in.b.valid := Bool(false) | ||||||
|  |     in.c.ready := Bool(true) | ||||||
|  |     in.e.ready := Bool(true) | ||||||
|  |  | ||||||
|  |     // State tracking | ||||||
|  |     val sourceIdMap = Mem(maxInFlight, in.a.bits.source) | ||||||
|  |     val allocated = RegInit(UInt(0, width = maxInFlight)) | ||||||
|  |     val nextFreeOH = ~(leftOR(~allocated) << 1) & ~allocated | ||||||
|  |     val nextFree = OHToUInt(nextFreeOH) | ||||||
|  |     val full = allocated.andR() | ||||||
|  |  | ||||||
|  |     val a_first = edgeIn.first(in.a) | ||||||
|  |     val d_last  = edgeIn.last(in.d) | ||||||
|  |  | ||||||
|  |     val block = a_first && full | ||||||
|  |     in.a.ready := out.a.ready && !block | ||||||
|  |     out.a.valid := in.a.valid && !block | ||||||
|  |     out.a.bits := in.a.bits | ||||||
|  |     out.a.bits.source := holdUnless(nextFree, a_first) | ||||||
|  |  | ||||||
|  |     in.d <> out.d | ||||||
|  |     in.d.bits.source := sourceIdMap(out.d.bits.source) | ||||||
|  |  | ||||||
|  |     when (a_first && in.a.fire()) { | ||||||
|  |       sourceIdMap(nextFree) := in.a.bits.source | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     val alloc = a_first && in.a.fire() | ||||||
|  |     val free = d_last && in.d.fire() | ||||||
|  |     val alloc_id = Mux(alloc, nextFreeOH, UInt(0)) | ||||||
|  |     val free_id = Mux(free, UIntToOH(out.d.bits.source), UInt(0)) | ||||||
|  |     allocated := (allocated | alloc_id) & ~free_id | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | object TLSourceShrinker | ||||||
|  | { | ||||||
|  |   // applied to the TL source node; y.node := TLSourceShrinker(n)(x.node) | ||||||
|  |   def apply(maxInFlight: Int)(x: TLOutwardNode)(implicit sourceInfo: SourceInfo): TLOutwardNode = { | ||||||
|  |     val shrinker = LazyModule(new TLSourceShrinker(maxInFlight)) | ||||||
|  |     shrinker.node := x | ||||||
|  |     shrinker.node | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -13,6 +13,7 @@ package object tilelink2 | |||||||
|   def OH1ToOH(x: UInt) = (x << 1 | UInt(1)) & ~Cat(UInt(0, width=1), x) |   def OH1ToOH(x: UInt) = (x << 1 | UInt(1)) & ~Cat(UInt(0, width=1), x) | ||||||
|   def OH1ToUInt(x: UInt) = OHToUInt(OH1ToOH(x)) |   def OH1ToUInt(x: UInt) = OHToUInt(OH1ToOH(x)) | ||||||
|   def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0) |   def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0) | ||||||
|  |   def holdUnless[T <: Data](in : T, enable: Bool): T = Mux(!enable, RegEnable(in, enable), in) | ||||||
|   def trailingZeros(x: Int) = if (x > 0) Some(log2Ceil(x & -x)) else None |   def trailingZeros(x: Int) = if (x > 0) Some(log2Ceil(x & -x)) else None | ||||||
|   // Fill 1s from low bits to high bits |   // Fill 1s from low bits to high bits | ||||||
|   def leftOR(x: UInt) = { |   def leftOR(x: UInt) = { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user