1
0

tilelink2: RAMModel, use CRC16 to check AMO response

This commit is contained in:
Wesley W. Terpstra 2017-04-14 15:00:41 -07:00
parent 6aeec673f2
commit ba8be17c9a

View File

@ -5,7 +5,7 @@ package uncore.tilelink2
import Chisel._
import config._
import diplomacy._
import util.GenericParameterizedBundle
import util.{GenericParameterizedBundle, CRC}
// We detect concurrent puts that put memory into an undefined state.
// put0, put0Ack, put1, put1Ack => ok: defined
@ -45,6 +45,7 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
val addressBits = log2Up(endAddress)
val countBits = log2Up(endSourceId)
val sizeBits = edge.bundle.sizeBits
val divisor = CRC.CRC_16F_4_2
// Reset control logic
val wipeIndex = RegInit(UInt(0, width = log2Ceil(endAddressHi) + 1))
@ -157,18 +158,29 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
val a_waddr = Mux(wipe, wipeIndex, a_addr_hi)
val a_shadow = shadow.map(_.read(a_waddr))
val a_known_old = !(Cat(a_shadow.map(!_.valid).reverse) & a_mask).orR
val alu = Module(new Atomics(a.params))
alu.io.write := Bool(false)
alu.io.a := a
alu.io.data_in := Cat(a_shadow.map(_.value).reverse)
val crc = Mem(endSourceId, UInt(width = 16))
val crc_valid = Mem(endSourceId, Bool())
val a_crc_acc = Mux(a_first, UInt(0), crc(a.source))
val a_crc_new = Cat(a_shadow.zipWithIndex.map { case (z, i) => Mux(a_mask(i), z.value, UInt(0)) }.reverse)
val a_crc = CRC(divisor, Cat(a_crc_acc, a_crc_new), 16 + beatBytes*8)
val a_crc_valid = a_known_old && Mux(a_first, Bool(true), crc_valid(a.source))
when (a_fire) {
crc.write(a.source, a_crc)
crc_valid.write(a.source, a_crc_valid)
}
for (i <- 0 until beatBytes) {
val data = Wire(new TLRAMModel.ByteMonitor(params))
val busy = a_inc(i) =/= a_dec(i) + (!a_first).asUInt
val amo = a.opcode === TLMessages.ArithmeticData || a.opcode === TLMessages.LogicalData
val known_old = !(Cat(a_shadow.map(!_.valid).reverse) & a_mask).orR
val beat_amo = a.size <= UInt(log2Ceil(beatBytes))
data.valid := Mux(wipe, Bool(false), (!busy || a_fifo) && (!amo || (known_old && beat_amo)))
data.valid := Mux(wipe, Bool(false), (!busy || a_fifo) && (!amo || (a_known_old && beat_amo)))
data.value := alu.io.data_out(8*(i+1)-1, 8*i)
when (shadow_wen(i)) {
shadow(i).write(a_waddr, data)
@ -213,7 +225,22 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
val d_shadow = shadow.map(_.read(d_addr_hi))
val d_valid = valid(d.source)
// CRC check
val d_crc_reg = Reg(UInt(width = 16))
val d_crc_acc = Mux(d_first, UInt(0), d_crc_reg)
val d_crc_new = FillInterleaved(8, d_mask) & d.data
val d_crc = CRC(divisor, Cat(d_crc_acc, d_crc_new), 16 + beatBytes*8)
val crc_bypass = if (edge.manager.minLatency > 0) Bool(false) else a_fire && a.source === d.source
val d_crc_valid = Mux(crc_bypass, a_crc_valid, crc_valid.read(d.source))
val d_crc_check = Mux(crc_bypass, a_crc, crc.read(d.source))
val d_no_race_reg = Reg(Bool())
val d_no_race = Wire(init = d_no_race_reg)
when (d_fire) {
d_crc_reg := d_crc
d_no_race_reg := d_no_race
// Check the response is correct
assert (d_size === d_flight.size)
// addr_lo is allowed to differ
@ -262,20 +289,30 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
printf(" 0x%x := 0x%x", d_addr, got)
when (!shadow.valid) {
printf(", undefined (uninitialized or prior overlapping puts)\n")
} .elsewhen ((d_flight.opcode === TLMessages.ArithmeticData || d_flight.opcode === TLMessages.LogicalData) &&
(d_inc(i) - d_dec(i) === UInt(1))) {
printf(", unsupported AMO output check\n") // !!! improve this?
} .elsewhen (d_inc(i) =/= d_dec(i)) {
printf(", undefined (concurrent incomplete puts #%d)\n", d_inc(i) - d_dec(i))
} .elsewhen (!d_fifo && !d_valid) {
printf(", undefined (concurrent completed put)\n")
} .otherwise {
printf("\n")
when (shadow.value =/= got) { printf("EXPECTED: 0x%x\n", shadow.value) }
assert (shadow.value === got)
}
}
}
}
when (d_flight.opcode === TLMessages.ArithmeticData || d_flight.opcode === TLMessages.LogicalData) {
val race = (d_inc zip d_dec) map { case (i, d) => i - d =/= UInt(1) }
when (d_first) { d_no_race := Bool(true) }
when ((Cat(race.reverse) & d_mask).orR) { d_no_race := Bool(false) }
when (d_last) {
val must_match = d_crc_valid && (d_fifo || (d_valid && d_no_race))
printf(log + " crc = 0x%x %d\n", d_crc, must_match.asUInt)
when (must_match && d_crc =/= d_crc_check) { printf("EXPECTED: 0x%x\n", d_crc_check) }
assert (!must_match || d_crc === d_crc_check)
}
}
}
val d_waddr = Mux(wipe, wipeIndex, d_addr_hi)