diff --git a/groundtest/src/main/scala/Regression.scala b/groundtest/src/main/scala/Regression.scala index 424adf5a..a971d327 100644 --- a/groundtest/src/main/scala/Regression.scala +++ b/groundtest/src/main/scala/Regression.scala @@ -558,7 +558,11 @@ class PutBeforePutBlockRegression(implicit p: Parameters) extends Regression()(p io.errored := Bool(false) } -class RepeatedGetRegression(implicit p: Parameters) extends Regression()(p) { +/** + * Make sure that multiple gets to the same line and beat are merged + * correctly, even if it is a cache miss. + */ +class MergedGetRegression(implicit p: Parameters) extends Regression()(p) { disableCache() val l2params = p.alterPartial({ case CacheName => "L2Bank" }) @@ -568,6 +572,7 @@ class RepeatedGetRegression(implicit p: Parameters) extends Regression()(p) { val (s_idle :: s_put :: s_get :: s_done :: Nil) = Enum(Bits(), 4) val state = Reg(init = s_idle) + // Write NWays + 1 different conflicting lines to force an eviction of the first line val (put_acq_cnt, put_acq_done) = Counter(state === s_put && io.mem.acquire.fire(), nWays + 1) val (put_gnt_cnt, put_gnt_done) = Counter(state === s_put && io.mem.grant.fire(), nWays + 1) val put_addr = UInt(memStartBlock) + Cat(put_acq_cnt, UInt(0, log2Up(nSets))) @@ -608,6 +613,74 @@ class RepeatedGetRegression(implicit p: Parameters) extends Regression()(p) { io.errored := data_mismatch } +/** + * Make sure that multiple puts to the same line and beat are merged + * correctly, even if there is a release from the L1 + */ +class MergedPutRegression(implicit p: Parameters) extends Regression()(p) + with HasTileLinkParameters { + val (s_idle :: s_cache_req :: s_cache_wait :: + s_put :: s_get :: s_done :: Nil) = Enum(Bits(), 6) + val state = Reg(init = s_idle) + + io.cache.req.valid := (state === s_cache_req) + io.cache.req.bits.cmd := M_XWR + io.cache.req.bits.typ := MT_D + io.cache.req.bits.addr := UInt(memStart) + io.cache.req.bits.data := UInt(1) + io.cache.req.bits.tag := UInt(0) + + val sending = Reg(init = Bool(false)) + val delaying = Reg(init = Bool(false)) + val (put_cnt, put_done) = Counter(io.mem.acquire.fire(), tlMaxClientXacts) + val (delay_cnt, delay_done) = Counter(delaying, 8) + val put_acked = Reg(UInt(width = 3), init = UInt(0)) + + io.mem.acquire.valid := sending && !delaying + io.mem.acquire.bits := Mux(state === s_put, + Put( + client_xact_id = put_cnt, + addr_block = UInt(memStartBlock), + addr_beat = UInt(0), + data = put_cnt + UInt(2)), + Get( + client_xact_id = UInt(0), + addr_block = UInt(memStartBlock), + addr_beat = UInt(0))) + io.mem.grant.ready := Bool(true) + + when (state === s_idle && io.start) { state := s_cache_req } + when (io.cache.req.fire()) { state := s_cache_wait } + when (io.cache.resp.valid) { state := s_put; sending := Bool(true) } + + when (io.mem.acquire.fire()) { + delaying := Bool(true) + when (put_done || state === s_get) { sending := Bool(false) } + } + when (delay_done) { delaying := Bool(false) } + + when (io.mem.grant.fire()) { + when (state === s_put) { + put_acked := put_acked | UIntToOH(io.mem.grant.bits.client_xact_id) + } + when (state === s_get) { state := s_done } + } + + when (state === s_put && put_acked.andR) { + state := s_get + sending := Bool(true) + } + + val expected_data = UInt(2 + tlMaxClientXacts - 1) + val data_mismatch = io.mem.grant.valid && io.mem.grant.bits.hasData() && + io.mem.grant.bits.data =/= expected_data + + assert(!data_mismatch, "MergedPutRegression: data mismatch") + + io.finished := (state === s_done) + io.errored := data_mismatch +} + object RegressionTests { def cacheRegressions(implicit p: Parameters) = Seq( Module(new PutBlockMergeRegression), @@ -620,7 +693,8 @@ object RegressionTests { Module(new PutBeforePutBlockRegression), Module(new MixedAllocPutRegression), Module(new ReleaseRegression), - Module(new RepeatedGetRegression)) + Module(new MergedGetRegression), + Module(new MergedPutRegression)) def broadcastRegressions(implicit p: Parameters) = Seq( Module(new IOGetAfterPutBlockRegression), Module(new WriteMaskedPutBlockRegression),