From 387554e0e21995130cccd0ec295a6878c71aace4 Mon Sep 17 00:00:00 2001 From: Clo91eaf Date: Mon, 1 Jul 2024 19:49:24 +0800 Subject: [PATCH] [difftest] add memory write check --- difftest/t1-simulator/Cargo.lock | 35 +++++ difftest/t1-simulator/Cargo.toml | 1 + difftest/t1-simulator/src/difftest.rs | 120 +++++++++++------- difftest/t1-simulator/src/difftest/dut.rs | 69 +++++++--- difftest/t1-simulator/src/difftest/spike.rs | 38 ++++++ .../src/difftest/spike/spike_event.rs | 27 ++-- ipemu/src/TestBench.scala | 19 ++- t1/src/T1.scala | 2 +- t1/src/lsu/LSU.scala | 17 ++- t1/src/lsu/SimpleAccessUnit.scala | 15 +++ t1/src/lsu/StoreUnit.scala | 14 ++ 11 files changed, 270 insertions(+), 87 deletions(-) diff --git a/difftest/t1-simulator/Cargo.lock b/difftest/t1-simulator/Cargo.lock index d242b3a3d..3ca2112f1 100644 --- a/difftest/t1-simulator/Cargo.lock +++ b/difftest/t1-simulator/Cargo.lock @@ -65,6 +65,12 @@ version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + [[package]] name = "cfg-if" version = "1.0.0" @@ -182,6 +188,34 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -340,6 +374,7 @@ dependencies = [ "lazy_static", "libc", "libloading", + "num-bigint", "serde", "serde_json", "tracing", diff --git a/difftest/t1-simulator/Cargo.toml b/difftest/t1-simulator/Cargo.toml index b49da3e13..855f24dd9 100644 --- a/difftest/t1-simulator/Cargo.toml +++ b/difftest/t1-simulator/Cargo.toml @@ -16,4 +16,5 @@ anyhow = "1.0.79" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" lazy_static = "1.4.0" +num-bigint = "0.4.6" diff --git a/difftest/t1-simulator/src/difftest.rs b/difftest/t1-simulator/src/difftest.rs index 6c19be573..da3b2ce41 100644 --- a/difftest/t1-simulator/src/difftest.rs +++ b/difftest/t1-simulator/src/difftest.rs @@ -82,88 +82,120 @@ impl Difftest { let event = self.dut.step()?; + let cycle = event.parameter.cycle.unwrap(); + self.spike.cycle = cycle; match &*event.event { - "peekTL" => {} + "memoryWrite" => { + let data = event.parameter.data.clone().unwrap(); + let mask = event.parameter.mask.clone().unwrap(); + let address = event.parameter.address.unwrap(); + let source = event.parameter.source.unwrap(); + self.spike.peek_memory_write(MemoryWriteEvent { + mask, + data, + source, + address, + cycle, + }) + } "issue" => { let idx = event.parameter.idx.unwrap(); - let cycle = event.parameter.cycle.unwrap(); - self.spike.cycle = cycle; - self.peek_issue(IssueEvent { idx, cycle }).unwrap(); + self.peek_issue(IssueEvent { idx, cycle }) } "lsuEnq" => { let enq = event.parameter.enq.unwrap(); - let cycle = event.parameter.cycle.unwrap(); - self.spike.cycle = cycle; - self.update_lsu_idx(LsuEnqEvent { enq, cycle }).unwrap(); + self.update_lsu_idx(LsuEnqEvent { enq, cycle }) } "vrfWriteFromLsu" => { let idx = event.parameter.idx.unwrap(); let vd = event.parameter.vd.unwrap(); let offset = event.parameter.offset.unwrap(); - let mask = event.parameter.mask.unwrap(); - let data = event.parameter.data.unwrap(); + let mask = event.parameter.mask.clone().unwrap(); + let data = event.parameter.data.clone().unwrap(); let instruction = event.parameter.instruction.unwrap(); let lane = event.parameter.lane.unwrap(); - let cycle = event.parameter.cycle.unwrap(); - self.spike.cycle = cycle; assert!(idx < self.spike.config.dlen / 32); - self - .spike - .peek_vrf_write_from_lsu(VrfWriteEvent { - idx: lane.trailing_zeros(), - vd, - offset, - mask, - data, - instruction, - cycle, - }) - .unwrap(); + assert!(data.len() <= 4, "data length should be less than 4"); + let mut data_array = [0u8; 4]; + data + .iter() + .enumerate() + .for_each(|(i, &byte)| data_array[i] = byte); + let data = u32::from_le_bytes(data_array); + // convert mask to u8 + let mask = mask + .iter() + .rev() + .fold(0, |acc, &bit| (acc << 1) | bit as u8); + + self.spike.peek_vrf_write_from_lsu(VrfWriteEvent { + idx: lane.trailing_zeros(), + vd, + offset, + mask, + data, + instruction, + cycle, + }) } "vrfWriteFromLane" => { let idx = event.parameter.idx.unwrap(); let vd = event.parameter.vd.unwrap(); let offset = event.parameter.offset.unwrap(); - let mask = event.parameter.mask.unwrap(); - let data = event.parameter.data.unwrap(); + let mask = event.parameter.mask.clone().unwrap(); + let data = event.parameter.data.clone().unwrap(); let instruction = event.parameter.instruction.unwrap(); - let cycle = event.parameter.cycle.unwrap(); - self.spike.cycle = cycle; assert!(idx < self.spike.config.dlen / 32); - self - .spike - .peek_vrf_write_from_lane(VrfWriteEvent { - idx, - vd, - offset, - mask, - data, - instruction, - cycle, - }) - .unwrap(); + + assert!(data.len() <= 4, "data length should be less than 4"); + let mut array = [0u8; 4]; + data + .iter() + .enumerate() + .for_each(|(i, &byte)| array[i] = byte); + let data = u32::from_le_bytes(array); + // convert mask to u8 + let mask = mask + .iter() + .rev() + .fold(0, |acc, &bit| (acc << 1) | bit as u8); + + self.spike.peek_vrf_write_from_lane(VrfWriteEvent { + idx, + vd, + offset, + mask, + data, + instruction, + cycle, + }) } "inst" => { - let data = event.parameter.data.unwrap() as u32; - let cycle = event.parameter.cycle.unwrap(); - self.spike.cycle = cycle; + let data = event.parameter.data.clone().unwrap(); // let vxsat = event.parameter.vxsat.unwrap(); // let rd_valid = event.parameter.rd_valid.unwrap(); // let rd = event.parameter.rd.unwrap(); // let mem = event.parameter.mem.unwrap(); + assert!(data.len() <= 4, "data length should be less than 4"); + let mut array = [0u8; 4]; + data + .iter() + .enumerate() + .for_each(|(i, &byte)| array[i] = byte); + let data = u32::from_le_bytes(array); + let se = self.spike.to_rtl_queue.back().unwrap(); se.record_rd_write(data).unwrap(); se.check_is_ready_for_commit(cycle).unwrap(); self.spike.to_rtl_queue.pop_back(); + Ok(()) } _ => { panic!("unknown event: {}", event.event) } } - - Ok(()) } } diff --git a/difftest/t1-simulator/src/difftest/dut.rs b/difftest/t1-simulator/src/difftest/dut.rs index 51cb86fa1..cf2b8593c 100644 --- a/difftest/t1-simulator/src/difftest/dut.rs +++ b/difftest/t1-simulator/src/difftest/dut.rs @@ -1,14 +1,43 @@ -use serde::Deserialize; +use num_bigint::BigUint; +use serde::{Deserialize, Deserializer}; use std::io::BufRead; use std::path::Path; +use std::str::FromStr; -#[derive(Deserialize, Debug, PartialEq, Clone)] -pub enum Opcode { - PutFullData = 0, - PutPartialData = 1, - Get = 4, - // AccessAckData = 0, - // AccessAck = 0, +fn bigint_to_vec_u8<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let opt: Option<&str> = Option::deserialize(deserializer)?; + match opt { + Some(s) => { + let bigint = + BigUint::from_str(s.trim_start_matches(' ')).map_err(serde::de::Error::custom)?; + Ok(Some(bigint.to_bytes_le())) + } + None => Ok(None), + } +} + +fn bigint_to_vec_bool<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let opt: Option<&str> = Option::deserialize(deserializer)?; + match opt { + Some(s) => { + let bigint = + BigUint::from_str(s.trim_start_matches(' ')).map_err(serde::de::Error::custom)?; + let bytes = bigint.to_bytes_le(); + let bools = bytes + .iter() + .flat_map(|byte| (0..8).map(move |i| (byte >> i) & 1 == 1)) + .collect(); + + Ok(Some(bools)) + } + None => Ok(None), + } } #[derive(Deserialize, Debug)] @@ -18,15 +47,17 @@ pub struct Parameter { pub opcode: Option, pub param: Option, pub size: Option, - pub source: Option, + pub source: Option, pub address: Option, - pub mask: Option, - pub data: Option, + #[serde(deserialize_with = "bigint_to_vec_bool", default)] + pub mask: Option>, + #[serde(deserialize_with = "bigint_to_vec_u8", default)] + pub data: Option>, pub corrupt: Option, pub dready: Option, pub vd: Option, pub offset: Option, - pub instruction: Option, + pub instruction: Option, pub lane: Option, pub vxsat: Option, pub rd_valid: Option, @@ -51,13 +82,21 @@ pub struct LsuEnqEvent { pub cycle: usize, } +pub struct MemoryWriteEvent { + pub mask: Vec, + pub data: Vec, + pub source: u8, + pub address: u32, + pub cycle: usize, +} + pub struct VrfWriteEvent { pub idx: u32, pub vd: u32, pub offset: u32, - pub mask: u32, - pub data: u64, - pub instruction: u32, + pub mask: u8, + pub data: u32, + pub instruction: u8, pub cycle: usize, } diff --git a/difftest/t1-simulator/src/difftest/spike.rs b/difftest/t1-simulator/src/difftest/spike.rs index 9ddacaacb..d03e4f866 100644 --- a/difftest/t1-simulator/src/difftest/spike.rs +++ b/difftest/t1-simulator/src/difftest/spike.rs @@ -401,4 +401,42 @@ impl SpikeHandle { info!("[{cycle}] RecordRFAccess: index={} rtl detect vrf write which cannot find se, maybe from committed load insn", vrf_write.idx); Ok(()) } + + pub fn peek_memory_write(&mut self, memory_write: MemoryWriteEvent) -> anyhow::Result<()> { + let mut mask = memory_write.mask; + mask.resize(self.config.dlen as usize / 8, false); + let mut data = memory_write.data; + data.resize(self.config.dlen as usize / 8, 0u8); + let cycle = memory_write.cycle; + let base_addr = memory_write.address; + let source = memory_write.source; + + if let Some(se) = self + .to_rtl_queue + .iter_mut() + .find(|se| se.lsu_idx == source) + { + info!("[{cycle}] MemoryWrite: address={base_addr:08x}, size={}, data={data:?}, mask={mask:?}, pc = {:#x}, disasm = {}", data.len(), se.pc, se.disasm); + // compare with spike event record + for offset in 0..data.len() { + if mask[offset] { + let byte_addr = base_addr + offset as u32; + let data_byte = data[offset]; + let mem_write = se + .mem_access_record + .all_writes + .get_mut(&byte_addr) + .unwrap_or_else(|| { + panic!("[{cycle}] cannot find mem write of byte_addr {byte_addr:08x}") + }); + let single_mem_write_val = mem_write.writes[mem_write.num_completed_writes].val; + mem_write.num_completed_writes += 1; + assert_eq!(single_mem_write_val, data_byte, "[{cycle}] expect mem write of byte {single_mem_write_val:02X}, actual byte {data_byte:02X} (byte_addr={byte_addr:08X}, pc = {:#x}, disasm = {})", se.pc, se.disasm); + } + } + return Ok(()); + } + + panic!("[{cycle}] cannot find se with instruction source={source}") + } } diff --git a/difftest/t1-simulator/src/difftest/spike/spike_event.rs b/difftest/t1-simulator/src/difftest/spike/spike_event.rs index e027f9607..275890f46 100644 --- a/difftest/t1-simulator/src/difftest/spike/spike_event.rs +++ b/difftest/t1-simulator/src/difftest/spike/spike_event.rs @@ -371,24 +371,15 @@ impl SpikeEvent { } pub fn check_is_ready_for_commit(&self, cycle: usize) -> anyhow::Result<()> { - // for (addr, record) in &self.mem_access_record.all_writes { - // assert_eq!( - // record.num_completed_writes, - // record.writes.len(), - // "[{cycle}] expect to write mem {addr:#x}, not executed when commit (pc={:#x}, inst={})", - // self.pc, - // self.disasm - // ); - // } - // for (addr, record) in &self.mem_access_record.all_reads { - // assert_eq!( - // record.num_completed_reads, - // record.reads.len(), - // "[{cycle}] expect to read mem {addr:#x}, not executed when commit (pc={:#x}, inst={})", - // self.pc, - // self.disasm - // ); - // } + for (addr, record) in &self.mem_access_record.all_writes { + assert_eq!( + record.num_completed_writes, + record.writes.len(), + "[{cycle}] expect to write mem {addr:#x}, not executed when commit (pc={:#x}, inst={})", + self.pc, + self.disasm + ); + } for (idx, record) in &self.vrf_access_record.all_writes { assert!( record.executed, diff --git a/ipemu/src/TestBench.scala b/ipemu/src/TestBench.scala index 1cbcc26b4..1f515ff02 100644 --- a/ipemu/src/TestBench.scala +++ b/ipemu/src/TestBench.scala @@ -63,6 +63,9 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) extends wire } + val storeUnitProbe = lsuProbe.storeUnitProbe.suggestName("storeUnitProbe") + val otherUnitProbe = lsuProbe.otherUnitProbe.suggestName("otherUnitProbe") + val t1Probe = probe.read(dut.t1Probe) withClockAndReset(clock, reset) { @@ -70,16 +73,18 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) extends val cycleCounter = RegInit(0.U(64.W)) cycleCounter := cycleCounter + 1.U - // memory write - lsuProbe.slots.zipWithIndex.foreach { case (mshr, i) => when(mshr.writeValid)(printf(cf"""{"event":"vrfWriteFromLsu","parameter":{"idx":$i,"vd":${mshr.dataVd},"offset":${mshr.dataOffset},"mask":${mshr.dataMask},"data":${mshr.dataData},"instruction":${mshr.dataInstruction},"lane":${mshr.targetLane},"cycle": ${cycleCounter}}}\n""")) } - // vrf write - laneVrfProbes.zipWithIndex.foreach { case (lane, i) => when(lane.valid)(printf(cf"""{"event":"vrfWriteFromLane","parameter":{"idx":$i,"vd":${lane.requestVd},"offset":${lane.requestOffset},"mask":${lane.requestMask},"data":${lane.requestData},"instruction":${lane.requestInstruction},"cycle": ${cycleCounter}}}\n""")) } + // vrf write from lsu + lsuProbe.slots.zipWithIndex.foreach { case (mshr, i) => when(mshr.writeValid)(printf(cf"""{"event":"vrfWriteFromLsu","parameter":{"idx":$i,"vd":${mshr.dataVd},"offset":${mshr.dataOffset},"mask":"${mshr.dataMask}","data":"${mshr.dataData}","instruction":${mshr.dataInstruction},"lane":${mshr.targetLane},"cycle": ${cycleCounter}}}\n""")) } + // vrf write from lane + laneVrfProbes.zipWithIndex.foreach { case (lane, i) => when(lane.valid)(printf(cf"""{"event":"vrfWriteFromLane","parameter":{"idx":$i,"vd":${lane.requestVd},"offset":${lane.requestOffset},"mask":"${lane.requestMask}","data":"${lane.requestData}","instruction":${lane.requestInstruction},"cycle": ${cycleCounter}}}\n""")) } + // memory write from store unit + when(storeUnitProbe.valid)(printf(cf"""{"event":"memoryWrite","parameter":{"mask":"${storeUnitProbe.mask}","data":"${storeUnitProbe.data}","address":${storeUnitProbe.address},"source":${storeUnitProbe.index},"cycle": ${cycleCounter}}}\n""")) + // memory write from other unit + when(otherUnitProbe.valid)(printf(cf"""{"event":"memoryWrite","parameter":{"mask":"${otherUnitProbe.mask}","data":"${otherUnitProbe.data}","address":${otherUnitProbe.address},"source":${otherUnitProbe.index},"cycle": ${cycleCounter}}}\n""")) // issue when(dut.request.fire)(printf(cf"""{"event":"issue","parameter":{"idx":${t1Probe.instructionCounter},"cycle": ${cycleCounter}}}\n""")) // inst - when(dut.response.valid)(printf(cf"""{"event":"inst","parameter":{"data":${dut.response.bits.data},"vxsat":${dut.response.bits.vxsat},"rd_valid":${dut.response.bits.rd.valid},"rd":${dut.response.bits.rd.bits},"mem":${dut.response.bits.mem},"cycle": ${cycleCounter}}}\n""")) - // peekTL - dut.memoryPorts.zipWithIndex.foreach { case (bundle, i) => when(bundle.a.valid)(printf(cf"""{"event":"peekTL","parameter":{"idx":$i,"opcode":${bundle.a.bits.opcode},"param":${bundle.a.bits.param},"size":${bundle.a.bits.size},"source":${bundle.a.bits.source},"address":${bundle.a.bits.address},"mask":${bundle.a.bits.mask},"data":${bundle.a.bits.data},"corrupt":${bundle.a.bits.corrupt},"dready":${bundle.d.ready},"cycle": ${cycleCounter}}}\n""")) } + when(dut.response.valid)(printf(cf"""{"event":"inst","parameter":{"data":"${dut.response.bits.data}","vxsat":${dut.response.bits.vxsat},"rd_valid":${dut.response.bits.rd.valid},"rd":${dut.response.bits.rd.bits},"mem":${dut.response.bits.mem},"cycle": ${cycleCounter}}}\n""")) // lsu enq when(lsuProbe.reqEnq.orR)(printf(cf"""{"event":"lsuEnq","parameter":{"enq":${lsuProbe.reqEnq},"cycle": ${cycleCounter}}}\n""")) } diff --git a/t1/src/T1.scala b/t1/src/T1.scala index 197288639..322990b89 100644 --- a/t1/src/T1.scala +++ b/t1/src/T1.scala @@ -1546,7 +1546,7 @@ class T1(val parameter: T1Parameter) extends Module with SerializableModule[T1Pa omInstance.lanesIn := Property(laneVec.map(_.om.asAnyClassType)) - define(lsuProbe, lsu.probe) + define(lsuProbe, lsu._probe) dataInWritePipeVec := VecInit(laneVec.map(_.writeQueueValid)) diff --git a/t1/src/lsu/LSU.scala b/t1/src/lsu/LSU.scala index 7d0b6a2bb..0f133df8e 100644 --- a/t1/src/lsu/LSU.scala +++ b/t1/src/lsu/LSU.scala @@ -119,8 +119,18 @@ class LSUSlotProbe(param: LSUParameter) extends Bundle { val targetLane: UInt = UInt(param.laneNumber.W) } +class MemoryWriteProbe(param: MSHRParam) extends Bundle { + val valid: Bool = Bool() + val data: UInt = UInt((param.lsuTransposeSize * 8).W) + val mask: UInt = UInt(param.lsuTransposeSize.W) + val index: UInt = UInt(param.cacheLineIndexBits.W) + val address: UInt = UInt(param.paWidth.W) +} + class LSUProbe(param: LSUParameter) extends Bundle { val slots = Vec(param.laneNumber, new LSUSlotProbe(param)) + val storeUnitProbe = new MemoryWriteProbe(param.mshrParam) + val otherUnitProbe = new MemoryWriteProbe(param.mshrParam) val reqEnq: UInt = UInt(param.lsuMSHRSize.W) } @@ -270,9 +280,9 @@ class LSU(param: LSUParameter) extends Module { ) @public - val probe = IO(Output(Probe(new LSUProbe(param)))) + val _probe = IO(Output(Probe(new LSUProbe(param)))) val probeWire = Wire(new LSUProbe(param)) - define(probe, ProbeValue(probeWire)) + define(_probe, ProbeValue(probeWire)) // read vrf val otherTryReadVrf: UInt = Mux(otherUnit.vrfReadDataPorts.valid, otherUnit.status.targetLane, 0.U) @@ -311,6 +321,9 @@ class LSU(param: LSUParameter) extends Module { } probeWire.reqEnq := reqEnq.asUInt + probeWire.storeUnitProbe := probe.read(storeUnit.probe) + probeWire.otherUnitProbe := probe.read(otherUnit.probe) + vrfWritePort.zip(writeQueueVec).foreach { case (p, q) => p.valid := q.io.deq.valid p.bits := q.io.deq.bits.data diff --git a/t1/src/lsu/SimpleAccessUnit.scala b/t1/src/lsu/SimpleAccessUnit.scala index f36be6b0d..845a94d14 100644 --- a/t1/src/lsu/SimpleAccessUnit.scala +++ b/t1/src/lsu/SimpleAccessUnit.scala @@ -10,6 +10,7 @@ import chisel3.probe._ import chisel3.util.experimental.BitSet import org.chipsalliance.t1.rtl.{CSRInterface, LSUBankParameter, LSURequest, VRFReadRequest, VRFWriteRequest, ffo, firstlastHelper} import tilelink.{TLBundle, TLBundleParameter} +import org.chipsalliance.t1.rtl.lsu.MemoryWriteProbe /** * @param datapathWidth ELEN @@ -202,6 +203,12 @@ class SimpleAccessUnit(param: MSHRParam) extends Module with LSUPublic { @public val status: SimpleAccessStatus = IO(Output(new SimpleAccessStatus(param.laneNumber))) + // other unit probe + @public + val probe = IO(Output(Probe(new MemoryWriteProbe(param)))) + val probeWire = Wire(new MemoryWriteProbe(param)) + define(probe, ProbeValue(probeWire)) + val s0Fire: Bool = Wire(Bool()) val s1Fire: Bool = Wire(Bool()) val s2Fire: Bool = Wire(Bool()) @@ -1033,6 +1040,14 @@ class SimpleAccessUnit(param: MSHRParam) extends Module with LSUPublic { /** * probes for monitoring internal signal */ + val dataOffset = (s1EnqQueue.io.deq.bits.indexInMaskGroup << dataEEW)(1, 0) ## 0.U(3.W) + + probeWire.valid := s1EnqDataQueue.io.deq.fire + probeWire.index := 2.U + probeWire.data := s1EnqDataQueue.io.deq.bits >> dataOffset + probeWire.mask := dataEEWOH(2) ## dataEEWOH(2) ## !dataEEWOH(0) ## true.B + probeWire.address := s1EnqQueue.io.deq.bits.address + @public val lsuRequestValidProbe = IO(Output(Probe(Bool()))) define(lsuRequestValidProbe, ProbeValue(lsuRequest.valid)) diff --git a/t1/src/lsu/StoreUnit.scala b/t1/src/lsu/StoreUnit.scala index cb86bab54..fb3846d2d 100644 --- a/t1/src/lsu/StoreUnit.scala +++ b/t1/src/lsu/StoreUnit.scala @@ -9,6 +9,7 @@ import chisel3.util._ import chisel3.probe._ import org.chipsalliance.t1.rtl.{EmptyBundle, VRFReadRequest, cutUInt, multiShifter} import tilelink.TLChannelA +import org.chipsalliance.t1.rtl.lsu.MemoryWriteProbe class cacheLineEnqueueBundle(param: MSHRParam) extends Bundle { val data: UInt = UInt((param.lsuTransposeSize * 8).W) @@ -43,6 +44,12 @@ class StoreUnit(param: MSHRParam) extends StrideBase(param) with LSUPublic { @public val vrfReadyToStore: Bool = IO(Input(Bool())) + // store unit probe + @public + val probe = IO(Output(Probe(new MemoryWriteProbe(param)))) + val probeWire = Wire(new MemoryWriteProbe(param)) + define(probe, ProbeValue(probeWire)) + // stage 0, 处理 vl, mask ... val dataGroupByteSize: Int = param.datapathWidth * param.laneNumber / 8 val dataByteSize: UInt = (csrInterface.vl << lsuRequest.bits.instructionInformation.eew).asUInt @@ -285,6 +292,7 @@ class StoreUnit(param: MSHRParam) extends StrideBase(param) with LSUPublic { port.bits.data := dataToSend.bits.data(param.tlParam.a.dataWidth - 1, 0) port.bits.corrupt := false.B sendStageReady(portIndex) := enqueueReady + !dataToSend.valid } @@ -304,6 +312,12 @@ class StoreUnit(param: MSHRParam) extends StrideBase(param) with LSUPublic { /** * Probes */ + probeWire.valid := alignedDequeueFire + probeWire.index := 1.U + probeWire.data := alignedDequeue.bits.data + probeWire.mask := alignedDequeue.bits.mask + probeWire.address := alignedDequeueAddress + // Store Unit is idle @public val idleProbe = IO(Output(Probe(Bool())))