change WriteMaskedPutBlockRegression for better bug detection
Instead of sending puts back-to-back, separate the two puts with a get. Also, stall a bit between each transaction. This makes sure the puts and intermediate get are sent to the same transactor, which will cause the data buffer to get overwritten between the two puts.
This commit is contained in:
parent
3b0e87f42a
commit
471f4c2695
@ -198,60 +198,71 @@ class RepeatedNoAllocPutRegression(implicit p: Parameters) extends Regression()(
|
||||
io.finished := acked.andR
|
||||
}
|
||||
|
||||
/* Make sure write masking works properly.
|
||||
* This test assumes the memory is initialized to zero at the beginning.
|
||||
* This is true for the test harnesses, but not on the FPGA.
|
||||
* Technically, what should be done is to fill up a single set until the
|
||||
* first block is evicted, and then do the write-masked puts.
|
||||
* But this is annoying, and I doubt we will ever run these regression
|
||||
* tests on the FPGA. So ... */
|
||||
/* Make sure write masking works properly by writing a block of data
|
||||
* piece by piece */
|
||||
class WriteMaskedPutBlockRegression(implicit p: Parameters) extends Regression()(p) {
|
||||
io.cache.req.valid := Bool(false)
|
||||
|
||||
val s_idle :: s_put :: s_get :: s_wait :: s_done :: Nil = Enum(Bits(), 5)
|
||||
val (s_idle :: s_put_send :: s_put_ack :: s_stall ::
|
||||
s_get_send :: s_get_ack :: s_done :: Nil) = Enum(Bits(), 7)
|
||||
val state = Reg(init = s_idle)
|
||||
val post_stall_state = Reg(init = s_idle)
|
||||
|
||||
val gnt = io.mem.grant.bits
|
||||
val acq = io.mem.acquire.bits
|
||||
|
||||
val stage = Reg(init = UInt(0, 1))
|
||||
|
||||
val nPuts = 2
|
||||
val (put_beat, put_block_done) = Counter(
|
||||
io.mem.acquire.fire() && io.mem.acquire.bits.hasData(), tlDataBeats)
|
||||
val (put_cnt, puts_done) = Counter(put_block_done, nPuts)
|
||||
io.mem.acquire.fire() && acq.hasData(), tlDataBeats)
|
||||
|
||||
val data_bytes = Vec.tabulate(nPuts) { i => UInt(i, 8) }
|
||||
val data_beat = Fill(tlDataBytes, data_bytes(put_cnt))
|
||||
val acked = Reg(init = UInt(0, nPuts + 1))
|
||||
|
||||
val put_acq = PutBlock(
|
||||
client_xact_id = put_cnt,
|
||||
addr_block = UInt(7),
|
||||
addr_beat = put_beat,
|
||||
data = data_beat,
|
||||
wmask = UIntToOH(put_cnt))
|
||||
|
||||
val get_acq = Get(
|
||||
client_xact_id = UInt(nPuts),
|
||||
addr_block = UInt(7),
|
||||
addr_beat = UInt(0),
|
||||
addr_byte = UInt(0),
|
||||
operand_size = MT_D,
|
||||
alloc = Bool(false))
|
||||
|
||||
io.mem.acquire.valid := (state === s_put || state === s_get)
|
||||
io.mem.acquire.bits := Mux(state === s_get, get_acq, put_acq)
|
||||
io.mem.grant.ready := Bool(true)
|
||||
|
||||
when (io.mem.grant.fire()) {
|
||||
acked := acked | UIntToOH(io.mem.grant.bits.client_xact_id)
|
||||
val data_beats = Vec.tabulate(tlDataBeats) {
|
||||
i => UInt(0x3001040 + i * 4, tlDataBits)
|
||||
}
|
||||
|
||||
when (state === s_idle && io.start) { state := s_put }
|
||||
when (puts_done) { state := s_get }
|
||||
when (state === s_get && io.mem.acquire.ready) { state := s_wait }
|
||||
when (state === s_wait && acked.andR) { state := s_done }
|
||||
val put_acq = PutBlock(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(7),
|
||||
addr_beat = put_beat,
|
||||
data = Mux(put_beat(0) === stage, data_beats(put_beat), UInt(0)),
|
||||
wmask = Mux(put_beat(0) === stage, Acquire.fullWriteMask, Bits(0)))
|
||||
|
||||
val get_acq = GetBlock(
|
||||
client_xact_id = UInt(0),
|
||||
addr_block = UInt(6) + stage)
|
||||
|
||||
io.mem.acquire.valid := (state === s_put_send || state === s_get_send)
|
||||
io.mem.acquire.bits := Mux(state === s_get_send, get_acq, put_acq)
|
||||
io.mem.grant.ready := (state === s_put_ack || state === s_get_ack)
|
||||
|
||||
val (get_cnt, get_done) = Counter(
|
||||
io.mem.grant.fire() && gnt.hasData(), tlDataBeats)
|
||||
|
||||
val (stall_cnt, stall_done) = Counter(state === s_stall, 16)
|
||||
|
||||
when (state === s_idle && io.start) { state := s_put_send }
|
||||
when (put_block_done) { state := s_put_ack }
|
||||
when (state === s_put_ack && io.mem.grant.valid) {
|
||||
post_stall_state := s_get_send
|
||||
state := s_stall
|
||||
}
|
||||
when (stall_done) { state := post_stall_state }
|
||||
when (state === s_get_send && io.mem.acquire.ready) { state := s_get_ack }
|
||||
when (get_done) {
|
||||
// do a read in-between the two put-blocks to overwrite the data buffer
|
||||
when (stage === UInt(0)) {
|
||||
stage := stage + UInt(1)
|
||||
post_stall_state := s_put_send
|
||||
state := s_stall
|
||||
} .otherwise { state := s_done }
|
||||
}
|
||||
|
||||
io.finished := (state === s_done)
|
||||
|
||||
assert(!io.mem.grant.valid || !io.mem.grant.bits.hasData() ||
|
||||
io.mem.grant.bits.data === data_bytes.toBits,
|
||||
assert(!io.mem.grant.valid ||
|
||||
!io.mem.grant.bits.hasData() ||
|
||||
stage === UInt(0) ||
|
||||
io.mem.grant.bits.data === data_beats(get_cnt),
|
||||
"WriteMaskedPutBlockRegression: data does not match")
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user