1
0

reduce hardware usage of Comparator to allow it to synthesize

This commit is contained in:
Howard Mao 2016-07-12 10:54:18 -07:00
parent 18967642de
commit d435bb4185
2 changed files with 62 additions and 20 deletions

View File

@ -48,7 +48,7 @@ object LFSR64
object NoiseMaker object NoiseMaker
{ {
def apply(wide: Int, increment: Bool = Bool(true)): UInt = { def apply(wide: Int, increment: Bool = Bool(true)): UInt = {
val lfsrs = Seq.fill((wide+63)/64) { LFSR64() } val lfsrs = Seq.fill((wide+63)/64) { LFSR64(increment) }
Cat(lfsrs)(wide-1,0) Cat(lfsrs)(wide-1,0)
} }
} }
@ -64,7 +64,7 @@ class ComparatorSource(implicit val p: Parameters) extends Module
with HasTileLinkParameters with HasTileLinkParameters
{ {
val io = new Bundle { val io = new Bundle {
val out = Valid(new Acquire) val out = Decoupled(new Acquire)
val finished = Bool(OUTPUT) val finished = Bool(OUTPUT)
} }
@ -81,18 +81,19 @@ class ComparatorSource(implicit val p: Parameters) extends Module
io.out.valid := !finished && valid io.out.valid := !finished && valid
// Generate random operand sizes // Generate random operand sizes
val raw_operand_size = NoiseMaker(2) | UInt(0, M_SZ) val inc = io.out.fire()
val raw_operand_size = NoiseMaker(2, inc) | UInt(0, M_SZ)
val max_operand_size = UInt(log2Up(tlDataBytes)) val max_operand_size = UInt(log2Up(tlDataBytes))
val get_operand_size = Mux(raw_operand_size > max_operand_size, max_operand_size, raw_operand_size) val get_operand_size = Mux(raw_operand_size > max_operand_size, max_operand_size, raw_operand_size)
val atomic_operand_size = Mux(NoiseMaker(1)(0), MT_W, MT_D) val atomic_operand_size = Mux(NoiseMaker(1, inc)(0), MT_W, MT_D)
// Generate random, but valid addr_bytes // Generate random, but valid addr_bytes
val raw_addr_byte = NoiseMaker(tlByteAddrBits) val raw_addr_byte = NoiseMaker(tlByteAddrBits, inc)
val get_addr_byte = raw_addr_byte & ~MaskMaker(tlByteAddrBits, get_operand_size) val get_addr_byte = raw_addr_byte & ~MaskMaker(tlByteAddrBits, get_operand_size)
val atomic_addr_byte = raw_addr_byte & ~MaskMaker(tlByteAddrBits, atomic_operand_size) val atomic_addr_byte = raw_addr_byte & ~MaskMaker(tlByteAddrBits, atomic_operand_size)
// Only allow some of the possible choices (M_XA_MAXU untested) // Only allow some of the possible choices (M_XA_MAXU untested)
val atomic_opcode = MuxLookup(NoiseMaker(3), M_XA_SWAP, Array( val atomic_opcode = MuxLookup(NoiseMaker(3, inc), M_XA_SWAP, Array(
UInt("b000") -> M_XA_ADD, UInt("b000") -> M_XA_ADD,
UInt("b001") -> M_XA_XOR, UInt("b001") -> M_XA_XOR,
UInt("b010") -> M_XA_OR, UInt("b010") -> M_XA_OR,
@ -106,10 +107,10 @@ class ComparatorSource(implicit val p: Parameters) extends Module
val addr_block_mask = MaskMaker(tlBlockAddrBits, UInt(targetWidth-tlBeatAddrBits-tlByteAddrBits)) val addr_block_mask = MaskMaker(tlBlockAddrBits, UInt(targetWidth-tlBeatAddrBits-tlByteAddrBits))
// Generate some random values // Generate some random values
val addr_block = NoiseMaker(tlBlockAddrBits) & addr_block_mask val addr_block = NoiseMaker(tlBlockAddrBits, inc) & addr_block_mask
val addr_beat = NoiseMaker(tlBeatAddrBits) val addr_beat = NoiseMaker(tlBeatAddrBits, inc)
val wmask = NoiseMaker(tlDataBytes) val wmask = NoiseMaker(tlDataBytes, inc)
val data = NoiseMaker(tlDataBits) val data = NoiseMaker(tlDataBits, inc)
val client_xact_id = UInt(0) // filled by Client val client_xact_id = UInt(0) // filled by Client
// Random transactions // Random transactions
@ -127,7 +128,7 @@ class ComparatorSource(implicit val p: Parameters) extends Module
val getPrefetch = if (prefetches) val getPrefetch = if (prefetches)
GetPrefetch(client_xact_id, addr_block) GetPrefetch(client_xact_id, addr_block)
else get else get
val a_type_sel = NoiseMaker(3) val a_type_sel = NoiseMaker(3, inc)
// We must initially putBlock all of memory to have a consistent starting state // We must initially putBlock all of memory to have a consistent starting state
val final_addr_block = addr_block_mask + UInt(1) val final_addr_block = addr_block_mask + UInt(1)
@ -152,7 +153,7 @@ class ComparatorSource(implicit val p: Parameters) extends Module
} }
val idx = Reg(init = UInt(0, log2Up(nOperations))) val idx = Reg(init = UInt(0, log2Up(nOperations)))
when (valid && !finished) { when (io.out.fire()) {
when (!done_wipe) { when (!done_wipe) {
printf("[acq %d]: PutBlock(addr_block = %x, data = %x)\n", printf("[acq %d]: PutBlock(addr_block = %x, data = %x)\n",
idx, wipe_addr_block, data) idx, wipe_addr_block, data)
@ -219,9 +220,7 @@ class ComparatorClient(val target: Long)(implicit val p: Parameters) extends Mod
val ready = RegInit(Vec.fill(xacts) {Bool(false)}) val ready = RegInit(Vec.fill(xacts) {Bool(false)})
val result = Reg(Vec(xacts, new Grant)) val result = Reg(Vec(xacts, new Grant))
// Big enough to never stall the broadcast Source val buffer = Queue(io.in, xacts)
// (test code not synthesized => big SRAMs are OK)
val buffer = Queue(io.in, nOperations)
val queue = Module(new Queue(io.tl.acquire.bits.client_xact_id, xacts)) val queue = Module(new Queue(io.tl.acquire.bits.client_xact_id, xacts))
val isMultiOut = buffer.bits.hasMultibeatData() val isMultiOut = buffer.bits.hasMultibeatData()
@ -246,9 +245,9 @@ class ComparatorClient(val target: Long)(implicit val p: Parameters) extends Mod
io.tl.acquire.bits.addr_block := buffer.bits.addr_block + offset io.tl.acquire.bits.addr_block := buffer.bits.addr_block + offset
io.tl.acquire.bits.client_xact_id := xact_id io.tl.acquire.bits.client_xact_id := xact_id
when (isMultiOut) { when (isMultiOut) {
val multiplier = beatOut + UInt(1, tlBeatAddrBits + 1) val dataOut = (buffer.bits.data << beatOut) + buffer.bits.data // mix the data up a bit
io.tl.acquire.bits.addr_beat := beatOut io.tl.acquire.bits.addr_beat := beatOut
io.tl.acquire.bits.data := buffer.bits.data * multiplier // mix the data up a bit io.tl.acquire.bits.data := dataOut
} }
when (io.tl.acquire.fire()) { when (io.tl.acquire.fire()) {
@ -364,10 +363,10 @@ class ComparatorCore(implicit p: Parameters) extends GroundTest()(p)
val source = Module(new ComparatorSource) val source = Module(new ComparatorSource)
val sink = Module(new ComparatorSink) val sink = Module(new ComparatorSink)
val broadcast = Broadcaster(source.io.out, nTargets)
val clients = targets.zipWithIndex.map { case (target, index) => val clients = targets.zipWithIndex.map { case (target, index) =>
val client = Module(new ComparatorClient(target)) val client = Module(new ComparatorClient(target))
assert (client.io.in.ready) // must accept client.io.in <> broadcast(index)
client.io.in := source.io.out
io.mem(index) <> client.io.tl io.mem(index) <> client.io.tl
sink.io.in(index) <> client.io.out sink.io.in(index) <> client.io.out
client client

View File

@ -177,3 +177,46 @@ object DebugCombiner {
out out
} }
} }
/**
* Takes in data on one decoupled interface and broadcasts it to
* N decoupled output interfaces
*/
class Broadcaster[T <: Data](typ: T, n: Int) extends Module {
val io = new Bundle {
val in = Decoupled(typ).flip
val out = Vec(n, Decoupled(typ))
}
require (n > 0)
if (n == 1) {
io.out.head <> io.in
} else {
val idx = Reg(init = UInt(0, log2Up(n)))
val save = Reg(typ)
io.out.head.valid := idx === UInt(0) && io.in.valid
io.out.head.bits := io.in.bits
for (i <- 1 until n) {
io.out(i).valid := idx === UInt(i)
io.out(i).bits := save
}
io.in.ready := io.out.head.ready && idx === UInt(0)
when (io.in.fire()) { save := io.in.bits }
when (io.out(idx).fire()) {
when (idx === UInt(n - 1)) { idx := UInt(0) }
.otherwise { idx := idx + UInt(1) }
}
}
}
object Broadcaster {
def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = {
val split = Module(new Broadcaster(in.bits, n))
split.io.in <> in
split.io.out
}
}