From e909093f3788cd61b4e44691563eda4eeb88f364 Mon Sep 17 00:00:00 2001 From: Huy Vo Date: Mon, 1 Oct 2012 16:08:41 -0700 Subject: [PATCH] factoring out uncore into separate uncore repo --- rocket/src/main/scala/arbiter.scala | 1 + rocket/src/main/scala/coherence.scala | 765 -------------------------- rocket/src/main/scala/htif.scala | 1 + rocket/src/main/scala/icache.scala | 1 + rocket/src/main/scala/llc.scala | 437 --------------- rocket/src/main/scala/memserdes.scala | 1 + rocket/src/main/scala/nbdcache.scala | 1 + rocket/src/main/scala/tile.scala | 1 + rocket/src/main/scala/top.scala | 1 + rocket/src/main/scala/uncore.scala | 519 ----------------- 10 files changed, 7 insertions(+), 1721 deletions(-) delete mode 100644 rocket/src/main/scala/coherence.scala delete mode 100644 rocket/src/main/scala/llc.scala delete mode 100644 rocket/src/main/scala/uncore.scala diff --git a/rocket/src/main/scala/arbiter.scala b/rocket/src/main/scala/arbiter.scala index 93a72be0..95432dc8 100644 --- a/rocket/src/main/scala/arbiter.scala +++ b/rocket/src/main/scala/arbiter.scala @@ -3,6 +3,7 @@ package rocket import Chisel._; import Node._; import Constants._; +import uncore._ class ioUncachedRequestor extends Bundle { val xact_init = (new FIFOIO) { new TransactionInit } diff --git a/rocket/src/main/scala/coherence.scala b/rocket/src/main/scala/coherence.scala deleted file mode 100644 index 2517b08a..00000000 --- a/rocket/src/main/scala/coherence.scala +++ /dev/null @@ -1,765 +0,0 @@ -package rocket - -import Chisel._ -import Constants._ - -object TransactionInit -{ - def apply(x_type: Bits, addr: UFix, tile_xact_id: UFix) = { - val init = new TransactionInit - init.x_type := x_type - init.addr := addr - init.tile_xact_id := tile_xact_id - init - } - def apply(x_type: Bits, addr: UFix, tile_xact_id: UFix, write_mask: Bits) = { - val init = new TransactionInit - init.x_type := x_type - init.addr := addr - init.tile_xact_id := tile_xact_id - init.write_mask := write_mask - init - } - def apply(x_type: Bits, addr: UFix, tile_xact_id: UFix, subword_addr: UFix, atomic_opcode: UFix) = { - val init = new TransactionInit - init.x_type := x_type - init.addr := addr - init.tile_xact_id := tile_xact_id - init.subword_addr := subword_addr - init.atomic_opcode := atomic_opcode - init - } -} -class TransactionInit extends PhysicalAddress { - val x_type = Bits(width = X_INIT_TYPE_MAX_BITS) - val tile_xact_id = Bits(width = TILE_XACT_ID_BITS) - val write_mask = Bits(width = X_INIT_WRITE_MASK_BITS) - val subword_addr = Bits(width = X_INIT_SUBWORD_ADDR_BITS) - val atomic_opcode = Bits(width = X_INIT_ATOMIC_OP_BITS) -} - -class TransactionInitData extends MemData - -class TransactionAbort extends Bundle { - val tile_xact_id = Bits(width = TILE_XACT_ID_BITS) -} - -class ProbeRequest extends PhysicalAddress { - val p_type = Bits(width = P_REQ_TYPE_MAX_BITS) - val global_xact_id = Bits(width = GLOBAL_XACT_ID_BITS) -} - -class ProbeReply extends Bundle { - val p_type = Bits(width = P_REP_TYPE_MAX_BITS) - val global_xact_id = Bits(width = GLOBAL_XACT_ID_BITS) -} - -class ProbeReplyData extends MemData - -class TransactionReply extends MemData { - val x_type = Bits(width = X_REP_TYPE_MAX_BITS) - val tile_xact_id = Bits(width = TILE_XACT_ID_BITS) - val global_xact_id = Bits(width = GLOBAL_XACT_ID_BITS) - val require_ack = Bool() -} - -class TransactionFinish extends Bundle { - val global_xact_id = Bits(width = GLOBAL_XACT_ID_BITS) -} - -object cpuCmdToRW { - def apply(cmd: Bits): (Bool, Bool) = { - val store = (cmd === M_XWR) - val load = (cmd === M_XRD) - val amo = cmd(3).toBool - val read = load || amo || (cmd === M_PFR) || (cmd === M_PFW) - val write = store || amo - (read, write) - } -} - -abstract class CoherencePolicy { - def isHit (cmd: Bits, state: UFix): Bool - def isValid (state: UFix): Bool - - def needsTransactionOnSecondaryMiss(cmd: Bits, outstanding: TransactionInit): Bool - def needsTransactionOnCacheControl(cmd: Bits, state: UFix): Bool - def needsWriteback (state: UFix): Bool - - def newStateOnHit(cmd: Bits, state: UFix): UFix - def newStateOnCacheControl(cmd: Bits): UFix - def newStateOnWriteback(): UFix - def newStateOnFlush(): UFix - def newStateOnTransactionReply(incoming: TransactionReply, outstanding: TransactionInit): UFix - def newStateOnProbeRequest(incoming: ProbeRequest, state: UFix): Bits - - def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix - def getTransactionInitTypeOnSecondaryMiss(cmd: Bits, state: UFix, outstanding: TransactionInit): UFix - def getTransactionInitTypeOnCacheControl(cmd: Bits): Bits - def getTransactionInitTypeOnWriteback(): Bits - - def newProbeReply (incoming: ProbeRequest, state: UFix): ProbeReply - - def messageHasData (reply: ProbeReply): Bool - def messageHasData (init: TransactionInit): Bool - def messageHasData (reply: TransactionReply): Bool - def messageUpdatesDataArray (reply: TransactionReply): Bool - def messageIsUncached(init: TransactionInit): Bool - - def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool - def getTransactionReplyType(x_type: UFix, count: UFix): Bits - def getProbeRequestType(x_type: UFix, global_state: UFix): UFix - def needsMemRead(x_type: UFix, global_state: UFix): Bool - def needsMemWrite(x_type: UFix, global_state: UFix): Bool - def needsAckReply(x_type: UFix, global_state: UFix): Bool -} - -trait UncachedTransactions { - def getUncachedReadTransactionInit(addr: UFix, id: UFix): TransactionInit - def getUncachedWriteTransactionInit(addr: UFix, id: UFix): TransactionInit - def getUncachedReadWordTransactionInit(addr: UFix, id: UFix): TransactionInit - def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits): TransactionInit - def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix): TransactionInit -} - -abstract class CoherencePolicyWithUncached extends CoherencePolicy with UncachedTransactions - -abstract class IncoherentPolicy extends CoherencePolicy { - // UNIMPLEMENTED - def newStateOnProbeRequest(incoming: ProbeRequest, state: UFix): Bits = state - def newProbeReply (incoming: ProbeRequest, state: UFix): ProbeReply = { - val reply = new ProbeReply() - reply.p_type := UFix(0) - reply.global_xact_id := UFix(0) - reply - } - def messageHasData (reply: ProbeReply) = Bool(false) - def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = Bool(false) - def getTransactionReplyType(x_type: UFix, count: UFix): Bits = Bits(0) - def getProbeRequestType(x_type: UFix, global_state: UFix): UFix = UFix(0) - def needsMemRead(x_type: UFix, global_state: UFix): Bool = Bool(false) - def needsMemWrite(x_type: UFix, global_state: UFix): Bool = Bool(false) - def needsAckReply(x_type: UFix, global_state: UFix): Bool = Bool(false) -} - -class ThreeStateIncoherence extends IncoherentPolicy { - val tileInvalid :: tileClean :: tileDirty :: Nil = Enum(3){ UFix() } - val xactInitReadClean :: xactInitReadDirty :: xactInitWriteback :: Nil = Enum(3){ UFix() } - val xactReplyData :: xactReplyAck :: Nil = Enum(2){ UFix() } - val probeRepInvalidateAck :: Nil = Enum(1){ UFix() } - val uncachedTypeList = List() - val hasDataTypeList = List(xactInitWriteback) - - def isHit ( cmd: Bits, state: UFix): Bool = (state === tileClean || state === tileDirty) - def isValid (state: UFix): Bool = state != tileInvalid - - def needsTransactionOnSecondaryMiss(cmd: Bits, outstanding: TransactionInit) = Bool(false) - def needsTransactionOnCacheControl(cmd: Bits, state: UFix): Bool = state === tileDirty - def needsWriteback (state: UFix): Bool = state === tileDirty - - def newState(cmd: Bits, state: UFix): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, tileDirty, Mux(read, Mux(state === tileDirty, tileDirty, tileClean), state)) - } - def newStateOnHit(cmd: Bits, state: UFix): UFix = newState(cmd, state) - def newStateOnCacheControl(cmd: Bits) = tileInvalid //TODO - def newStateOnWriteback() = tileInvalid - def newStateOnFlush() = tileInvalid - def newStateOnTransactionReply(incoming: TransactionReply, outstanding: TransactionInit) = { - MuxLookup(incoming.x_type, tileInvalid, Array( - xactReplyData -> Mux(outstanding.x_type === xactInitReadDirty, tileDirty, tileClean), - xactReplyAck -> tileInvalid - )) - } - - def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write || cmd === M_PFW, xactInitReadDirty, xactInitReadClean) - } - def getTransactionInitTypeOnSecondaryMiss(cmd: Bits, state: UFix, outstanding: TransactionInit): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, xactInitReadDirty, outstanding.x_type) - } - def getTransactionInitTypeOnCacheControl(cmd: Bits): Bits = xactInitWriteback //TODO - def getTransactionInitTypeOnWriteback(): Bits = xactInitWriteback - - def messageHasData (init: TransactionInit): Bool = hasDataTypeList.map(t => init.x_type === t).reduceLeft(_||_) - def messageHasData (reply: TransactionReply) = (reply.x_type === xactReplyData) - def messageUpdatesDataArray (reply: TransactionReply) = (reply.x_type === xactReplyData) - def messageIsUncached(init: TransactionInit): Bool = uncachedTypeList.map(t => init.x_type === t).reduceLeft(_||_) -} - -class MICoherence extends CoherencePolicyWithUncached { - - val tileInvalid :: tileValid :: Nil = Enum(2){ UFix() } - val globalInvalid :: globalValid :: Nil = Enum(2){ UFix() } - - val xactInitReadExclusive :: xactInitReadUncached :: xactInitWriteUncached :: xactInitReadWordUncached :: xactInitWriteWordUncached :: xactInitAtomicUncached :: Nil = Enum(6){ UFix() } - val xactReplyReadExclusive :: xactReplyReadUncached :: xactReplyWriteUncached :: xactReplyReadWordUncached :: xactReplyWriteWordUncached :: xactReplyAtomicUncached :: Nil = Enum(6){ UFix() } - val probeReqInvalidate :: probeReqCopy :: Nil = Enum(2){ UFix() } - val probeRepInvalidateData :: probeRepCopyData :: probeRepInvalidateAck :: probeRepCopyAck :: Nil = Enum(4){ UFix() } - val uncachedTypeList = List(xactInitReadUncached, xactInitWriteUncached, xactReplyReadWordUncached, xactInitWriteWordUncached, xactInitAtomicUncached) - val hasDataTypeList = List(xactInitWriteUncached, xactInitWriteWordUncached, xactInitAtomicUncached) - - def isHit (cmd: Bits, state: UFix): Bool = state != tileInvalid - def isValid (state: UFix): Bool = state != tileInvalid - - def needsTransactionOnSecondaryMiss(cmd: Bits, outstanding: TransactionInit): Bool = (outstanding.x_type != xactInitReadExclusive) - def needsTransactionOnCacheControl(cmd: Bits, state: UFix): Bool = { - MuxLookup(cmd, (state === tileValid), Array( - M_INV -> (state === tileValid), - M_CLN -> (state === tileValid) - )) - } - def needsWriteback (state: UFix): Bool = { - needsTransactionOnCacheControl(M_INV, state) - } - - def newStateOnHit(cmd: Bits, state: UFix): UFix = state - def newStateOnCacheControl(cmd: Bits) = { - MuxLookup(cmd, tileInvalid, Array( - M_INV -> tileInvalid, - M_CLN -> tileValid - )) - } - def newStateOnWriteback() = newStateOnCacheControl(M_INV) - def newStateOnFlush() = newStateOnCacheControl(M_INV) - def newStateOnTransactionReply(incoming: TransactionReply, outstanding: TransactionInit): UFix = { - MuxLookup(incoming.x_type, tileInvalid, Array( - xactReplyReadExclusive -> tileValid, - xactReplyReadUncached -> tileInvalid, - xactReplyWriteUncached -> tileInvalid, - xactReplyReadWordUncached -> tileInvalid, - xactReplyWriteWordUncached -> tileInvalid, - xactReplyAtomicUncached -> tileInvalid - )) - } - def newStateOnProbeRequest(incoming: ProbeRequest, state: UFix): Bits = { - MuxLookup(incoming.p_type, state, Array( - probeReqInvalidate -> tileInvalid, - probeReqCopy -> state - )) - } - - def getUncachedReadTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadUncached, addr, id) - def getUncachedWriteTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitWriteUncached, addr, id) - def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id) - def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask) - def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op) - - def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = xactInitReadExclusive - def getTransactionInitTypeOnSecondaryMiss(cmd: Bits, state: UFix, outstanding: TransactionInit): UFix = xactInitReadExclusive - def getTransactionInitTypeOnCacheControl(cmd: Bits): Bits = xactInitWriteUncached - def getTransactionInitTypeOnWriteback(): Bits = getTransactionInitTypeOnCacheControl(M_INV) - - def newProbeReply (incoming: ProbeRequest, state: UFix): ProbeReply = { - val reply = new ProbeReply() - val with_data = MuxLookup(incoming.p_type, probeRepInvalidateData, Array( - probeReqInvalidate -> probeRepInvalidateData, - probeReqCopy -> probeRepCopyData - )) - val without_data = MuxLookup(incoming.p_type, probeRepInvalidateAck, Array( - probeReqInvalidate -> probeRepInvalidateAck, - probeReqCopy -> probeRepCopyAck - )) - reply.p_type := Mux(needsWriteback(state), with_data, without_data) - reply.global_xact_id := incoming.global_xact_id - reply - } - - def messageHasData (reply: ProbeReply): Bool = { - (reply.p_type === probeRepInvalidateData || - reply.p_type === probeRepCopyData) - } - def messageHasData (init: TransactionInit): Bool = hasDataTypeList.map(t => init.x_type === t).reduceLeft(_||_) - def messageHasData (reply: TransactionReply): Bool = { - (reply.x_type != xactReplyWriteUncached && reply.x_type != xactReplyWriteWordUncached) - } - def messageUpdatesDataArray (reply: TransactionReply): Bool = { - (reply.x_type === xactReplyReadExclusive) - } - def messageIsUncached(init: TransactionInit): Bool = uncachedTypeList.map(t => init.x_type === t).reduceLeft(_||_) - - def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2) - - def getTransactionReplyType(x_type: UFix, count: UFix): Bits = { - MuxLookup(x_type, xactReplyReadUncached, Array( - xactInitReadExclusive -> xactReplyReadExclusive, - xactInitReadUncached -> xactReplyReadUncached, - xactInitWriteUncached -> xactReplyWriteUncached, - xactInitReadWordUncached -> xactReplyReadWordUncached, - xactInitWriteWordUncached -> xactReplyWriteWordUncached, - xactInitAtomicUncached -> xactReplyAtomicUncached - )) - } - - def getProbeRequestType(x_type: UFix, global_state: UFix): UFix = { - MuxLookup(x_type, probeReqCopy, Array( - xactInitReadExclusive -> probeReqInvalidate, - xactInitReadUncached -> probeReqCopy, - xactInitWriteUncached -> probeReqInvalidate, - xactInitReadWordUncached -> probeReqCopy, - xactInitWriteWordUncached -> probeReqInvalidate, - xactInitAtomicUncached -> probeReqInvalidate - )) - } - - def needsMemRead(x_type: UFix, global_state: UFix): Bool = { - (x_type != xactInitWriteUncached) - } - def needsMemWrite(x_type: UFix, global_state: UFix): Bool = { - (x_type === xactInitWriteUncached) - } - def needsAckReply(x_type: UFix, global_state: UFix): Bool = { - (x_type === xactInitWriteUncached) - } -} - -class MEICoherence extends CoherencePolicyWithUncached { - - val tileInvalid :: tileExclusiveClean :: tileExclusiveDirty :: Nil = Enum(3){ UFix() } - val globalInvalid :: globalExclusiveClean :: Nil = Enum(2){ UFix() } - - val xactInitReadExclusiveClean :: xactInitReadExclusiveDirty :: xactInitReadUncached :: xactInitWriteUncached :: xactInitReadWordUncached :: xactInitWriteWordUncached :: xactInitAtomicUncached :: Nil = Enum(7){ UFix() } - val xactReplyReadExclusive :: xactReplyReadUncached :: xactReplyWriteUncached :: xactReplyReadExclusiveAck :: xactReplyReadWordUncached :: xactReplyWriteWordUncached :: xactReplyAtomicUncached :: Nil = Enum(7){ UFix() } - val probeReqInvalidate :: probeReqDowngrade :: probeReqCopy :: Nil = Enum(3){ UFix() } - val probeRepInvalidateData :: probeRepDowngradeData :: probeRepCopyData :: probeRepInvalidateAck :: probeRepDowngradeAck :: probeRepCopyAck :: Nil = Enum(6){ UFix() } - val uncachedTypeList = List(xactInitReadUncached, xactInitWriteUncached, xactReplyReadWordUncached, xactInitWriteWordUncached, xactInitAtomicUncached) - val hasDataTypeList = List(xactInitWriteUncached, xactInitWriteWordUncached, xactInitAtomicUncached) - - def isHit (cmd: Bits, state: UFix): Bool = state != tileInvalid - def isValid (state: UFix): Bool = state != tileInvalid - - def needsTransactionOnSecondaryMiss(cmd: Bits, outstanding: TransactionInit): Bool = { - val (read, write) = cpuCmdToRW(cmd) - (read && messageIsUncached(outstanding)) || - (write && (outstanding.x_type != xactInitReadExclusiveDirty)) - } - def needsTransactionOnCacheControl(cmd: Bits, state: UFix): Bool = { - MuxLookup(cmd, (state === tileExclusiveDirty), Array( - M_INV -> (state === tileExclusiveDirty), - M_CLN -> (state === tileExclusiveDirty) - )) - } - def needsWriteback (state: UFix): Bool = { - needsTransactionOnCacheControl(M_INV, state) - } - - def newStateOnHit(cmd: Bits, state: UFix): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, tileExclusiveDirty, state) - } - def newStateOnCacheControl(cmd: Bits) = { - MuxLookup(cmd, tileInvalid, Array( - M_INV -> tileInvalid, - M_CLN -> tileExclusiveClean - )) - } - def newStateOnWriteback() = newStateOnCacheControl(M_INV) - def newStateOnFlush() = newStateOnCacheControl(M_INV) - def newStateOnTransactionReply(incoming: TransactionReply, outstanding: TransactionInit): UFix = { - MuxLookup(incoming.x_type, tileInvalid, Array( - xactReplyReadExclusive -> Mux(outstanding.x_type === xactInitReadExclusiveDirty, tileExclusiveDirty, tileExclusiveClean), - xactReplyReadExclusiveAck -> tileExclusiveDirty, - xactReplyReadUncached -> tileInvalid, - xactReplyWriteUncached -> tileInvalid, - xactReplyReadWordUncached -> tileInvalid, - xactReplyWriteWordUncached -> tileInvalid, - xactReplyAtomicUncached -> tileInvalid - )) - } - def newStateOnProbeRequest(incoming: ProbeRequest, state: UFix): Bits = { - MuxLookup(incoming.p_type, state, Array( - probeReqInvalidate -> tileInvalid, - probeReqDowngrade -> tileExclusiveClean, - probeReqCopy -> state - )) - } - - def getUncachedReadTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadUncached, addr, id) - def getUncachedWriteTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitWriteUncached, addr, id) - def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id) - def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask) - def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op) - - def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, xactInitReadExclusiveDirty, xactInitReadExclusiveClean) - } - def getTransactionInitTypeOnSecondaryMiss(cmd: Bits, state: UFix, outstanding: TransactionInit): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, xactInitReadExclusiveDirty, outstanding.x_type) - } - def getTransactionInitTypeOnCacheControl(cmd: Bits): Bits = xactInitWriteUncached - def getTransactionInitTypeOnWriteback(): Bits = getTransactionInitTypeOnCacheControl(M_INV) - - def newProbeReply (incoming: ProbeRequest, state: UFix): ProbeReply = { - val reply = new ProbeReply() - val with_data = MuxLookup(incoming.p_type, probeRepInvalidateData, Array( - probeReqInvalidate -> probeRepInvalidateData, - probeReqDowngrade -> probeRepDowngradeData, - probeReqCopy -> probeRepCopyData - )) - val without_data = MuxLookup(incoming.p_type, probeRepInvalidateAck, Array( - probeReqInvalidate -> probeRepInvalidateAck, - probeReqDowngrade -> probeRepDowngradeAck, - probeReqCopy -> probeRepCopyAck - )) - reply.p_type := Mux(needsWriteback(state), with_data, without_data) - reply.global_xact_id := incoming.global_xact_id - reply - } - - def messageHasData (reply: ProbeReply): Bool = { - (reply.p_type === probeRepInvalidateData || - reply.p_type === probeRepDowngradeData || - reply.p_type === probeRepCopyData) - } - def messageHasData (init: TransactionInit): Bool = hasDataTypeList.map(t => init.x_type === t).reduceLeft(_||_) - def messageHasData (reply: TransactionReply): Bool = { - (reply.x_type != xactReplyWriteUncached && reply.x_type != xactReplyReadExclusiveAck && reply.x_type != xactReplyWriteWordUncached) - } - def messageUpdatesDataArray (reply: TransactionReply): Bool = { - (reply.x_type === xactReplyReadExclusive) - } - def messageIsUncached(init: TransactionInit): Bool = uncachedTypeList.map(t => init.x_type === t).reduceLeft(_||_) - - def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2) - - def getTransactionReplyType(x_type: UFix, count: UFix): Bits = { - MuxLookup(x_type, xactReplyReadUncached, Array( - xactInitReadExclusiveClean -> xactReplyReadExclusive, - xactInitReadExclusiveDirty -> xactReplyReadExclusive, - xactInitReadUncached -> xactReplyReadUncached, - xactInitWriteUncached -> xactReplyWriteUncached, - xactInitReadWordUncached -> xactReplyReadWordUncached, - xactInitWriteWordUncached -> xactReplyWriteWordUncached, - xactInitAtomicUncached -> xactReplyAtomicUncached - )) - } - - def getProbeRequestType(x_type: UFix, global_state: UFix): UFix = { - MuxLookup(x_type, probeReqCopy, Array( - xactInitReadExclusiveClean -> probeReqInvalidate, - xactInitReadExclusiveDirty -> probeReqInvalidate, - xactInitReadUncached -> probeReqCopy, - xactInitWriteUncached -> probeReqInvalidate, - xactInitReadWordUncached -> probeReqCopy, - xactInitWriteWordUncached -> probeReqInvalidate, - xactInitAtomicUncached -> probeReqInvalidate - )) - } - - def needsMemRead(x_type: UFix, global_state: UFix): Bool = { - (x_type != xactInitWriteUncached) - } - def needsMemWrite(x_type: UFix, global_state: UFix): Bool = { - (x_type === xactInitWriteUncached) - } - def needsAckReply(x_type: UFix, global_state: UFix): Bool = { - (x_type === xactInitWriteUncached) - } -} - -class MSICoherence extends CoherencePolicyWithUncached { - - val tileInvalid :: tileShared :: tileExclusiveDirty :: Nil = Enum(3){ UFix() } - val globalInvalid :: globalShared :: globalExclusive :: Nil = Enum(3){ UFix() } - - val xactInitReadShared :: xactInitReadExclusive :: xactInitReadUncached :: xactInitWriteUncached :: xactInitReadWordUncached :: xactInitWriteWordUncached :: xactInitAtomicUncached :: Nil = Enum(7){ UFix() } - val xactReplyReadShared :: xactReplyReadExclusive :: xactReplyReadUncached :: xactReplyWriteUncached :: xactReplyReadExclusiveAck :: xactReplyReadWordUncached :: xactReplyWriteWordUncached :: xactReplyAtomicUncached :: Nil = Enum(8){ UFix() } - val probeReqInvalidate :: probeReqDowngrade :: probeReqCopy :: Nil = Enum(3){ UFix() } - val probeRepInvalidateData :: probeRepDowngradeData :: probeRepCopyData :: probeRepInvalidateAck :: probeRepDowngradeAck :: probeRepCopyAck :: Nil = Enum(6){ UFix() } - val uncachedTypeList = List(xactInitReadUncached, xactInitWriteUncached, xactReplyReadWordUncached, xactInitWriteWordUncached, xactInitAtomicUncached) - val hasDataTypeList = List(xactInitWriteUncached, xactInitWriteWordUncached, xactInitAtomicUncached) - - def isHit (cmd: Bits, state: UFix): Bool = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, (state === tileExclusiveDirty), - (state === tileShared || state === tileExclusiveDirty)) - } - def isValid (state: UFix): Bool = { - state != tileInvalid - } - - def needsTransactionOnSecondaryMiss(cmd: Bits, outstanding: TransactionInit): Bool = { - val (read, write) = cpuCmdToRW(cmd) - (read && messageIsUncached(outstanding)) || - (write && (outstanding.x_type != xactInitReadExclusive)) - } - def needsTransactionOnCacheControl(cmd: Bits, state: UFix): Bool = { - MuxLookup(cmd, (state === tileExclusiveDirty), Array( - M_INV -> (state === tileExclusiveDirty), - M_CLN -> (state === tileExclusiveDirty) - )) - } - def needsWriteback (state: UFix): Bool = { - needsTransactionOnCacheControl(M_INV, state) - } - - def newStateOnHit(cmd: Bits, state: UFix): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, tileExclusiveDirty, state) - } - def newStateOnCacheControl(cmd: Bits) = { - MuxLookup(cmd, tileInvalid, Array( - M_INV -> tileInvalid, - M_CLN -> tileShared - )) - } - def newStateOnWriteback() = newStateOnCacheControl(M_INV) - def newStateOnFlush() = newStateOnCacheControl(M_INV) - def newStateOnTransactionReply(incoming: TransactionReply, outstanding: TransactionInit): UFix = { - MuxLookup(incoming.x_type, tileInvalid, Array( - xactReplyReadShared -> tileShared, - xactReplyReadExclusive -> tileExclusiveDirty, - xactReplyReadExclusiveAck -> tileExclusiveDirty, - xactReplyReadUncached -> tileInvalid, - xactReplyWriteUncached -> tileInvalid, - xactReplyReadWordUncached -> tileInvalid, - xactReplyWriteWordUncached -> tileInvalid, - xactReplyAtomicUncached -> tileInvalid - )) - } - def newStateOnProbeRequest(incoming: ProbeRequest, state: UFix): Bits = { - MuxLookup(incoming.p_type, state, Array( - probeReqInvalidate -> tileInvalid, - probeReqDowngrade -> tileShared, - probeReqCopy -> state - )) - } - - def getUncachedReadTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadUncached, addr, id) - def getUncachedWriteTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitWriteUncached, addr, id) - def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id) - def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask) - def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op) - - def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write || cmd === M_PFW, xactInitReadExclusive, xactInitReadShared) - } - def getTransactionInitTypeOnSecondaryMiss(cmd: Bits, state: UFix, outstanding: TransactionInit): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, xactInitReadExclusive, outstanding.x_type) - } - def getTransactionInitTypeOnCacheControl(cmd: Bits): Bits = xactInitWriteUncached - def getTransactionInitTypeOnWriteback(): Bits = getTransactionInitTypeOnCacheControl(M_INV) - - def newProbeReply (incoming: ProbeRequest, state: UFix): ProbeReply = { - val reply = new ProbeReply() - val with_data = MuxLookup(incoming.p_type, probeRepInvalidateData, Array( - probeReqInvalidate -> probeRepInvalidateData, - probeReqDowngrade -> probeRepDowngradeData, - probeReqCopy -> probeRepCopyData - )) - val without_data = MuxLookup(incoming.p_type, probeRepInvalidateAck, Array( - probeReqInvalidate -> probeRepInvalidateAck, - probeReqDowngrade -> probeRepDowngradeAck, - probeReqCopy -> probeRepCopyAck - )) - reply.p_type := Mux(needsWriteback(state), with_data, without_data) - reply.global_xact_id := incoming.global_xact_id - reply - } - - def messageHasData (reply: ProbeReply): Bool = { - (reply.p_type === probeRepInvalidateData || - reply.p_type === probeRepDowngradeData || - reply.p_type === probeRepCopyData) - } - def messageHasData (init: TransactionInit): Bool = hasDataTypeList.map(t => init.x_type === t).reduceLeft(_||_) - def messageHasData (reply: TransactionReply): Bool = { - (reply.x_type != xactReplyWriteUncached && reply.x_type != xactReplyReadExclusiveAck && reply.x_type != xactReplyWriteWordUncached) - } - def messageUpdatesDataArray (reply: TransactionReply): Bool = { - (reply.x_type === xactReplyReadShared || reply.x_type === xactReplyReadExclusive) - } - def messageIsUncached(init: TransactionInit): Bool = uncachedTypeList.map(t => init.x_type === t).reduceLeft(_||_) - - def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2) - - def getTransactionReplyType(x_type: UFix, count: UFix): Bits = { - MuxLookup(x_type, xactReplyReadUncached, Array( - xactInitReadShared -> Mux(count > UFix(0), xactReplyReadShared, xactReplyReadExclusive), - xactInitReadExclusive -> xactReplyReadExclusive, - xactInitReadUncached -> xactReplyReadUncached, - xactInitWriteUncached -> xactReplyWriteUncached, - xactInitReadWordUncached -> xactReplyReadWordUncached, - xactInitWriteWordUncached -> xactReplyWriteWordUncached, - xactInitAtomicUncached -> xactReplyAtomicUncached - )) - } - - def getProbeRequestType(x_type: UFix, global_state: UFix): UFix = { - MuxLookup(x_type, probeReqCopy, Array( - xactInitReadShared -> probeReqDowngrade, - xactInitReadExclusive -> probeReqInvalidate, - xactInitReadUncached -> probeReqCopy, - xactInitWriteUncached -> probeReqInvalidate - )) - } - - def needsMemRead(x_type: UFix, global_state: UFix): Bool = { - (x_type != xactInitWriteUncached) - } - def needsMemWrite(x_type: UFix, global_state: UFix): Bool = { - (x_type === xactInitWriteUncached) - } - def needsAckReply(x_type: UFix, global_state: UFix): Bool = { - (x_type === xactInitWriteUncached) - } -} - -class MESICoherence extends CoherencePolicyWithUncached { - - val tileInvalid :: tileShared :: tileExclusiveClean :: tileExclusiveDirty :: Nil = Enum(4){ UFix() } - val globalInvalid :: globalShared :: globalExclusiveClean :: Nil = Enum(3){ UFix() } - - val xactInitReadShared :: xactInitReadExclusive :: xactInitReadUncached :: xactInitWriteUncached :: xactInitReadWordUncached :: xactInitWriteWordUncached :: xactInitAtomicUncached :: Nil = Enum(7){ UFix() } - val xactReplyReadShared :: xactReplyReadExclusive :: xactReplyReadUncached :: xactReplyWriteUncached :: xactReplyReadExclusiveAck :: xactReplyReadWordUncached :: xactReplyWriteWordUncached :: xactReplyAtomicUncached :: Nil = Enum(8){ UFix() } - val probeReqInvalidate :: probeReqDowngrade :: probeReqCopy :: Nil = Enum(3){ UFix() } - val probeRepInvalidateData :: probeRepDowngradeData :: probeRepCopyData :: probeRepInvalidateAck :: probeRepDowngradeAck :: probeRepCopyAck :: Nil = Enum(6){ UFix() } - val uncachedTypeList = List(xactInitReadUncached, xactInitWriteUncached, xactReplyReadWordUncached, xactInitWriteWordUncached, xactInitAtomicUncached) - val hasDataTypeList = List(xactInitWriteUncached, xactInitWriteWordUncached, xactInitAtomicUncached) - - def isHit (cmd: Bits, state: UFix): Bool = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, (state === tileExclusiveClean || state === tileExclusiveDirty), - (state === tileShared || state === tileExclusiveClean || state === tileExclusiveDirty)) - } - def isValid (state: UFix): Bool = { - state != tileInvalid - } - - def needsTransactionOnSecondaryMiss(cmd: Bits, outstanding: TransactionInit): Bool = { - val (read, write) = cpuCmdToRW(cmd) - (read && messageIsUncached(outstanding)) || - (write && (outstanding.x_type != xactInitReadExclusive)) - } - def needsTransactionOnCacheControl(cmd: Bits, state: UFix): Bool = { - MuxLookup(cmd, (state === tileExclusiveDirty), Array( - M_INV -> (state === tileExclusiveDirty), - M_CLN -> (state === tileExclusiveDirty) - )) - } - def needsWriteback (state: UFix): Bool = { - needsTransactionOnCacheControl(M_INV, state) - } - - def newStateOnHit(cmd: Bits, state: UFix): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, tileExclusiveDirty, state) - } - def newStateOnCacheControl(cmd: Bits) = { - MuxLookup(cmd, tileInvalid, Array( - M_INV -> tileInvalid, - M_CLN -> tileShared - )) - } - def newStateOnWriteback() = newStateOnCacheControl(M_INV) - def newStateOnFlush() = newStateOnCacheControl(M_INV) - def newStateOnTransactionReply(incoming: TransactionReply, outstanding: TransactionInit): UFix = { - MuxLookup(incoming.x_type, tileInvalid, Array( - xactReplyReadShared -> tileShared, - xactReplyReadExclusive -> Mux(outstanding.x_type === xactInitReadExclusive, tileExclusiveDirty, tileExclusiveClean), - xactReplyReadExclusiveAck -> tileExclusiveDirty, - xactReplyReadUncached -> tileInvalid, - xactReplyWriteUncached -> tileInvalid, - xactReplyReadWordUncached -> tileInvalid, - xactReplyWriteWordUncached -> tileInvalid, - xactReplyAtomicUncached -> tileInvalid - )) - } - def newStateOnProbeRequest(incoming: ProbeRequest, state: UFix): Bits = { - MuxLookup(incoming.p_type, state, Array( - probeReqInvalidate -> tileInvalid, - probeReqDowngrade -> tileShared, - probeReqCopy -> state - )) - } - - def getUncachedReadTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadUncached, addr, id) - def getUncachedWriteTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitWriteUncached, addr, id) - def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id) - def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask) - def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op) - - def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write || cmd === M_PFW, xactInitReadExclusive, xactInitReadShared) - } - def getTransactionInitTypeOnSecondaryMiss(cmd: Bits, state: UFix, outstanding: TransactionInit): UFix = { - val (read, write) = cpuCmdToRW(cmd) - Mux(write, xactInitReadExclusive, outstanding.x_type) - } - def getTransactionInitTypeOnCacheControl(cmd: Bits): Bits = xactInitWriteUncached - def getTransactionInitTypeOnWriteback(): Bits = getTransactionInitTypeOnCacheControl(M_INV) - - def newProbeReply (incoming: ProbeRequest, state: UFix): ProbeReply = { - val reply = new ProbeReply() - val with_data = MuxLookup(incoming.p_type, probeRepInvalidateData, Array( - probeReqInvalidate -> probeRepInvalidateData, - probeReqDowngrade -> probeRepDowngradeData, - probeReqCopy -> probeRepCopyData - )) - val without_data = MuxLookup(incoming.p_type, probeRepInvalidateAck, Array( - probeReqInvalidate -> probeRepInvalidateAck, - probeReqDowngrade -> probeRepDowngradeAck, - probeReqCopy -> probeRepCopyAck - )) - reply.p_type := Mux(needsWriteback(state), with_data, without_data) - reply.global_xact_id := incoming.global_xact_id - reply - } - - def messageHasData (reply: ProbeReply): Bool = { - (reply.p_type === probeRepInvalidateData || - reply.p_type === probeRepDowngradeData || - reply.p_type === probeRepCopyData) - } - def messageHasData (init: TransactionInit): Bool = hasDataTypeList.map(t => init.x_type === t).reduceLeft(_||_) - def messageHasData (reply: TransactionReply): Bool = { - (reply.x_type != xactReplyWriteUncached && reply.x_type != xactReplyReadExclusiveAck && reply.x_type != xactReplyWriteWordUncached) - } - def messageUpdatesDataArray (reply: TransactionReply): Bool = { - (reply.x_type === xactReplyReadShared || reply.x_type === xactReplyReadExclusive) - } - def messageIsUncached(init: TransactionInit): Bool = uncachedTypeList.map(t => init.x_type === t).reduceLeft(_||_) - - def isCoherenceConflict(addr1: Bits, addr2: Bits): Bool = (addr1 === addr2) - - def getTransactionReplyType(x_type: UFix, count: UFix): Bits = { - MuxLookup(x_type, xactReplyReadUncached, Array( - xactInitReadShared -> Mux(count > UFix(0), xactReplyReadShared, xactReplyReadExclusive), - xactInitReadExclusive -> xactReplyReadExclusive, - xactInitReadUncached -> xactReplyReadUncached, - xactInitWriteUncached -> xactReplyWriteUncached, - xactInitReadWordUncached -> xactReplyReadWordUncached, - xactInitWriteWordUncached -> xactReplyWriteWordUncached, - xactInitAtomicUncached -> xactReplyAtomicUncached - )) - } - - def getProbeRequestType(x_type: UFix, global_state: UFix): UFix = { - MuxLookup(x_type, probeReqCopy, Array( - xactInitReadShared -> probeReqDowngrade, - xactInitReadExclusive -> probeReqInvalidate, - xactInitReadUncached -> probeReqCopy, - xactInitWriteUncached -> probeReqInvalidate, - xactInitReadWordUncached -> probeReqCopy, - xactInitWriteWordUncached -> probeReqInvalidate, - xactInitAtomicUncached -> probeReqInvalidate - )) - } - - def needsMemRead(x_type: UFix, global_state: UFix): Bool = { - (x_type != xactInitWriteUncached) - } - def needsMemWrite(x_type: UFix, global_state: UFix): Bool = { - (x_type === xactInitWriteUncached) - } - def needsAckReply(x_type: UFix, global_state: UFix): Bool = { - (x_type === xactInitWriteUncached) - } -} diff --git a/rocket/src/main/scala/htif.scala b/rocket/src/main/scala/htif.scala index 38955296..335ef3cb 100644 --- a/rocket/src/main/scala/htif.scala +++ b/rocket/src/main/scala/htif.scala @@ -3,6 +3,7 @@ package rocket import Chisel._ import Node._; import Constants._; +import uncore._ class ioDebug extends Bundle { diff --git a/rocket/src/main/scala/icache.scala b/rocket/src/main/scala/icache.scala index 17d47ca1..9b79e2ce 100644 --- a/rocket/src/main/scala/icache.scala +++ b/rocket/src/main/scala/icache.scala @@ -4,6 +4,7 @@ import Chisel._; import Node._; import Constants._; import scala.math._; +import uncore._ // interface between I$ and pipeline/ITLB (32 bits wide) class ioImem extends Bundle diff --git a/rocket/src/main/scala/llc.scala b/rocket/src/main/scala/llc.scala deleted file mode 100644 index a2a5d361..00000000 --- a/rocket/src/main/scala/llc.scala +++ /dev/null @@ -1,437 +0,0 @@ -package rocket - -import Chisel._ -import Node._ -import Constants._ - -class BigMem[T <: Data](n: Int, preLatency: Int, postLatency: Int, leaf: Mem[Bits])(gen: => T) extends Component -{ - class Inputs extends Bundle { - val addr = UFix(INPUT, log2Up(n)) - val rw = Bool(INPUT) - val wdata = gen.asInput - val wmask = gen.asInput - override def clone = new Inputs().asInstanceOf[this.type] - } - val io = new Bundle { - val in = new PipeIO()(new Inputs).flip - val rdata = gen.asOutput - } - val data = gen - val colMux = if (2*data.width <= leaf.data.width && n > leaf.n) 1 << math.floor(math.log(leaf.data.width/data.width)/math.log(2)).toInt else 1 - val nWide = if (data.width > leaf.data.width) 1+(data.width-1)/leaf.data.width else 1 - val nDeep = if (n > colMux*leaf.n) 1+(n-1)/(colMux*leaf.n) else 1 - if (nDeep > 1 || colMux > 1) - require(isPow2(n) && isPow2(leaf.n)) - - val rdataDeep = Vec(nDeep) { Bits() } - val rdataSel = Vec(nDeep) { Bool() } - for (i <- 0 until nDeep) { - val in = Pipe(io.in.valid && (if (nDeep == 1) Bool(true) else UFix(i) === io.in.bits.addr(log2Up(n)-1, log2Up(n/nDeep))), io.in.bits, preLatency) - val idx = in.bits.addr(log2Up(n/nDeep/colMux)-1, 0) - val wdata = in.bits.wdata.toBits - val wmask = in.bits.wmask.toBits - val ren = in.valid && !in.bits.rw - val reg_ren = Reg(ren) - val rdata = Vec(nWide) { Bits() } - - val r = Pipe(ren, in.bits.addr, postLatency) - - for (j <- 0 until nWide) { - val mem = leaf.clone - var dout: Bits = null - val dout1 = if (postLatency > 0) Reg() { Bits() } else null - - var wmask0 = Fill(colMux, wmask(math.min(wmask.getWidth, leaf.data.width*(j+1))-1, leaf.data.width*j)) - if (colMux > 1) - wmask0 = wmask0 & FillInterleaved(gen.width, UFixToOH(in.bits.addr(log2Up(n/nDeep)-1, log2Up(n/nDeep/colMux)), log2Up(colMux))) - val wdata0 = Fill(colMux, wdata(math.min(wdata.getWidth, leaf.data.width*(j+1))-1, leaf.data.width*j)) - when (in.valid) { - when (in.bits.rw) { mem.write(idx, wdata0, wmask0) } - .otherwise { if (postLatency > 0) dout1 := mem(idx) } - } - - if (postLatency == 0) { - dout = mem(idx) - } else if (postLatency == 1) { - dout = dout1 - } else - dout = Pipe(reg_ren, dout1, postLatency-1).bits - - rdata(j) := dout - } - val rdataWide = rdata.reduceLeft((x, y) => Cat(y, x)) - - var colMuxOut = rdataWide - if (colMux > 1) { - val colMuxIn = Vec((0 until colMux).map(k => rdataWide(gen.width*(k+1)-1, gen.width*k))) { Bits() } - colMuxOut = colMuxIn(r.bits(log2Up(n/nDeep)-1, log2Up(n/nDeep/colMux))) - } - - rdataDeep(i) := colMuxOut - rdataSel(i) := r.valid - } - - io.rdata := Mux1H(rdataSel, rdataDeep) -} - -class LLCDataReq(ways: Int) extends MemReqCmd -{ - val way = UFix(width = log2Up(ways)) - val isWriteback = Bool() - - override def clone = new LLCDataReq(ways).asInstanceOf[this.type] -} - -class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int) extends Component -{ - val io = new Bundle { - val cpu = (new FIFOIO) { new MemReqCmd }.flip - val repl_way = UFix(INPUT, log2Up(ways)) - val repl_dirty = Bool(INPUT) - val repl_tag = UFix(INPUT, PADDR_BITS - OFFSET_BITS - log2Up(sets)) - val data = (new FIFOIO) { new LLCDataReq(ways) } - val tag = (new FIFOIO) { new Bundle { - val addr = UFix(width = PADDR_BITS - OFFSET_BITS) - val way = UFix(width = log2Up(ways)) - } } - val mem = new ioMemPipe - val mem_resp_set = UFix(OUTPUT, log2Up(sets)) - val mem_resp_way = UFix(OUTPUT, log2Up(ways)) - } - - class MSHR extends Bundle { - val addr = UFix(width = PADDR_BITS - OFFSET_BITS) - val way = UFix(width = log2Up(ways)) - val tag = io.cpu.bits.tag.clone - val refilled = Bool() - val refillCount = UFix(width = log2Up(REFILL_CYCLES)) - val requested = Bool() - val old_dirty = Bool() - val old_tag = UFix(width = PADDR_BITS - OFFSET_BITS - log2Up(sets)) - - override def clone = new MSHR().asInstanceOf[this.type] - } - - val valid = Vec(outstanding) { Reg(resetVal = Bool(false)) } - val validBits = valid.toBits - val freeId = PriorityEncoder(~validBits) - val mshr = Vec(outstanding) { Reg() { new MSHR } } - when (io.cpu.valid && io.cpu.ready) { - valid(freeId) := Bool(true) - mshr(freeId).addr := io.cpu.bits.addr - mshr(freeId).tag := io.cpu.bits.tag - mshr(freeId).way := io.repl_way - mshr(freeId).old_dirty := io.repl_dirty - mshr(freeId).old_tag := io.repl_tag - mshr(freeId).requested := Bool(false) - mshr(freeId).refillCount := UFix(0) - mshr(freeId).refilled := Bool(false) - } - - val requests = Cat(Bits(0), (outstanding-1 to 0 by -1).map(i => valid(i) && !mshr(i).old_dirty && !mshr(i).requested):_*) - val request = requests.orR - val requestId = PriorityEncoder(requests) - when (io.mem.req_cmd.valid && io.mem.req_cmd.ready) { mshr(requestId).requested := Bool(true) } - - val refillId = io.mem.resp.bits.tag(log2Up(outstanding)-1, 0) - val refillCount = mshr(refillId).refillCount - when (io.mem.resp.valid) { - mshr(refillId).refillCount := refillCount + UFix(1) - when (refillCount === UFix(REFILL_CYCLES-1)) { mshr(refillId).refilled := Bool(true) } - } - - val replays = Cat(Bits(0), (outstanding-1 to 0 by -1).map(i => valid(i) && mshr(i).refilled):_*) - val replay = replays.orR - val replayId = PriorityEncoder(replays) - when (replay && io.data.ready && io.tag.ready) { valid(replayId) := Bool(false) } - - val writebacks = Cat(Bits(0), (outstanding-1 to 0 by -1).map(i => valid(i) && mshr(i).old_dirty):_*) - val writeback = writebacks.orR - val writebackId = PriorityEncoder(writebacks) - when (writeback && io.data.ready && !replay) { mshr(writebackId).old_dirty := Bool(false) } - - val conflicts = Cat(Bits(0), (0 until outstanding).map(i => valid(i) && io.cpu.bits.addr(log2Up(sets)-1, 0) === mshr(i).addr(log2Up(sets)-1, 0)):_*) - io.cpu.ready := !conflicts.orR && !validBits.andR - - io.data.valid := writeback - io.data.bits.rw := Bool(false) - io.data.bits.tag := mshr(replayId).tag - io.data.bits.isWriteback := Bool(true) - io.data.bits.addr := Cat(mshr(writebackId).old_tag, mshr(writebackId).addr(log2Up(sets)-1, 0)).toUFix - io.data.bits.way := mshr(writebackId).way - when (replay) { - io.data.valid := io.tag.ready - io.data.bits.isWriteback := Bool(false) - io.data.bits.addr := mshr(replayId).addr - io.data.bits.way := mshr(replayId).way - } - io.tag.valid := replay && io.data.ready - io.tag.bits.addr := io.data.bits.addr - io.tag.bits.way := io.data.bits.way - - io.mem.req_cmd.valid := request - io.mem.req_cmd.bits.rw := Bool(false) - io.mem.req_cmd.bits.addr := mshr(requestId).addr - io.mem.req_cmd.bits.tag := requestId - io.mem_resp_set := mshr(refillId).addr - io.mem_resp_way := mshr(refillId).way -} - -class LLCWriteback(requestors: Int) extends Component -{ - val io = new Bundle { - val req = Vec(requestors) { (new FIFOIO) { UFix(width = PADDR_BITS - OFFSET_BITS) }.flip } - val data = Vec(requestors) { (new FIFOIO) { new MemData }.flip } - val mem = new ioMemPipe - } - - val valid = Reg(resetVal = Bool(false)) - val who = Reg() { UFix() } - val addr = Reg() { UFix() } - val cmd_sent = Reg() { Bool() } - val data_sent = Reg() { Bool() } - val count = Reg(resetVal = UFix(0, log2Up(REFILL_CYCLES))) - - var anyReq = Bool(false) - for (i <- 0 until requestors) { - io.req(i).ready := !valid && !anyReq - io.data(i).ready := valid && who === UFix(i) && io.mem.req_data.ready - anyReq = anyReq || io.req(i).valid - } - - val nextWho = PriorityEncoder(io.req.map(_.valid)) - when (!valid && io.req.map(_.valid).reduceLeft(_||_)) { - valid := Bool(true) - cmd_sent := Bool(false) - data_sent := Bool(false) - who := nextWho - addr := io.req(nextWho).bits - } - - when (io.mem.req_data.valid && io.mem.req_data.ready) { - count := count + UFix(1) - when (count === UFix(REFILL_CYCLES-1)) { - data_sent := Bool(true) - when (cmd_sent) { valid := Bool(false) } - } - } - when (io.mem.req_cmd.valid && io.mem.req_cmd.ready) { cmd_sent := Bool(true) } - when (valid && cmd_sent && data_sent) { valid := Bool(false) } - - io.mem.req_cmd.valid := valid && !cmd_sent - io.mem.req_cmd.bits.addr := addr - io.mem.req_cmd.bits.rw := Bool(true) - - io.mem.req_data.valid := valid && !data_sent && io.data(who).valid - io.mem.req_data.bits := io.data(who).bits -} - -class LLCData(latency: Int, sets: Int, ways: Int, leaf: Mem[Bits]) extends Component -{ - val io = new Bundle { - val req = (new FIFOIO) { new LLCDataReq(ways) }.flip - val req_data = (new FIFOIO) { new MemData }.flip - val writeback = (new FIFOIO) { UFix(width = PADDR_BITS - OFFSET_BITS) } - val writeback_data = (new FIFOIO) { new MemData } - val resp = (new FIFOIO) { new MemResp } - val mem_resp = (new PipeIO) { new MemResp }.flip - val mem_resp_set = UFix(INPUT, log2Up(sets)) - val mem_resp_way = UFix(INPUT, log2Up(ways)) - } - - val data = new BigMem(sets*ways*REFILL_CYCLES, 1, latency-1, leaf)(Bits(width = MEM_DATA_BITS)) - class QEntry extends MemResp { - val isWriteback = Bool() - override def clone = new QEntry().asInstanceOf[this.type] - } - val q = (new Queue(latency+2)) { new QEntry } - val qReady = q.io.count <= UFix(q.entries-latency-1) - val valid = Reg(resetVal = Bool(false)) - val req = Reg() { io.req.bits.clone } - val count = Reg(resetVal = UFix(0, log2Up(REFILL_CYCLES))) - val refillCount = Reg(resetVal = UFix(0, log2Up(REFILL_CYCLES))) - - when (data.io.in.valid && !io.mem_resp.valid) { - count := count + UFix(1) - when (valid && count === UFix(REFILL_CYCLES-1)) { valid := Bool(false) } - } - when (io.req.valid && io.req.ready) { valid := Bool(true); req := io.req.bits } - when (io.mem_resp.valid) { refillCount := refillCount + UFix(1) } - - data.io.in.valid := io.req.valid && io.req.ready && Mux(io.req.bits.rw, io.req_data.valid, qReady) - data.io.in.bits.addr := Cat(io.req.bits.way, io.req.bits.addr(log2Up(sets)-1, 0), count).toUFix - data.io.in.bits.rw := io.req.bits.rw - data.io.in.bits.wdata := io.req_data.bits.data - data.io.in.bits.wmask := Fix(-1, io.req_data.bits.data.width) - when (valid) { - data.io.in.valid := Mux(req.rw, io.req_data.valid, qReady) - data.io.in.bits.addr := Cat(req.way, req.addr(log2Up(sets)-1, 0), count).toUFix - data.io.in.bits.rw := req.rw - } - when (io.mem_resp.valid) { - data.io.in.valid := Bool(true) - data.io.in.bits.addr := Cat(io.mem_resp_way, io.mem_resp_set, refillCount).toUFix - data.io.in.bits.rw := Bool(true) - data.io.in.bits.wdata := io.mem_resp.bits.data - } - - val tagPipe = Pipe(data.io.in.valid && !data.io.in.bits.rw, Mux(valid, req.tag, io.req.bits.tag), latency) - q.io.enq.valid := tagPipe.valid - q.io.enq.bits.tag := tagPipe.bits - q.io.enq.bits.isWriteback := Pipe(Mux(valid, req.isWriteback, io.req.bits.isWriteback), Bool(false), latency).valid - q.io.enq.bits.data := data.io.rdata - - io.req.ready := !valid && Mux(io.req.bits.isWriteback, io.writeback.ready, Bool(true)) - io.req_data.ready := !io.mem_resp.valid && Mux(valid, req.rw, io.req.valid && io.req.bits.rw) - - io.writeback.valid := io.req.valid && io.req.ready && io.req.bits.isWriteback - io.writeback.bits := io.req.bits.addr - - q.io.deq.ready := Mux(q.io.deq.bits.isWriteback, io.writeback_data.ready, io.resp.ready) - io.resp.valid := q.io.deq.valid && !q.io.deq.bits.isWriteback - io.resp.bits := q.io.deq.bits - io.writeback_data.valid := q.io.deq.valid && q.io.deq.bits.isWriteback - io.writeback_data.bits := q.io.deq.bits -} - -class MemReqArb(n: Int) extends Component // UNTESTED -{ - val io = new Bundle { - val cpu = Vec(n) { new ioMem().flip } - val mem = new ioMem - } - - val lock = Reg(resetVal = Bool(false)) - val locker = Reg() { UFix() } - - val arb = new RRArbiter(n)(new MemReqCmd) - val respWho = io.mem.resp.bits.tag(log2Up(n)-1,0) - val respTag = io.mem.resp.bits.tag >> UFix(log2Up(n)) - for (i <- 0 until n) { - val me = UFix(i, log2Up(n)) - arb.io.in(i).valid := io.cpu(i).req_cmd.valid - arb.io.in(i).bits := io.cpu(i).req_cmd.bits - arb.io.in(i).bits.tag := Cat(io.cpu(i).req_cmd.bits.tag, me) - io.cpu(i).req_cmd.ready := arb.io.in(i).ready - io.cpu(i).req_data.ready := Bool(false) - - val getLock = io.cpu(i).req_cmd.fire() && io.cpu(i).req_cmd.bits.rw && !lock - val haveLock = lock && locker === me - when (getLock) { - lock := Bool(true) - locker := UFix(i) - } - when (getLock || haveLock) { - io.cpu(i).req_data.ready := io.mem.req_data.ready - io.mem.req_data.valid := Bool(true) - io.mem.req_data.bits := io.cpu(i).req_data.bits - } - - io.cpu(i).resp.valid := io.mem.resp.valid && respWho === me - io.cpu(i).resp.bits := io.mem.resp.bits - io.cpu(i).resp.bits.tag := respTag - } - io.mem.resp.ready := io.cpu(respWho).resp.ready - - val unlock = Counter(io.mem.req_data.fire(), REFILL_CYCLES)._2 - when (unlock) { lock := Bool(false) } -} - -class DRAMSideLLC(sets: Int, ways: Int, outstanding: Int, tagLeaf: Mem[Bits], dataLeaf: Mem[Bits]) extends Component -{ - val io = new Bundle { - val cpu = new ioMem().flip - val mem = new ioMemPipe - } - - val tagWidth = PADDR_BITS - OFFSET_BITS - log2Up(sets) - val metaWidth = tagWidth + 2 // valid + dirty - - val memCmdArb = (new Arbiter(2)) { new MemReqCmd } - val dataArb = (new Arbiter(2)) { new LLCDataReq(ways) } - val mshr = new LLCMSHRFile(sets, ways, outstanding) - val tags = new BigMem(sets, 0, 1, tagLeaf)(Bits(width = metaWidth*ways)) - val data = new LLCData(4, sets, ways, dataLeaf) - val writeback = new LLCWriteback(2) - - val initCount = Reg(resetVal = UFix(0, log2Up(sets+1))) - val initialize = !initCount(log2Up(sets)) - when (initialize) { initCount := initCount + UFix(1) } - - val stall_s1 = Bool() - val replay_s1 = Reg(resetVal = Bool(false)) - val s1_valid = Reg(io.cpu.req_cmd.valid && !stall_s1 || replay_s1, resetVal = Bool(false)) - replay_s1 := s1_valid && stall_s1 - val s1 = Reg() { new MemReqCmd } - when (io.cpu.req_cmd.valid && io.cpu.req_cmd.ready) { s1 := io.cpu.req_cmd.bits } - - val stall_s2 = Bool() - val s2_valid = Reg(resetVal = Bool(false)) - s2_valid := s1_valid && !replay_s1 && !stall_s1 || stall_s2 - val s2 = Reg() { new MemReqCmd } - val s2_tags = Vec(ways) { Reg() { Bits(width = metaWidth) } } - when (s1_valid && !stall_s1 && !replay_s1) { - s2 := s1 - for (i <- 0 until ways) - s2_tags(i) := tags.io.rdata(metaWidth*(i+1)-1, metaWidth*i) - } - val s2_hits = s2_tags.map(t => t(tagWidth) && s2.addr(s2.addr.width-1, s2.addr.width-tagWidth) === t(tagWidth-1, 0)) - val s2_hit_way = OHToUFix(s2_hits) - val s2_hit = s2_hits.reduceLeft(_||_) - val s2_hit_dirty = s2_tags(s2_hit_way)(tagWidth+1) - val repl_way = LFSR16(s2_valid)(log2Up(ways)-1, 0) - val repl_tag = s2_tags(repl_way).toUFix - val setDirty = s2_valid && s2.rw && s2_hit && !s2_hit_dirty - stall_s1 := initialize || stall_s2 - - val tag_we = setDirty || mshr.io.tag.valid - val tag_waddr = Mux(setDirty, s2.addr, mshr.io.tag.bits.addr)(log2Up(sets)-1,0) - val tag_wdata = Cat(setDirty, Bool(true), Mux(setDirty, s2.addr, mshr.io.tag.bits.addr)(mshr.io.tag.bits.addr.width-1, mshr.io.tag.bits.addr.width-tagWidth)) - val tag_wway = Mux(setDirty, s2_hit_way, mshr.io.tag.bits.way) - tags.io.in.valid := (io.cpu.req_cmd.valid || replay_s1) && !stall_s1 || initialize || tag_we - tags.io.in.bits.addr := Mux(initialize, initCount, Mux(tag_we, tag_waddr, Mux(replay_s1, s1.addr, io.cpu.req_cmd.bits.addr)(log2Up(sets)-1,0))) - tags.io.in.bits.rw := initialize || tag_we - tags.io.in.bits.wdata := Mux(initialize, UFix(0), Fill(ways, tag_wdata)) - tags.io.in.bits.wmask := FillInterleaved(metaWidth, Mux(initialize, Fix(-1, ways), UFixToOH(tag_wway))) - when (tag_we && Mux(stall_s2, s2.addr, s1.addr)(log2Up(sets)-1,0) === tag_waddr) { s2_tags(tag_wway) := tag_wdata } - - mshr.io.cpu.valid := s2_valid && !s2_hit && !s2.rw && dataArb.io.in(1).ready && writeback.io.req(0).ready // stall_s2 - mshr.io.cpu.bits := s2 - mshr.io.repl_way := repl_way - mshr.io.repl_dirty := repl_tag(tagWidth+1, tagWidth).andR - mshr.io.repl_tag := repl_tag - mshr.io.mem.resp := io.mem.resp - mshr.io.tag.ready := !setDirty - - data.io.req <> dataArb.io.out - data.io.mem_resp := io.mem.resp - data.io.mem_resp_set := mshr.io.mem_resp_set - data.io.mem_resp_way := mshr.io.mem_resp_way - data.io.req_data.bits := io.cpu.req_data.bits - data.io.req_data.valid := io.cpu.req_data.valid - - writeback.io.req(0) <> data.io.writeback - writeback.io.data(0) <> data.io.writeback_data - writeback.io.req(1).valid := s2_valid && !s2_hit && s2.rw && dataArb.io.in(1).ready && mshr.io.cpu.ready // stall_s2 - writeback.io.req(1).bits := s2.addr - writeback.io.data(1).valid := io.cpu.req_data.valid - writeback.io.data(1).bits := io.cpu.req_data.bits - - memCmdArb.io.in(0) <> mshr.io.mem.req_cmd - memCmdArb.io.in(1) <> writeback.io.mem.req_cmd - - dataArb.io.in(0) <> mshr.io.data - dataArb.io.in(1).valid := s2_valid && s2_hit && writeback.io.req(0).ready && mshr.io.cpu.ready // stall_s2 - dataArb.io.in(1).bits := s2 - dataArb.io.in(1).bits.way := s2_hit_way - dataArb.io.in(1).bits.isWriteback := Bool(false) - - stall_s2 := s2_valid && !(dataArb.io.in(1).ready && writeback.io.req(0).ready && mshr.io.cpu.ready) - - io.cpu.resp <> data.io.resp - io.cpu.req_cmd.ready := !stall_s1 && !replay_s1 - io.cpu.req_data.ready := writeback.io.data(1).ready || data.io.req_data.ready - io.mem.req_cmd <> memCmdArb.io.out - io.mem.req_data <> writeback.io.mem.req_data -} diff --git a/rocket/src/main/scala/memserdes.scala b/rocket/src/main/scala/memserdes.scala index cdd109c2..712dec16 100644 --- a/rocket/src/main/scala/memserdes.scala +++ b/rocket/src/main/scala/memserdes.scala @@ -4,6 +4,7 @@ import Chisel._ import Node._ import Constants._ import scala.math._ +import uncore._ class ioMemSerialized extends Bundle { diff --git a/rocket/src/main/scala/nbdcache.scala b/rocket/src/main/scala/nbdcache.scala index 40b9e6ab..951d6adc 100644 --- a/rocket/src/main/scala/nbdcache.scala +++ b/rocket/src/main/scala/nbdcache.scala @@ -2,6 +2,7 @@ package rocket import Chisel._ import Constants._ +import uncore._ class ioReplacementWayGen extends Bundle { val pick_new_way = Bool(dir = INPUT) diff --git a/rocket/src/main/scala/tile.scala b/rocket/src/main/scala/tile.scala index a5178fb4..5e621808 100644 --- a/rocket/src/main/scala/tile.scala +++ b/rocket/src/main/scala/tile.scala @@ -3,6 +3,7 @@ package rocket import Chisel._ import Node._ import Constants._ +import uncore._ class Tile(co: CoherencePolicyWithUncached, resetSignal: Bool = null) extends Component(resetSignal) { diff --git a/rocket/src/main/scala/top.scala b/rocket/src/main/scala/top.scala index c8437567..4390f8d7 100644 --- a/rocket/src/main/scala/top.scala +++ b/rocket/src/main/scala/top.scala @@ -2,6 +2,7 @@ package rocket import Chisel._ import Node._; +import uncore._ import Constants._; import collection.mutable.ArrayBuffer diff --git a/rocket/src/main/scala/uncore.scala b/rocket/src/main/scala/uncore.scala deleted file mode 100644 index 84b74366..00000000 --- a/rocket/src/main/scala/uncore.scala +++ /dev/null @@ -1,519 +0,0 @@ -package rocket - -import Chisel._ -import Constants._ - -class PhysicalAddress extends Bundle { - val addr = UFix(width = PADDR_BITS - OFFSET_BITS) -} - -class MemData extends Bundle { - val data = Bits(width = MEM_DATA_BITS) -} - -class MemReqCmd() extends PhysicalAddress -{ - val rw = Bool() - val tag = Bits(width = MEM_TAG_BITS) -} - -class MemResp () extends MemData -{ - val tag = Bits(width = MEM_TAG_BITS) -} - -class ioMem() extends Bundle -{ - val req_cmd = (new FIFOIO) { new MemReqCmd() } - val req_data = (new FIFOIO) { new MemData() } - val resp = (new FIFOIO) { new MemResp() }.flip -} - -class ioMemPipe() extends Bundle -{ - val req_cmd = (new FIFOIO) { new MemReqCmd() } - val req_data = (new FIFOIO) { new MemData() } - val resp = (new PipeIO) { new MemResp() }.flip -} - -class TrackerProbeData extends Bundle { - val tile_id = Bits(width = TILE_ID_BITS) -} - -class TrackerAllocReq extends Bundle { - val xact_init = new TransactionInit() - val tile_id = Bits(width = TILE_ID_BITS) -} - -class TrackerDependency extends Bundle { - val global_xact_id = Bits(width = GLOBAL_XACT_ID_BITS) -} - -class ioTileLink extends Bundle { - val xact_init = (new FIFOIO) { new TransactionInit } - val xact_init_data = (new FIFOIO) { new TransactionInitData } - val xact_abort = (new FIFOIO) { new TransactionAbort }.flip - val probe_req = (new FIFOIO) { new ProbeRequest }.flip - val probe_rep = (new FIFOIO) { new ProbeReply } - val probe_rep_data = (new FIFOIO) { new ProbeReplyData } - val xact_rep = (new FIFOIO) { new TransactionReply }.flip - val xact_finish = (new FIFOIO) { new TransactionFinish } - val incoherent = Bool(OUTPUT) -} - -class XactTracker(ntiles: Int, id: Int, co: CoherencePolicy) extends Component { - val io = new Bundle { - val alloc_req = (new FIFOIO) { new TrackerAllocReq }.flip - val p_data = (new PipeIO) { new TrackerProbeData }.flip - val can_alloc = Bool(INPUT) - val xact_finish = Bool(INPUT) - val p_rep_cnt_dec = Bits(INPUT, ntiles) - val p_req_cnt_inc = Bits(INPUT, ntiles) - val tile_incoherent = Bits(INPUT, ntiles) - val p_rep_data = (new PipeIO) { new ProbeReplyData }.flip - val x_init_data = (new PipeIO) { new TransactionInitData }.flip - val sent_x_rep_ack = Bool(INPUT) - val p_rep_data_dep = (new PipeIO) { new TrackerDependency }.flip - val x_init_data_dep = (new PipeIO) { new TrackerDependency }.flip - - val mem_req_cmd = (new FIFOIO) { new MemReqCmd } - val mem_req_data = (new FIFOIO) { new MemData } - val mem_req_lock = Bool(OUTPUT) - val probe_req = (new FIFOIO) { new ProbeRequest } - val busy = Bool(OUTPUT) - val addr = Bits(OUTPUT, PADDR_BITS - OFFSET_BITS) - val init_tile_id = Bits(OUTPUT, TILE_ID_BITS) - val p_rep_tile_id = Bits(OUTPUT, TILE_ID_BITS) - val tile_xact_id = Bits(OUTPUT, TILE_XACT_ID_BITS) - val sharer_count = Bits(OUTPUT, TILE_ID_BITS+1) - val x_type = Bits(OUTPUT, X_INIT_TYPE_MAX_BITS) - val push_p_req = Bits(OUTPUT, ntiles) - val pop_p_rep = Bits(OUTPUT, ntiles) - val pop_p_rep_data = Bits(OUTPUT, ntiles) - val pop_p_rep_dep = Bits(OUTPUT, ntiles) - val pop_x_init = Bits(OUTPUT, ntiles) - val pop_x_init_data = Bits(OUTPUT, ntiles) - val pop_x_init_dep = Bits(OUTPUT, ntiles) - val send_x_rep_ack = Bool(OUTPUT) - } - - def doMemReqWrite(req_cmd: FIFOIO[MemReqCmd], req_data: FIFOIO[MemData], lock: Bool, data: PipeIO[MemData], trigger: Bool, cmd_sent: Bool, pop_data: Bits, pop_dep: Bits, at_front_of_dep_queue: Bool, tile_id: UFix) { - req_cmd.bits.rw := Bool(true) - req_data.bits := data.bits - when(req_cmd.ready && req_cmd.valid) { - cmd_sent := Bool(true) - } - when (at_front_of_dep_queue) { - req_cmd.valid := !cmd_sent && req_data.ready && data.valid - lock := data.valid || cmd_sent - when (req_cmd.ready || cmd_sent) { - req_data.valid := data.valid - when(req_data.ready) { - pop_data := UFix(1) << tile_id - when (data.valid) { - mem_cnt := mem_cnt_next - when(mem_cnt === UFix(REFILL_CYCLES-1)) { - pop_dep := UFix(1) << tile_id - trigger := Bool(false) - } - } - } - } - } - } - - def doMemReqRead(req_cmd: FIFOIO[MemReqCmd], trigger: Bool) { - req_cmd.valid := Bool(true) - req_cmd.bits.rw := Bool(false) - when(req_cmd.ready) { - trigger := Bool(false) - } - } - - val s_idle :: s_ack :: s_mem :: s_probe :: s_busy :: Nil = Enum(5){ UFix() } - val state = Reg(resetVal = s_idle) - val addr_ = Reg{ UFix() } - val x_type_ = Reg{ Bits() } - val init_tile_id_ = Reg{ Bits() } - val tile_xact_id_ = Reg{ Bits() } - val p_rep_count = if (ntiles == 1) UFix(0) else Reg(resetVal = UFix(0, width = log2Up(ntiles))) - val p_req_flags = Reg(resetVal = Bits(0, width = ntiles)) - val p_rep_tile_id_ = Reg{ Bits() } - val x_needs_read = Reg(resetVal = Bool(false)) - val x_init_data_needs_write = Reg(resetVal = Bool(false)) - val p_rep_data_needs_write = Reg(resetVal = Bool(false)) - val x_w_mem_cmd_sent = Reg(resetVal = Bool(false)) - val p_w_mem_cmd_sent = Reg(resetVal = Bool(false)) - val mem_cnt = Reg(resetVal = UFix(0, width = log2Up(REFILL_CYCLES))) - val mem_cnt_next = mem_cnt + UFix(1) - val mem_cnt_max = ~UFix(0, width = log2Up(REFILL_CYCLES)) - val p_req_initial_flags = Bits(width = ntiles) - p_req_initial_flags := (if (ntiles == 1) Bits(0) else ~(io.tile_incoherent | UFixToOH(io.alloc_req.bits.tile_id(log2Up(ntiles)-1,0)))) //TODO: Broadcast only - - io.busy := state != s_idle - io.addr := addr_ - io.init_tile_id := init_tile_id_ - io.p_rep_tile_id := p_rep_tile_id_ - io.tile_xact_id := tile_xact_id_ - io.sharer_count := UFix(ntiles) // TODO: Broadcast only - io.x_type := x_type_ - - io.mem_req_cmd.valid := Bool(false) - io.mem_req_cmd.bits.rw := Bool(false) - io.mem_req_cmd.bits.addr := addr_ - io.mem_req_cmd.bits.tag := UFix(id) - io.mem_req_data.valid := Bool(false) - io.mem_req_data.bits.data := UFix(0) - io.mem_req_lock := Bool(false) - io.probe_req.valid := Bool(false) - io.probe_req.bits.p_type := co.getProbeRequestType(x_type_, UFix(0)) - io.probe_req.bits.global_xact_id := UFix(id) - io.probe_req.bits.addr := addr_ - io.push_p_req := Bits(0, width = ntiles) - io.pop_p_rep := Bits(0, width = ntiles) - io.pop_p_rep_data := Bits(0, width = ntiles) - io.pop_p_rep_dep := Bits(0, width = ntiles) - io.pop_x_init := Bits(0, width = ntiles) - io.pop_x_init_data := Bits(0, width = ntiles) - io.pop_x_init_dep := Bits(0, width = ntiles) - io.send_x_rep_ack := Bool(false) - - switch (state) { - is(s_idle) { - when( io.alloc_req.valid && io.can_alloc ) { - addr_ := io.alloc_req.bits.xact_init.addr - x_type_ := io.alloc_req.bits.xact_init.x_type - init_tile_id_ := io.alloc_req.bits.tile_id - tile_xact_id_ := io.alloc_req.bits.xact_init.tile_xact_id - x_init_data_needs_write := co.messageHasData(io.alloc_req.bits.xact_init) - x_needs_read := co.needsMemRead(io.alloc_req.bits.xact_init.x_type, UFix(0)) - p_req_flags := p_req_initial_flags - mem_cnt := UFix(0) - p_w_mem_cmd_sent := Bool(false) - x_w_mem_cmd_sent := Bool(false) - io.pop_x_init := UFix(1) << io.alloc_req.bits.tile_id - if(ntiles > 1) { - p_rep_count := PopCount(p_req_initial_flags) - state := Mux(p_req_initial_flags.orR, s_probe, s_mem) - } else state := s_mem - } - } - is(s_probe) { - when(p_req_flags.orR) { - io.push_p_req := p_req_flags - io.probe_req.valid := Bool(true) - } - when(io.p_req_cnt_inc.orR) { - p_req_flags := p_req_flags & ~io.p_req_cnt_inc // unflag sent reqs - } - when(io.p_rep_cnt_dec.orR) { - val dec = PopCount(io.p_rep_cnt_dec) - io.pop_p_rep := io.p_rep_cnt_dec - if(ntiles > 1) p_rep_count := p_rep_count - dec - when(p_rep_count === dec) { - state := s_mem - } - } - when(io.p_data.valid) { - p_rep_data_needs_write := Bool(true) - p_rep_tile_id_ := io.p_data.bits.tile_id - } - } - is(s_mem) { - when (p_rep_data_needs_write) { - doMemReqWrite(io.mem_req_cmd, - io.mem_req_data, - io.mem_req_lock, - io.p_rep_data, - p_rep_data_needs_write, - p_w_mem_cmd_sent, - io.pop_p_rep_data, - io.pop_p_rep_dep, - io.p_rep_data_dep.valid && (io.p_rep_data_dep.bits.global_xact_id === UFix(id)), - p_rep_tile_id_) - } . elsewhen(x_init_data_needs_write) { - doMemReqWrite(io.mem_req_cmd, - io.mem_req_data, - io.mem_req_lock, - io.x_init_data, - x_init_data_needs_write, - x_w_mem_cmd_sent, - io.pop_x_init_data, - io.pop_x_init_dep, - io.x_init_data_dep.valid && (io.x_init_data_dep.bits.global_xact_id === UFix(id)), - init_tile_id_) - } . elsewhen (x_needs_read) { - doMemReqRead(io.mem_req_cmd, x_needs_read) - } . otherwise { - state := Mux(co.needsAckReply(x_type_, UFix(0)), s_ack, s_busy) - } - } - is(s_ack) { - io.send_x_rep_ack := Bool(true) - when(io.sent_x_rep_ack) { state := s_busy } - } - is(s_busy) { // Nothing left to do but wait for transaction to complete - when (io.xact_finish) { - state := s_idle - } - } - } -} - -abstract class CoherenceHub(ntiles: Int, co: CoherencePolicy) extends Component { - val io = new Bundle { - val tiles = Vec(ntiles) { new ioTileLink() }.flip - val mem = new ioMem - } -} - -class CoherenceHubNull(co: ThreeStateIncoherence) extends CoherenceHub(1, co) -{ - val x_init = io.tiles(0).xact_init - val is_write = x_init.bits.x_type === co.xactInitWriteback - x_init.ready := io.mem.req_cmd.ready && !(is_write && io.mem.resp.valid) //stall write req/resp to handle previous read resp - io.mem.req_cmd.valid := x_init.valid && !(is_write && io.mem.resp.valid) - io.mem.req_cmd.bits.rw := is_write - io.mem.req_cmd.bits.tag := x_init.bits.tile_xact_id - io.mem.req_cmd.bits.addr := x_init.bits.addr - io.mem.req_data <> io.tiles(0).xact_init_data - - val x_rep = io.tiles(0).xact_rep - x_rep.bits.x_type := Mux(io.mem.resp.valid, co.xactReplyData, co.xactReplyAck) - x_rep.bits.tile_xact_id := Mux(io.mem.resp.valid, io.mem.resp.bits.tag, x_init.bits.tile_xact_id) - x_rep.bits.global_xact_id := UFix(0) // don't care - x_rep.bits.data := io.mem.resp.bits.data - x_rep.bits.require_ack := Bool(true) - x_rep.valid := io.mem.resp.valid || x_init.valid && is_write && io.mem.req_cmd.ready - - io.tiles(0).xact_abort.valid := Bool(false) - io.tiles(0).xact_finish.ready := Bool(true) - io.tiles(0).probe_req.valid := Bool(false) - io.tiles(0).probe_rep.ready := Bool(true) - io.tiles(0).probe_rep_data.ready := Bool(true) -} - - -class CoherenceHubBroadcast(ntiles: Int, co: CoherencePolicy) extends CoherenceHub(ntiles, co) -{ - val trackerList = (0 until NGLOBAL_XACTS).map(new XactTracker(ntiles, _, co)) - - val busy_arr = Vec(NGLOBAL_XACTS){ Bool() } - val addr_arr = Vec(NGLOBAL_XACTS){ Bits(width=PADDR_BITS-OFFSET_BITS) } - val init_tile_id_arr = Vec(NGLOBAL_XACTS){ Bits(width=TILE_ID_BITS) } - val tile_xact_id_arr = Vec(NGLOBAL_XACTS){ Bits(width=TILE_XACT_ID_BITS) } - val x_type_arr = Vec(NGLOBAL_XACTS){ Bits(width=X_INIT_TYPE_MAX_BITS) } - val sh_count_arr = Vec(NGLOBAL_XACTS){ Bits(width=TILE_ID_BITS) } - val send_x_rep_ack_arr = Vec(NGLOBAL_XACTS){ Bool() } - - val do_free_arr = Vec(NGLOBAL_XACTS){ Bool() } - val p_rep_cnt_dec_arr = VecBuf(NGLOBAL_XACTS){ Vec(ntiles){ Bool()} } - val p_req_cnt_inc_arr = VecBuf(NGLOBAL_XACTS){ Vec(ntiles){ Bool()} } - val sent_x_rep_ack_arr = Vec(NGLOBAL_XACTS){ Bool() } - val p_data_tile_id_arr = Vec(NGLOBAL_XACTS){ Bits(width = TILE_ID_BITS) } - val p_data_valid_arr = Vec(NGLOBAL_XACTS){ Bool() } - - for( i <- 0 until NGLOBAL_XACTS) { - val t = trackerList(i).io - busy_arr(i) := t.busy - addr_arr(i) := t.addr - init_tile_id_arr(i) := t.init_tile_id - tile_xact_id_arr(i) := t.tile_xact_id - x_type_arr(i) := t.x_type - sh_count_arr(i) := t.sharer_count - send_x_rep_ack_arr(i) := t.send_x_rep_ack - t.xact_finish := do_free_arr(i) - t.p_data.bits.tile_id := p_data_tile_id_arr(i) - t.p_data.valid := p_data_valid_arr(i) - t.p_rep_cnt_dec := p_rep_cnt_dec_arr(i).toBits - t.p_req_cnt_inc := p_req_cnt_inc_arr(i).toBits - t.tile_incoherent := (Vec(io.tiles.map(_.incoherent)) { Bool() }).toBits - t.sent_x_rep_ack := sent_x_rep_ack_arr(i) - do_free_arr(i) := Bool(false) - sent_x_rep_ack_arr(i) := Bool(false) - p_data_tile_id_arr(i) := Bits(0, width = TILE_ID_BITS) - p_data_valid_arr(i) := Bool(false) - for( j <- 0 until ntiles) { - p_rep_cnt_dec_arr(i)(j) := Bool(false) - p_req_cnt_inc_arr(i)(j) := Bool(false) - } - } - - val p_rep_data_dep_list = List.fill(ntiles)((new Queue(NGLOBAL_XACTS)){new TrackerDependency}) // depth must >= NPRIMARY - val x_init_data_dep_list = List.fill(ntiles)((new Queue(NGLOBAL_XACTS)){new TrackerDependency}) // depth should >= NPRIMARY - - // Free finished transactions - for( j <- 0 until ntiles ) { - val finish = io.tiles(j).xact_finish - when (finish.valid) { - do_free_arr(finish.bits.global_xact_id) := Bool(true) - } - finish.ready := Bool(true) - } - - // Reply to initial requestor - // Forward memory responses from mem to tile or arbitrate to ack - val mem_idx = io.mem.resp.bits.tag - val ack_idx = PriorityEncoder(send_x_rep_ack_arr.toBits) - for( j <- 0 until ntiles ) { - val rep = io.tiles(j).xact_rep - rep.bits.x_type := UFix(0) - rep.bits.tile_xact_id := UFix(0) - rep.bits.global_xact_id := UFix(0) - rep.bits.data := io.mem.resp.bits.data - rep.bits.require_ack := Bool(true) - rep.valid := Bool(false) - when(io.mem.resp.valid && (UFix(j) === init_tile_id_arr(mem_idx))) { - rep.bits.x_type := co.getTransactionReplyType(x_type_arr(mem_idx), sh_count_arr(mem_idx)) - rep.bits.tile_xact_id := tile_xact_id_arr(mem_idx) - rep.bits.global_xact_id := mem_idx - rep.valid := Bool(true) - } . otherwise { - rep.bits.x_type := co.getTransactionReplyType(x_type_arr(ack_idx), sh_count_arr(ack_idx)) - rep.bits.tile_xact_id := tile_xact_id_arr(ack_idx) - rep.bits.global_xact_id := ack_idx - when (UFix(j) === init_tile_id_arr(ack_idx)) { - rep.valid := send_x_rep_ack_arr.toBits.orR - sent_x_rep_ack_arr(ack_idx) := rep.ready - } - } - } - io.mem.resp.ready := io.tiles(init_tile_id_arr(mem_idx)).xact_rep.ready - - // Create an arbiter for the one memory port - // We have to arbitrate between the different trackers' memory requests - // and once we have picked a request, get the right write data - val mem_req_cmd_arb = (new Arbiter(NGLOBAL_XACTS)) { new MemReqCmd() } - val mem_req_data_arb = (new LockingArbiter(NGLOBAL_XACTS)) { new MemData() } - for( i <- 0 until NGLOBAL_XACTS ) { - mem_req_cmd_arb.io.in(i) <> trackerList(i).io.mem_req_cmd - mem_req_data_arb.io.in(i) <> trackerList(i).io.mem_req_data - mem_req_data_arb.io.lock(i) <> trackerList(i).io.mem_req_lock - } - io.mem.req_cmd <> Queue(mem_req_cmd_arb.io.out) - io.mem.req_data <> Queue(mem_req_data_arb.io.out) - - // Handle probe replies, which may or may not have data - for( j <- 0 until ntiles ) { - val p_rep = io.tiles(j).probe_rep - val p_rep_data = io.tiles(j).probe_rep_data - val idx = p_rep.bits.global_xact_id - val pop_p_reps = trackerList.map(_.io.pop_p_rep(j).toBool) - val do_pop = foldR(pop_p_reps)(_ || _) - p_rep.ready := Bool(true) - p_rep_data_dep_list(j).io.enq.valid := p_rep.valid && co.messageHasData(p_rep.bits) - p_rep_data_dep_list(j).io.enq.bits.global_xact_id := p_rep.bits.global_xact_id - p_rep_data.ready := foldR(trackerList.map(_.io.pop_p_rep_data(j)))(_ || _) - when (p_rep.valid && co.messageHasData(p_rep.bits)) { - p_data_valid_arr(idx) := Bool(true) - p_data_tile_id_arr(idx) := UFix(j) - } - p_rep_data_dep_list(j).io.deq.ready := foldR(trackerList.map(_.io.pop_p_rep_dep(j).toBool))(_||_) - } - for( i <- 0 until NGLOBAL_XACTS ) { - trackerList(i).io.p_rep_data.valid := io.tiles(trackerList(i).io.p_rep_tile_id).probe_rep_data.valid - trackerList(i).io.p_rep_data.bits := io.tiles(trackerList(i).io.p_rep_tile_id).probe_rep_data.bits - - trackerList(i).io.p_rep_data_dep.valid := MuxLookup(trackerList(i).io.p_rep_tile_id, p_rep_data_dep_list(0).io.deq.valid, (0 until ntiles).map( j => UFix(j) -> p_rep_data_dep_list(j).io.deq.valid)) - trackerList(i).io.p_rep_data_dep.bits := MuxLookup(trackerList(i).io.p_rep_tile_id, p_rep_data_dep_list(0).io.deq.bits, (0 until ntiles).map( j => UFix(j) -> p_rep_data_dep_list(j).io.deq.bits)) - - for( j <- 0 until ntiles) { - val p_rep = io.tiles(j).probe_rep - p_rep_cnt_dec_arr(i)(j) := p_rep.valid && (p_rep.bits.global_xact_id === UFix(i)) - } - } - - // Nack conflicting transaction init attempts - val s_idle :: s_abort_drain :: s_abort_send :: Nil = Enum(3){ UFix() } - val abort_state_arr = Vec(ntiles) { Reg(resetVal = s_idle) } - val want_to_abort_arr = Vec(ntiles) { Bool() } - for( j <- 0 until ntiles ) { - val x_init = io.tiles(j).xact_init - val x_init_data = io.tiles(j).xact_init_data - val x_abort = io.tiles(j).xact_abort - val abort_cnt = Reg(resetVal = UFix(0, width = log2Up(REFILL_CYCLES))) - val conflicts = Vec(NGLOBAL_XACTS) { Bool() } - for( i <- 0 until NGLOBAL_XACTS) { - val t = trackerList(i).io - conflicts(i) := t.busy && x_init.valid && co.isCoherenceConflict(t.addr, x_init.bits.addr) - } - x_abort.bits.tile_xact_id := x_init.bits.tile_xact_id - want_to_abort_arr(j) := x_init.valid && (conflicts.toBits.orR || busy_arr.toBits.andR || (!x_init_data_dep_list(j).io.enq.ready && co.messageHasData(x_init.bits))) - - x_abort.valid := Bool(false) - switch(abort_state_arr(j)) { - is(s_idle) { - when(want_to_abort_arr(j)) { - when(co.messageHasData(x_init.bits)) { - abort_state_arr(j) := s_abort_drain - } . otherwise { - abort_state_arr(j) := s_abort_send - } - } - } - is(s_abort_drain) { // raises x_init_data.ready below - when(x_init_data.valid) { - abort_cnt := abort_cnt + UFix(1) - when(abort_cnt === ~UFix(0, width = log2Up(REFILL_CYCLES))) { - abort_state_arr(j) := s_abort_send - } - } - } - is(s_abort_send) { // nothing is dequeued for now - x_abort.valid := Bool(true) - when(x_abort.ready) { // raises x_init.ready below - abort_state_arr(j) := s_idle - } - } - } - } - - // Handle transaction initiation requests - // Only one allocation per cycle - // Init requests may or may not have data - val alloc_arb = (new Arbiter(NGLOBAL_XACTS)) { Bool() } - val init_arb = (new Arbiter(ntiles)) { new TrackerAllocReq() } - for( i <- 0 until NGLOBAL_XACTS ) { - alloc_arb.io.in(i).valid := !trackerList(i).io.busy - trackerList(i).io.can_alloc := alloc_arb.io.in(i).ready - trackerList(i).io.alloc_req.bits := init_arb.io.out.bits - trackerList(i).io.alloc_req.valid := init_arb.io.out.valid - - trackerList(i).io.x_init_data.bits := io.tiles(trackerList(i).io.init_tile_id).xact_init_data.bits - trackerList(i).io.x_init_data.valid := io.tiles(trackerList(i).io.init_tile_id).xact_init_data.valid - trackerList(i).io.x_init_data_dep.bits := MuxLookup(trackerList(i).io.init_tile_id, x_init_data_dep_list(0).io.deq.bits, (0 until ntiles).map( j => UFix(j) -> x_init_data_dep_list(j).io.deq.bits)) - trackerList(i).io.x_init_data_dep.valid := MuxLookup(trackerList(i).io.init_tile_id, x_init_data_dep_list(0).io.deq.valid, (0 until ntiles).map( j => UFix(j) -> x_init_data_dep_list(j).io.deq.valid)) - } - for( j <- 0 until ntiles ) { - val x_init = io.tiles(j).xact_init - val x_init_data = io.tiles(j).xact_init_data - val x_init_data_dep = x_init_data_dep_list(j).io.deq - val x_abort = io.tiles(j).xact_abort - init_arb.io.in(j).valid := (abort_state_arr(j) === s_idle) && !want_to_abort_arr(j) && x_init.valid - init_arb.io.in(j).bits.xact_init := x_init.bits - init_arb.io.in(j).bits.tile_id := UFix(j) - val pop_x_inits = trackerList.map(_.io.pop_x_init(j).toBool) - val do_pop = foldR(pop_x_inits)(_||_) - x_init_data_dep_list(j).io.enq.valid := do_pop && co.messageHasData(x_init.bits) && (abort_state_arr(j) === s_idle) - x_init_data_dep_list(j).io.enq.bits.global_xact_id := OHToUFix(pop_x_inits) - x_init.ready := (x_abort.valid && x_abort.ready) || do_pop - x_init_data.ready := (abort_state_arr(j) === s_abort_drain) || foldR(trackerList.map(_.io.pop_x_init_data(j).toBool))(_||_) - x_init_data_dep.ready := foldR(trackerList.map(_.io.pop_x_init_dep(j).toBool))(_||_) - } - - alloc_arb.io.out.ready := init_arb.io.out.valid - - // Handle probe request generation - // Must arbitrate for each request port - val p_req_arb_arr = List.fill(ntiles)((new Arbiter(NGLOBAL_XACTS)) { new ProbeRequest() }) - for( j <- 0 until ntiles ) { - for( i <- 0 until NGLOBAL_XACTS ) { - val t = trackerList(i).io - p_req_arb_arr(j).io.in(i).bits := t.probe_req.bits - p_req_arb_arr(j).io.in(i).valid := t.probe_req.valid && t.push_p_req(j) - p_req_cnt_inc_arr(i)(j) := p_req_arb_arr(j).io.in(i).ready - } - p_req_arb_arr(j).io.out <> io.tiles(j).probe_req - } - -}