提交 d4da0b91 编写于 作者: B BigWhiteDog

add amo test

上级 fed99f11
......@@ -8,18 +8,24 @@ import scala.collection.mutable.{ArrayBuffer, ListBuffer}
class CoreAgent(ID: Int, name: String, addrStateMap: mutable.Map[BigInt, AddrState], serialList: ArrayBuffer[(Int, TLCTrans)]
, scoreboard: mutable.Map[BigInt, ScoreboardData], portNum: Int = 2)
(implicit p: Parameters) extends TLCAgent(ID, name, addrStateMap, serialList, scoreboard) {
(implicit p: Parameters) extends TLCAgent(ID, name, addrStateMap, serialList, scoreboard) with LitMemOp {
private val loadPortsReqMessage = ArrayBuffer.fill[Option[LitDCacheWordReq]](portNum)(None)
private val s0_loadTrans = ArrayBuffer.fill[Option[DCacheLoadCallerTrans]](portNum)(None)
private val s1_loadTrans = ArrayBuffer.fill[Option[DCacheLoadCallerTrans]](portNum)(None)
private val s2_loadTrans = ArrayBuffer.fill[Option[DCacheLoadCallerTrans]](portNum)(None)
private var storePortReqMessage: Option[LitDCacheLineReq] = None
private var amoPortReqMessage: Option[LitDCacheWordReq] = None
val outerLoad: ListBuffer[DCacheLoadCallerTrans] = ListBuffer()
val outerStore: ListBuffer[DCacheStoreCallerTrans] = ListBuffer()
val outerAMO: ListBuffer[DCacheAMOCallerTrans] = ListBuffer()
private val maxStoreId = 255
private val maxAMOId = 0
private val lsqWaiting: mutable.Queue[DCacheLoadCallerTrans] = mutable.Queue[DCacheLoadCallerTrans]()
private val storeIdMap: mutable.Map[BigInt, DCacheStoreCallerTrans] = mutable.Map[BigInt, DCacheStoreCallerTrans]()
private val amoIdMap: mutable.Map[BigInt, DCacheAMOCallerTrans] = mutable.Map[BigInt, DCacheAMOCallerTrans]()
def issueLoadReq(): Unit = {
for (i <- 0 until portNum) {
......@@ -108,7 +114,7 @@ class CoreAgent(ID: Int, name: String, addrStateMap: mutable.Map[BigInt, AddrSta
if (storePortReqMessage.isEmpty) {
val nextStore = outerStore.find(s => !s.reqIssued.getOrElse(true))
if (nextStore.isDefined) {
val allocId = (0 to 255).find(i => !storeIdMap.contains(BigInt(i)))
val allocId = (0 to maxStoreId).find(i => !storeIdMap.contains(BigInt(i)))
if (allocId.isDefined) {
//alloc & issue
storePortReqMessage = Some(nextStore.get.issueReq(BigInt(allocId.get)))
......@@ -141,6 +147,42 @@ class CoreAgent(ID: Int, name: String, addrStateMap: mutable.Map[BigInt, AddrSta
insertMaskedWrite(storeReq.addr, storeReq.data, storeReq.mask)
}
def issueAMOReq(): Unit = {
if (amoPortReqMessage.isEmpty) {
val nextAMO = outerAMO.find(a => !a.reqIssued.getOrElse(true))
if (nextAMO.isDefined) {
val allocId = (0 to maxAMOId).find(i => !amoIdMap.contains(BigInt(i)))
if (allocId.isDefined) {
val aid = allocId.get
//alloc & issue
amoPortReqMessage = Some(nextAMO.get.issueReq(BigInt(aid)))
amoIdMap(BigInt(aid))
}
}
}
}
def peekAMOReq(): Option[LitDCacheWordReq] = {
amoPortReqMessage
}
def fireAMOReq(): Unit = {
amoPortReqMessage = None
}
def fireAMOResp(resp: LitDCacheWordResp): Unit = {
val aid = resp.id
val amoT = amoIdMap(aid)
val amoReq = amoT.req.get
amoT.pairResp(resp)
amoIdMap.remove(aid)
outerAMO -= amoT
if (amoReq.cmd == M_XA_SWAP) {
insertMaskedWordRead(amoReq.addr, resp.data, amoReq.mask)
insertMaskedWordWrite(amoReq.addr, amoReq.data, amoReq.mask)
}
}
override def step(): Unit = {
for (i <- 0 until portNum) {
s2_loadTrans(i) = s1_loadTrans(i)
......@@ -183,4 +225,25 @@ class CoreAgent(ID: Int, name: String, addrStateMap: mutable.Map[BigInt, AddrSta
outerStore.append(storeT)
}
def addAMO(addr: BigInt): Unit = {
val amoT = new DCacheAMOCallerTrans()
val wordCnt = rand.nextInt(8)
val lgSize = rand.nextInt(4)
val rsize = 1 << lgSize
// addr must be aligned to size
val offset = (rand.nextInt(8) >> lgSize) << lgSize
val laddr = addr + wordCnt * 8 + offset
// generate mask from raddr and rsize
val mask = (BigInt(1) << rsize) - 1
val wmask = mask << offset
val wdata = (0 until 4).foldLeft(BigInt(0))(
(d, _) => (d << 16) | BigInt(rand.nextInt(0xffff))
)
//TODO: only swap for now
amoT.prepareAMOSwap(addr, wdata, wmask)
outerAMO.append(amoT)
}
}
\ No newline at end of file
......@@ -6,7 +6,9 @@ import xiangshan.cache.MemoryOpConstants
class LitDCacheWordReq(
val cmd: BigInt,
val addr: BigInt,
var data: BigInt = 0,
val mask: BigInt,
var id: BigInt = 0,
) {
}
......@@ -14,6 +16,7 @@ class LitDCacheWordResp(
val data: BigInt,
val miss: Boolean,
val replay: Boolean,
var id: BigInt = 0,
) {
}
......@@ -38,6 +41,7 @@ class LitDCacheLineResp(
trait LitMemOp {
val M_XRD: BigInt = MemoryOpConstants.M_XRD.litValue()
val M_XWR: BigInt = MemoryOpConstants.M_XWR.litValue()
val M_XA_SWAP: BigInt = MemoryOpConstants.M_XA_SWAP.litValue()
}
class DCacheLoadTrans extends TLCTrans with LitMemOp {
......@@ -110,3 +114,34 @@ class DCacheStoreCallerTrans extends DCacheStoreTrans with TLCCallerTrans {
}
class DCacheAMOTrans extends TLCTrans with LitMemOp {
var req: Option[LitDCacheWordReq] = None
var resp: Option[LitDCacheWordResp] = None
}
class DCacheAMOCallerTrans extends DCacheAMOTrans with TLCCallerTrans {
var reqIssued: Option[Boolean] = None
def prepareAMOSwap(addr: BigInt, data: BigInt, mask: BigInt): Unit = {
req = Some(
new LitDCacheWordReq(
cmd = M_XA_SWAP,
addr = addr,
data = data,
mask = mask,
)
)
reqIssued = Some(true)
}
def issueReq(allodId: BigInt = 0): LitDCacheWordReq = {
req.get.id = allodId
reqIssued = Some(true)
req.get
}
def pairResp(inResp: LitDCacheWordResp): Unit = {
resp = Some(inResp)
}
}
......@@ -64,7 +64,7 @@ class L1DCacheTest extends AnyFlatSpec with ChiselScalatestTester with Matchers
val rand = new Random(0xbeef)
val addr_pool = {
for (_ <- 0 until 16) yield BigInt(rand.nextInt(0xfff) << 12) | 0x80000000L.U.litValue()
for (_ <- 0 until 64) yield BigInt(rand.nextInt(0xfffff) << 6) | 0x80000000L.U.litValue()
}.distinct.toList // align to block size
val addr_list_len = addr_pool.length
println(f"addr pool length: $addr_list_len")
......@@ -97,6 +97,10 @@ class L1DCacheTest extends AnyFlatSpec with ChiselScalatestTester with Matchers
c.io.dcacheIO.store.resp.initSink().setSinkClock(c.clock)
c.io.dcacheIO.store.req.valid.poke(false.B)
c.io.dcacheIO.store.resp.ready.poke(false.B)
c.io.dcacheIO.atomics.req.initSource().setSourceClock(c.clock)
c.io.dcacheIO.atomics.resp.initSink().setSinkClock(c.clock)
c.io.dcacheIO.atomics.req.valid.poke(false.B)
c.io.dcacheIO.atomics.resp.ready.poke(false.B)
c.io.slaveIO.AChannel.initSink().setSinkClock(c.clock)
c.io.slaveIO.CChannel.initSink().setSinkClock(c.clock)
......@@ -110,7 +114,7 @@ class L1DCacheTest extends AnyFlatSpec with ChiselScalatestTester with Matchers
c.io.slaveIO.DChannel.valid.poke(false.B)
val total_clock = 50000
val total_clock = 500
c.reset.poke(true.B)
c.clock.step(100)
......@@ -149,6 +153,14 @@ class L1DCacheTest extends AnyFlatSpec with ChiselScalatestTester with Matchers
}
}
}
if (coreAgent.outerAMO.size <= 0) {
if (true) {
for (i <- 0 until 4) {
val addr = getRandomElement(addr_pool, rand)
coreAgent.addAMO(addr)
}
}
}
//========= core poke ============
val loadPortsReqValid = ListBuffer.fill(loadPortNum)(false)
val loadPortsRespReady = ListBuffer.fill(loadPortNum)(true)
......@@ -182,6 +194,21 @@ class L1DCacheTest extends AnyFlatSpec with ChiselScalatestTester with Matchers
coreIO.store.req.valid.poke(storePortReqValid.B)
coreIO.store.resp.ready.poke(storePortRespReady.B)
var amoPortReqValid = false
val amoPortRespReady = true
coreAgent.issueAMOReq()
val amoReq = coreAgent.peekAMOReq()
if (amoReq.isDefined) {
amoPortReqValid = true
coreIO.atomics.req.bits.cmd.poke(amoReq.get.cmd.U)
coreIO.atomics.req.bits.addr.poke(amoReq.get.addr.U)
coreIO.atomics.req.bits.data.poke(amoReq.get.data.U)
coreIO.atomics.req.bits.mask.poke(amoReq.get.mask.U)
coreIO.atomics.req.bits.meta.id.poke(amoReq.get.id.U)
}
coreIO.atomics.req.valid.poke(amoPortReqValid.B)
coreIO.atomics.resp.ready.poke(amoPortRespReady.B)
//========= slave ============
//randomly add when empty
if (slaveAgent.innerProbe.size <= 2) {
......@@ -318,6 +345,21 @@ class L1DCacheTest extends AnyFlatSpec with ChiselScalatestTester with Matchers
coreAgent.fireStoreResp(storeM)
}
val amoPortReqReady = peekBoolean(coreIO.atomics.req.ready)
if (amoPortReqValid && amoPortReqReady) {
coreAgent.fireAMOReq()
}
val amoPortRespValid = peekBoolean(coreIO.atomics.resp.valid)
if (amoPortRespValid && amoPortRespReady) {
val amoM = new LitDCacheWordResp(
data = peekBigInt(coreIO.atomics.resp.bits.data),
miss = false,
replay = false,
id = peekBigInt(coreIO.atomics.resp.bits.meta.id)
)
coreAgent.fireAMOResp(amoM)
}
val lsqRespValid = peekBoolean(coreIO.lsq.valid)
if (lsqRespValid) {
val lsqM = new LitDCacheLineResp(
......@@ -332,6 +374,17 @@ class L1DCacheTest extends AnyFlatSpec with ChiselScalatestTester with Matchers
c.clock.step()
}
c.io.dcacheIO.load.foreach { l =>
l.s1_kill.poke(true.B)
// l.s1_paddr.poke(0x80000000L.U)
l.req.valid.poke(false.B)
l.resp.ready.poke(true.B)
}
c.io.dcacheIO.store.req.valid.poke(false.B)
c.io.dcacheIO.store.resp.ready.poke(true.B)
c.io.dcacheIO.atomics.req.valid.poke(false.B)
c.io.dcacheIO.atomics.resp.ready.poke(true.B)
c.clock.step(10)
}
}
}
\ No newline at end of file
......@@ -302,6 +302,22 @@ class TLCAgent(ID: Int, name: String = "", addrStateMap: mutable.Map[BigInt, Add
debugPrintln(f"MaskedWrite, Addr: $alignAddr%x ,old sbData:$oldData%x , new sbData: $res%x , mask:$alignMask%x")
}
def insertMaskedWordWrite(addr:BigInt, newWordData: BigInt, wordByteMask: BigInt):Unit = {
//addr and mask must be aligned to block
val alignAddr = addrAlignBlock(addr)
val start_word = wordInBlock(addr)
val alignData = dataConcatWord(0, newWordData, start_word)
val alignMask = maskConcatWord(0, wordByteMask, start_word)
val addrState = getState(alignAddr)
//new data
val oldData = scoreboardRead(alignAddr)
val res = writeMaskedData(oldData, alignData, alignMask)
addrState.dirty = true
addrState.data = res
scoreboardWrite(alignAddr, res)
debugPrintln(f"MaskedWrite, Addr: $alignAddr%x ,old sbData:$oldData%x , new sbData: $res%x , mask:$alignMask%x")
}
//full block read
def insertRead(addr: BigInt, readData: BigInt): Unit = {
//Do not call masked read for performance
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册