From ba8be17c9a5ffbb86fe34c2845562395ce47f341 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 14 Apr 2017 15:00:41 -0700 Subject: [PATCH] tilelink2: RAMModel, use CRC16 to check AMO response --- .../scala/uncore/tilelink2/RAMModel.scala | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/RAMModel.scala b/src/main/scala/uncore/tilelink2/RAMModel.scala index e031273f..2befed32 100644 --- a/src/main/scala/uncore/tilelink2/RAMModel.scala +++ b/src/main/scala/uncore/tilelink2/RAMModel.scala @@ -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)