From eaf9627aa3ac1b94a4b1a86fbff188e0615e4ba6 Mon Sep 17 00:00:00 2001 From: Clo91eaf Date: Fri, 31 May 2024 02:52:30 +0800 Subject: [PATCH] [difftest] fix wrong tl_req_ongoing_burst update --- difftest/t1-simulator/src/difftest.rs | 4 +- difftest/t1-simulator/src/difftest/dut.rs | 6 +- difftest/t1-simulator/src/difftest/spike.rs | 190 ++++++++++++-------- ipemu/src/TestBench.scala | 2 +- 4 files changed, 122 insertions(+), 80 deletions(-) diff --git a/difftest/t1-simulator/src/difftest.rs b/difftest/t1-simulator/src/difftest.rs index 03aaa8df86..29de37511f 100644 --- a/difftest/t1-simulator/src/difftest.rs +++ b/difftest/t1-simulator/src/difftest.rs @@ -93,7 +93,7 @@ impl Difftest { let mask = event.parameter.mask.unwrap(); let data = event.parameter.data.unwrap(); let corrupt = event.parameter.corrupt.unwrap(); - let dready = event.parameter.dready.unwrap(); + let dready = event.parameter.dready.unwrap() != 0; let cycle = event.parameter.cycle.unwrap(); // check align let addr = event.parameter.address.unwrap(); @@ -107,7 +107,7 @@ impl Difftest { let opcode = Opcode::from_u32(opcode); self .spike - .peek_tl(PeekTLEvent { + .peek_tl(&PeekTLEvent { idx, opcode, param, diff --git a/difftest/t1-simulator/src/difftest/dut.rs b/difftest/t1-simulator/src/difftest/dut.rs index 06a82579c6..d7a845a74a 100644 --- a/difftest/t1-simulator/src/difftest/dut.rs +++ b/difftest/t1-simulator/src/difftest/dut.rs @@ -2,7 +2,7 @@ use serde::Deserialize; use std::io::BufRead; use std::path::Path; -#[derive(Deserialize, Debug, PartialEq)] +#[derive(Deserialize, Debug, PartialEq, Clone)] pub enum Opcode { PutFullData = 0, PutPartialData = 1, @@ -34,7 +34,7 @@ pub struct Parameter { pub mask: Option, pub data: Option, pub corrupt: Option, - pub dready: Option, + pub dready: Option, pub vd: Option, pub offset: Option, pub instruction: Option, @@ -73,7 +73,7 @@ pub struct PeekTLEvent { pub mask: u32, pub data: u32, pub corrupt: u32, - pub dready: u32, + pub dready: bool, pub cycle: usize, } diff --git a/difftest/t1-simulator/src/difftest/spike.rs b/difftest/t1-simulator/src/difftest/spike.rs index 1ff5c74382..cdb474c0d2 100644 --- a/difftest/t1-simulator/src/difftest/spike.rs +++ b/difftest/t1-simulator/src/difftest/spike.rs @@ -21,6 +21,7 @@ use super::dut::*; const MSHR: usize = 3; const LSU_IDX_DEFAULT: u8 = 0xff; +const DATAPATH_WIDTH_IN_BYTES: usize = 8; // 8 = config.datapath_width_in_bytes = beatbyte = lsuBankParameters(0).beatbyte for blastoise // read the addr from spike memory // caller should make sure the address is valid @@ -156,6 +157,7 @@ pub fn add_rtl_write(se: &mut SpikeEvent, vrf_write: VrfWriteEvent, record_idx_b }) // end for j } +#[derive(Debug, Clone)] pub struct TLReqRecord { data: Vec, cycle: usize, @@ -223,6 +225,23 @@ impl TLReqRecord { }; self.bytes_processed = self.bytes_committed; } + + fn commit_tl_respones(&mut self, tl_bytes: usize) -> anyhow::Result<()> { + self.bytes_returned += tl_bytes; + + Ok(()) + } + + fn done_return(&mut self) -> anyhow::Result { + if self.muxin_read_required { + return Ok(false); + } + if self.op == Opcode::PutFullData { + return Ok(self.bytes_returned > 0); + } else { + return Ok(self.bytes_returned >= self.size_by_byte); + } + } } pub struct SpikeHandle { @@ -480,14 +499,57 @@ impl SpikeHandle { Ok(()) } + pub fn peek_tl(&mut self, peek_tl: &PeekTLEvent) -> anyhow::Result<()> { + // config.tl_bank_number + assert!(peek_tl.idx < 13); + self.receive_tl_d_ready(peek_tl).unwrap(); + self.receive_tl_req(peek_tl).unwrap(); + Ok(()) + } + + pub fn receive_tl_d_ready(&mut self, peek_tl: &PeekTLEvent) -> anyhow::Result<()> { + let idx = peek_tl.idx as usize; + if !peek_tl.dready { + return Ok(()); + } + + if let Some(addr) = self.tl_req_waiting_ready[idx] { + let req_record = self.tl_req_record_of_bank[idx] + .get_mut(&addr) + .expect(&format!( + "cannot find current request with addr {:08X}", + addr + )); + + req_record + .commit_tl_respones(DATAPATH_WIDTH_IN_BYTES) + .unwrap(); + + if req_record.done_return().unwrap() { + info!( + "ReceiveTlDReady channel: {idx}, addr: {addr:08x}, -> tl response for {} reaches d_ready", + match req_record.op { + Opcode::Get => "Get", + _ => "PutFullData", + } + ); + } + + self.tl_req_waiting_ready[idx] = None; + + // TODO(Meow): add this check back + // panic!(format!("unknown opcode {}", req_record.op as i32)); + } + Ok(()) + } // the info in peek tl should have cycle to debug - pub fn peek_tl(&mut self, peek_tl: PeekTLEvent) -> anyhow::Result<()> { - let tl_idx = peek_tl.idx as usize; + pub fn receive_tl_req(&mut self, peek_tl: &PeekTLEvent) -> anyhow::Result<()> { + let idx = peek_tl.idx as usize; let tl_data = peek_tl.data; - let tl_mask = peek_tl.mask; - let tl_cycle = peek_tl.cycle as usize; - let tl_size = peek_tl.size; - let tl_source = peek_tl.source; + let mask = peek_tl.mask; + let cycle = peek_tl.cycle as usize; + let size = peek_tl.size; + let source = peek_tl.source; let base_addr = peek_tl.addr; let lsu_idx = (peek_tl.source & 3) as u8; if let Some(se) = self @@ -497,8 +559,8 @@ impl SpikeHandle { { match peek_tl.opcode { Opcode::Get => { - let mut actual_data = vec![0u8; tl_size]; - for offset in 0..tl_size { + let mut actual_data = vec![0u8; size]; + for offset in 0..size { let addr = base_addr + offset as u32; match se.mem_access_record.all_reads.get_mut(&addr) { Some(mem_read) => { @@ -507,7 +569,7 @@ impl SpikeHandle { } None => { // TODO: check if the cache line should be accessed - warn!("[{tl_cycle}] ReceiveTLReq addr: {addr:08X} insn: {} send falsy data 0xDE for accessing unexpected memory", format!("{:x}", se.inst_bits)); + warn!("[{cycle}] ReceiveTLReq addr: {addr:08X} insn: {} send falsy data 0xDE for accessing unexpected memory", format!("{:x}", se.inst_bits)); actual_data[offset as usize] = 0xDE; // falsy data } } @@ -516,31 +578,25 @@ impl SpikeHandle { let hex_actual_data = actual_data .iter() .fold(String::new(), |acc, x| acc + &format!("{:02X} ", x)); - info!("[{tl_cycle}] SpikeReceiveTLReq: <- receive rtl mem get req: channel={tl_idx}, base_addr={base_addr:08X}, size={tl_size}, mask={tl_mask:b}, source={tl_source}, return_data={hex_actual_data}"); + info!("[{cycle}] SpikeReceiveTLReq: <- receive rtl mem get req: channel={idx}, base_addr={base_addr:08X}, size={size}, mask={mask:b}, source={source}, return_data={hex_actual_data}"); - self - .tl_req_record_of_bank - .get_mut(tl_idx as usize) - .unwrap() - .insert( - tl_cycle, - TLReqRecord::new( - se, - tl_cycle, - actual_data, - tl_size, - base_addr, - tl_source, - Opcode::Get, - 1, - ), - ); + trace!("get tl_req_record_of_bank[{idx}] insert [{cycle}]"); + self.tl_req_record_of_bank[idx].insert( + cycle, + TLReqRecord::new( + se, + cycle, + actual_data, + size, + base_addr, + source, + Opcode::Get, + 1, + ), + ); - self - .tl_req_record_of_bank - .get_mut(tl_idx) - .unwrap() - .get_mut(&tl_cycle) + self.tl_req_record_of_bank[idx] + .get_mut(&cycle) .unwrap() .skip(); } @@ -549,26 +605,19 @@ impl SpikeHandle { let mut cur_record: Option<&mut TLReqRecord> = None; // determine if it is a beat of ongoing burst // the first Some match the result of get, the second Some match the result determined by if the - // tl_req_ongoing_burst[tl_idx] is Some / None - if let Some(Some(tl_req_ongoing_burst)) = self.tl_req_ongoing_burst.get(tl_idx) { - if let Some(record) = self - .tl_req_record_of_bank - .get_mut(tl_idx) - .unwrap() - .get_mut(tl_req_ongoing_burst) - { - assert!( - record.bytes_received < record.size_by_byte, - "[{tl_cycle}] invalid record" - ); + // tl_req_ongoing_burst[idx] is Some / None + if let Some(tl_req_ongoing_burst) = self.tl_req_ongoing_burst[idx] { + if let Some(record) = self.tl_req_record_of_bank[idx].get_mut(&tl_req_ongoing_burst) { if record.bytes_received < record.size_by_byte { assert_eq!(record.addr, base_addr, "inconsistent burst addr"); - assert_eq!(record.size_by_byte, tl_size, "inconsistent burst size"); + assert_eq!(record.size_by_byte, size, "inconsistent burst size"); info!( - "[{tl_cycle}] ReceiveTLReq: continue burst, channel: {tl_idx}, base_addr: {base_addr:08X}, offset: {}", + "[{cycle}] ReceiveTLReq: continue burst, channel: {idx}, base_addr: {base_addr:08X}, offset: {}", record.bytes_received ); cur_record = Some(record); + } else { + panic!("[{cycle}] invalid record") } } } @@ -579,46 +628,39 @@ impl SpikeHandle { // here we do not use dramsim3. let record = TLReqRecord::new( se, - tl_cycle, - vec![0; tl_size], - tl_size, + cycle, + vec![0; size], + size, base_addr, - tl_source, + source, Opcode::PutFullData, 1, ); - self - .tl_req_record_of_bank - .get_mut(tl_idx) - .unwrap() - .insert(tl_cycle, record); + trace!("put full is none: get tl_req_record_of_bank[{idx}] insert [{cycle}]"); + self.tl_req_record_of_bank[idx].insert(cycle, record); // record moved into self.tl_req_record_of_bank, so we should get it from there - cur_record = self - .tl_req_record_of_bank - .get_mut(tl_idx) - .unwrap() - .get_mut(&tl_cycle); + cur_record = self.tl_req_record_of_bank[idx].get_mut(&cycle); } - let mut data = vec![0u8; tl_size]; - // datapath_width_in_bytes = 32(datapath_width) / 8(bit / byte) - let actual_beat_size = std::cmp::min(tl_size, 4); // since tl require alignment + let mut data = vec![0u8; size]; + let actual_beat_size = std::cmp::min(size, DATAPATH_WIDTH_IN_BYTES); // since tl require alignment let data_begin_pos = cur_record.as_ref().unwrap().bytes_received; // receive put data - // if actual beat size is bigger than 4, there maybe some problems + // if actual beat size is bigger than 8, there maybe some problems // TODO: fix this for offset in 0..actual_beat_size { data[data_begin_pos + offset] = (tl_data >> (offset * 8)) as u8; } - info!("[{tl_cycle}] RTLMemPutReq: <- receive rtl mem put req, channel: {tl_idx}, base_addr: {base_addr:08X}, offset: {data_begin_pos}, size: {tl_size}, source: {tl_source:04X}, data: {tl_data:08X}, mask: {tl_mask:04X}"); + info!("[{cycle}] RTLMemPutReq: <- receive rtl mem put req, channel: {idx}, base_addr: {base_addr:08X}, offset: {data_begin_pos}, size: {size}, source: {source:04X}, data: {tl_data:08X}, mask: {mask:04X}"); // compare with spike event record for offset in 0..actual_beat_size { // config.datapath_width_in_bytes - 1 = 3 let byte_lane_idx = (base_addr & 3) + offset as u32; - if tl_mask >> byte_lane_idx & 1 != 0 { + // if byte_lane_idx > 32, there maybe some problem + if (mask >> byte_lane_idx) & 1 != 0 { let byte_addr = base_addr + cur_record.as_ref().unwrap().bytes_received as u32 + offset as u32; let tl_data_byte = (tl_data >> 8 * byte_lane_idx) as u8; @@ -627,15 +669,17 @@ impl SpikeHandle { .all_writes .get_mut(&byte_addr) .expect(&format!( - "[{tl_cycle}] cannot find mem write of byte_addr {tl_cycle:08X}" + "[{cycle}] cannot find mem write of byte_addr {byte_addr:08x}" )); assert!( mem_write.num_completed_writes < mem_write.writes.len(), - "[{tl_cycle}] written size should be smaller than completed writes" + "[{cycle}] written size:{} should be smaller than completed writes:{}", + mem_write.writes.len(), + mem_write.num_completed_writes ); 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, tl_data_byte, "[{tl_cycle}] expect mem write of byte {single_mem_write_val:02X}, actual byte {tl_data_byte:02X} (channel={tl_idx}, byte_addr={byte_addr:08X}, pc = {:#x}, disasm = {})", se.pc, se.disasm); + assert_eq!(single_mem_write_val, tl_data_byte, "[{cycle}] expect mem write of byte {single_mem_write_val:02X}, actual byte {tl_data_byte:02X} (channel={idx}, byte_addr={byte_addr:08X}, pc = {:#x}, disasm = {})", se.pc, se.disasm); } } @@ -643,12 +687,10 @@ impl SpikeHandle { cur_record.as_mut().unwrap().skip(); // update tl_req_ongoing_burst - if cur_record.as_ref().unwrap().bytes_received < tl_size { - self - .tl_req_ongoing_burst - .insert(tl_idx, Some(cur_record.as_ref().unwrap().cycle)); + if cur_record.as_ref().unwrap().bytes_received < size { + self.tl_req_ongoing_burst[idx] = Some(cur_record.as_ref().unwrap().cycle); } else { - self.tl_req_ongoing_burst.remove(tl_idx); + self.tl_req_ongoing_burst.remove(idx); } } _ => { diff --git a/ipemu/src/TestBench.scala b/ipemu/src/TestBench.scala index 07649af228..d158fc617b 100644 --- a/ipemu/src/TestBench.scala +++ b/ipemu/src/TestBench.scala @@ -50,7 +50,7 @@ class TestBench(generator: SerializableModuleGenerator[T1, T1Parameter]) extends withClockAndReset(clock, reset) { // count cycle for peek tl - val cycleCounter = RegInit(0.U(64.W)) + val cycleCounter = RegInit(0.U(32.W)) cycleCounter := cycleCounter + 1.U // memory write