reduce hardware usage of Comparator to allow it to synthesize
This commit is contained in:
parent
18967642de
commit
d435bb4185
@ -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
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user