1
0

tilelink2 Atomics: support Logical AMOs

This commit is contained in:
Wesley W. Terpstra 2016-09-21 20:08:17 -07:00
parent 4066fbe18f
commit 5b80fe5b51

View File

@ -64,12 +64,6 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
val AMO = UInt(2) // AccessDataAck sent up D waiting for A availability val AMO = UInt(2) // AccessDataAck sent up D waiting for A availability
val ACK = UInt(1) // Put sent down A waiting for PutAck from D val ACK = UInt(1) // Put sent down A waiting for PutAck from D
class CAMEntry extends Bundle {
val state = UInt(width = 2)
val fifoId = UInt(width = log2Up(domainsNeedingHelp.size))
val bits = new TLBundleA(in.a.bits.params)
}
def helper(select: Seq[Bool], x: Seq[TransferSizes], lgSize: UInt) = def helper(select: Seq[Bool], x: Seq[TransferSizes], lgSize: UInt) =
if (!passthrough) Bool(false) else if (!passthrough) Bool(false) else
if (x.map(_ == x(0)).reduce(_ && _)) x(0).containsLg(lgSize) else if (x.map(_ == x(0)).reduce(_ && _)) x(0).containsLg(lgSize) else
@ -83,6 +77,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
class CAM_A extends Bundle { class CAM_A extends Bundle {
val bits = new TLBundleA(out.a.bits.params) val bits = new TLBundleA(out.a.bits.params)
val fifoId = UInt(width = log2Up(domainsNeedingHelp.size)) val fifoId = UInt(width = log2Up(domainsNeedingHelp.size))
val lut = UInt(width = 4)
} }
class CAM_D extends Bundle { class CAM_D extends Bundle {
val data = UInt(width = out.a.bits.params.dataBits) val data = UInt(width = out.a.bits.params.dataBits)
@ -112,8 +107,8 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
val a_cam_any_put = cam_amo.reduce(_ || _) val a_cam_any_put = cam_amo.reduce(_ || _)
val a_cam_por_put = cam_amo.scanLeft(Bool(false))(_||_).init val a_cam_por_put = cam_amo.scanLeft(Bool(false))(_||_).init
val a_cam_sel_put = (cam_amo zip a_cam_por_put) map { case (a, b) => a && !b } val a_cam_sel_put = (cam_amo zip a_cam_por_put) map { case (a, b) => a && !b }
val a_cam_adata = PriorityMux(cam_amo, cam_a.map(_.bits)) val a_cam_a = PriorityMux(cam_amo, cam_a)
val a_cam_ddata = PriorityMux(cam_amo, cam_d.map(_.data)) val a_cam_d = PriorityMux(cam_amo, cam_d)
// Does the A request conflict with an inflight AMO? // Does the A request conflict with an inflight AMO?
val a_fifoId = Mux1H(a_select, camFifoIds) val a_fifoId = Mux1H(a_select, camFifoIds)
@ -124,8 +119,19 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
val a_cam_por_free = cam_free.scanLeft(Bool(false))(_||_).init val a_cam_por_free = cam_free.scanLeft(Bool(false))(_||_).init
val a_cam_sel_free = (cam_free zip a_cam_por_free) map { case (a,b) => a && !b } val a_cam_sel_free = (cam_free zip a_cam_por_free) map { case (a,b) => a && !b }
// !!! perform the AMO op // Logical AMO
val amo_data = a_cam_adata.data + a_cam_ddata val lut = Vec(a_cam_a.lut.toBools)
val indexes = (a_cam_a.bits.data.toBools zip a_cam_d.data.toBools) map { case (a,d) => a.asUInt << 1 | d.asUInt }
val logic_out = Cat(indexes.map(x => lut(x).asUInt).reverse)
// Arithmetic AMO
val arith_out = a_cam_a.bits.data + a_cam_d.data
// AMO result data
val amo_data =
if (!logical) arith_out else
if (!arithmetic) logic_out else
Mux(a_cam_a.bits.opcode(0), logic_out, arith_out)
// Potentially mutate the message from inner // Potentially mutate the message from inner
val source_i = Wire(in.a) val source_i = Wire(in.a)
@ -141,7 +147,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
// Potentially take the message from the CAM // Potentially take the message from the CAM
val source_c = Wire(in.a) val source_c = Wire(in.a)
source_c.valid := a_cam_any_put source_c.valid := a_cam_any_put
source_c.bits := edgeOut.Put(a_cam_adata.source, edgeIn.address(a_cam_adata), a_cam_adata.size, amo_data)._2 source_c.bits := edgeOut.Put(a_cam_a.bits.source, edgeIn.address(a_cam_a.bits), a_cam_a.bits.size, amo_data)._2
// Finishing an AMO from the CAM has highest priority // Finishing an AMO from the CAM has highest priority
TLArbiter(TLArbiter.lowestIndexFirst)(out.a, (UInt(1), source_c), (edgeOut.numBeats(in.a.bits), source_i)) TLArbiter(TLArbiter.lowestIndexFirst)(out.a, (UInt(1), source_c), (edgeOut.numBeats(in.a.bits), source_i))
@ -152,6 +158,11 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
when (en) { when (en) {
r.fifoId := a_fifoId r.fifoId := a_fifoId
r.bits := in.a.bits r.bits := in.a.bits
r.lut := MuxLookup(in.a.bits.param(1, 0), UInt(0, width = 4), Array(
TLAtomics.AND -> UInt(0x8),
TLAtomics.OR -> UInt(0xe),
TLAtomics.XOR -> UInt(0x6),
TLAtomics.SWAP -> UInt(0xc)))
} }
} }
(a_cam_sel_free zip cam_s) foreach { case (en, r) => (a_cam_sel_free zip cam_s) foreach { case (en, r) =>