diff --git a/difftest/t1-simulator/src/difftest/dut.rs b/difftest/t1-simulator/src/difftest/dut.rs index 50706af5f..bd80384f0 100644 --- a/difftest/t1-simulator/src/difftest/dut.rs +++ b/difftest/t1-simulator/src/difftest/dut.rs @@ -122,6 +122,6 @@ impl Dut { }; self.idx += 1; - return Ok(event); + Ok(event) } } diff --git a/difftest/t1-simulator/src/difftest/spike.rs b/difftest/t1-simulator/src/difftest/spike.rs index 0fd2b9fcd..20fb2cab3 100644 --- a/difftest/t1-simulator/src/difftest/spike.rs +++ b/difftest/t1-simulator/src/difftest/spike.rs @@ -19,7 +19,6 @@ use spike_event::*; 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 @@ -89,18 +88,15 @@ fn load_elf(fname: &Path) -> anyhow::Result { assert_eq!(header.pt1.class(), header::Class::ThirtyTwo); for ph in elf_file.program_iter() { - match ph { - ProgramHeader::Ph32(ph) => { - if ph.get_type() == Ok(Type::Load) { - let offset = ph.offset as usize; - let size = ph.file_size as usize; - let addr = ph.virtual_addr as usize; - - let slice = &buffer[offset..offset + size]; - ld(addr, size, slice.to_vec()).unwrap(); - } + if let ProgramHeader::Ph32(ph) = ph { + if ph.get_type() == Ok(Type::Load) { + let offset = ph.offset as usize; + let size = ph.file_size as usize; + let addr = ph.virtual_addr as usize; + + let slice = &buffer[offset..offset + size]; + ld(addr, size, slice.to_vec()).unwrap(); } - _ => (), } } @@ -134,11 +130,11 @@ pub fn add_rtl_write(se: &mut SpikeEvent, vrf_write: VrfWriteEvent, record_idx_b if let Some(record) = record_iter { assert_eq!( - (record.byte as u8), - (written_byte as u8), + record.byte, + written_byte, "{j}th byte incorrect ({:02X} != {written_byte:02X}) for vrf \ write (lane={}, vd={}, offset={}, mask={:04b}) \ - [vrf_idx={}] (lsu_idx={}, {})", + [vrf_idx={}] (lsu_idx={}, disasm: {}, pc: {:#x}, bits: {:#x})", record.byte, vrf_write.idx, vrf_write.vd, @@ -146,10 +142,9 @@ pub fn add_rtl_write(se: &mut SpikeEvent, vrf_write: VrfWriteEvent, record_idx_b vrf_write.mask, record_idx_base + j, se.lsu_idx, - format!( - "disasm: {}, pc: {:#x}, bits: {:#x}", - se.disasm, se.pc, se.inst_bits - ) + se.disasm, + se.pc, + se.inst_bits ); record.executed = true; } @@ -159,16 +154,11 @@ pub fn add_rtl_write(se: &mut SpikeEvent, vrf_write: VrfWriteEvent, record_idx_b #[derive(Debug, Clone)] pub struct TLReqRecord { - data: Vec, cycle: usize, size_by_byte: usize, addr: u32, - source: u16, muxin_read_required: bool, - muxin_read_sent: bool, - - se: SpikeEvent, // For writes, as soon as the transaction is sent to the controller, the request is resolved, so we don't have to track the number // of bytes that have been processed by the memory controller @@ -189,25 +179,12 @@ pub struct TLReqRecord { } impl TLReqRecord { - pub fn new( - se: &SpikeEvent, - cycle: usize, - data: Vec, - size_by_byte: usize, - addr: u32, - source: u16, - op: Opcode, - burst_size: usize, - ) -> Self { + pub fn new(cycle: usize, size_by_byte: usize, addr: u32, op: Opcode, burst_size: usize) -> Self { TLReqRecord { - data, cycle, size_by_byte, addr, - source, muxin_read_required: op == Opcode::PutFullData && size_by_byte < burst_size, - muxin_read_sent: false, - se: se.clone(), bytes_received: 0, bytes_committed: 0, bytes_processed: 0, @@ -237,9 +214,9 @@ impl TLReqRecord { return Ok(false); } if self.op == Opcode::PutFullData { - return Ok(self.bytes_returned > 0); + Ok(self.bytes_returned > 0) } else { - return Ok(self.bytes_returned >= self.size_by_byte); + Ok(self.bytes_returned >= self.size_by_byte) } } } @@ -513,10 +490,7 @@ impl SpikeHandle { 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 - )); + .unwrap_or_else(|| panic!("cannot find current request with addr {addr:08X}")); req_record .commit_tl_respones(DATAPATH_WIDTH_IN_BYTES) @@ -544,7 +518,7 @@ impl SpikeHandle { let idx = peek_tl.idx as usize; let tl_data = peek_tl.data; let mask = peek_tl.mask; - let cycle = peek_tl.cycle as usize; + let cycle = peek_tl.cycle; let size = peek_tl.size; let source = peek_tl.source; let base_addr = peek_tl.addr; @@ -557,17 +531,16 @@ impl SpikeHandle { match peek_tl.opcode { Opcode::Get => { let mut actual_data = vec![0u8; size]; - for offset in 0..size { + for (offset, actual) in actual_data.iter_mut().enumerate().take(size) { let addr = base_addr + offset as u32; match se.mem_access_record.all_reads.get_mut(&addr) { Some(mem_read) => { - actual_data[offset] = mem_read.reads[mem_read.num_completed_reads].val; + *actual = mem_read.reads[mem_read.num_completed_reads].val; mem_read.num_completed_reads += 1; } None => { - // TODO: check if the cache line should be accessed 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 + *actual = 0xDE; // falsy data } } } @@ -579,16 +552,7 @@ impl SpikeHandle { self.tl_req_record_of_bank[idx].insert( cycle, - TLReqRecord::new( - se, - cycle, - actual_data, - size, - base_addr, - source, - Opcode::Get, - 1, - ), + TLReqRecord::new(cycle, size, base_addr, Opcode::Get, 1), ); self.tl_req_record_of_bank[idx] @@ -622,16 +586,7 @@ impl SpikeHandle { if cur_record.is_none() { // 1 is dummy value, won't be effective whatsoever. 1 is to ensure that no sub-line write is possible // here we do not use dramsim3. - let record = TLReqRecord::new( - se, - cycle, - vec![0; size], - size, - base_addr, - source, - Opcode::PutFullData, - 1, - ); + let record = TLReqRecord::new(cycle, size, base_addr, Opcode::PutFullData, 1); 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 @@ -658,14 +613,14 @@ impl SpikeHandle { 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; + let tl_data_byte = (tl_data >> (8 * byte_lane_idx)) as u8; let mem_write = se .mem_access_record .all_writes .get_mut(&byte_addr) - .expect(&format!( - "[{cycle}] cannot find mem write of byte_addr {byte_addr:08x}" - )); + .unwrap_or_else(|| { + panic!("[{cycle}] cannot find mem write of byte_addr {byte_addr:08x}") + }); assert!( mem_write.num_completed_writes < mem_write.writes.len(), "[{cycle}] written size:{} should be smaller than completed writes:{}", diff --git a/difftest/t1-simulator/src/difftest/spike/libspike_interfaces.rs b/difftest/t1-simulator/src/difftest/spike/libspike_interfaces.rs index ea6df0d5e..9bbf0b420 100644 --- a/difftest/t1-simulator/src/difftest/spike/libspike_interfaces.rs +++ b/difftest/t1-simulator/src/difftest/spike/libspike_interfaces.rs @@ -15,7 +15,7 @@ impl Spike { } pub fn get_proc(&self) -> Processor { - let processor = unsafe { spike_get_proc(self.spike as *mut ()) }; + let processor = unsafe { spike_get_proc(self.spike) }; Processor { processor } } } diff --git a/difftest/t1-simulator/src/difftest/spike/spike_event.rs b/difftest/t1-simulator/src/difftest/spike/spike_event.rs index ba3ee5daa..1eaa55af5 100644 --- a/difftest/t1-simulator/src/difftest/spike/spike_event.rs +++ b/difftest/t1-simulator/src/difftest/spike/spike_event.rs @@ -100,61 +100,66 @@ pub struct SpikeEvent { impl SpikeEvent { pub fn new(spike: &Spike) -> Option { - let mut se = SpikeEvent::default(); - // se default value - se.lsu_idx = 255; - se.issue_idx = 255; - + let inst_bits = spike.get_proc().get_insn(); // inst info - se.inst_bits = spike.get_proc().get_insn(); - let opcode = clip(se.inst_bits, 0, 6); - let width = clip(se.inst_bits, 12, 14); // also funct3 - let funct6 = clip(se.inst_bits, 26, 31); - let mop = clip(se.inst_bits, 26, 27); - let lumop = clip(se.inst_bits, 20, 24); - let vm = clip(se.inst_bits, 25, 25); - - // rs1 + let opcode = clip(inst_bits, 0, 6); + let width = clip(inst_bits, 12, 14); // also funct3 + let funct6 = clip(inst_bits, 26, 31); + let mop = clip(inst_bits, 26, 27); + let lumop = clip(inst_bits, 20, 24); + let vm = clip(inst_bits, 25, 25); + + // rs1, rs2 let is_rs_fp = opcode == 0b1010111 && width == 0b101/* OPFVF */; let proc = spike.get_proc(); let state = proc.get_state(); let (rs1, rs2) = (proc.get_rs1(), proc.get_rs2()); - se.rs1_bits = state.get_reg(rs1, is_rs_fp); - se.rs2_bits = state.get_reg(rs2, is_rs_fp); - - // rd - se.is_rd_fp = - (opcode == 0b1010111) && (rs1 == 0) && (funct6 == 0b010000) && (vm == 1) && (width == 0b001); - se.rd_idx = proc.get_rd(); - se.is_rd_written = false; // vtype let vtype = proc.vu_get_vtype(); - se.vlmul = clip(vtype, 0, 2); - se.vma = clip(vtype, 7, 7) != 0; - se.vta = clip(vtype, 6, 6) != 0; - se.vsew = clip(vtype, 3, 5); - se.vxrm = proc.vu_get_vxrm(); - se.vnf = proc.vu_get_vnf(); - - se.vill = proc.vu_get_vill(); - se.vxsat = proc.vu_get_vxsat(); - se.vl = proc.vu_get_vl(); - se.vstart = proc.vu_get_vstart(); - - // se info - se.disasm = spike.get_proc().disassemble(); - se.pc = proc.get_state().get_pc(); - se.is_load = opcode == 0b0000111; - se.is_store = opcode == 0b0100111; - se.is_whole = mop == 0 && lumop == 8; - se.is_widening = opcode == 0b1010111 && (funct6 >> 4) == 0b11; - se.is_mask_vd = opcode == 0b1010111 && (funct6 >> 3 == 0b011 || funct6 == 0b010001); - se.is_exit_insn = opcode == 0b1110011; - se.is_vfence_insn = false; - - se.is_issued = false; - Some(se) + + Some(SpikeEvent { + lsu_idx: 255, + issue_idx: 255, + inst_bits, + rs1_bits: state.get_reg(rs1, is_rs_fp), + rs2_bits: state.get_reg(rs2, is_rs_fp), + // rd + is_rd_fp: (opcode == 0b1010111) + && (rs1 == 0) + && (funct6 == 0b010000) + && (vm == 1) + && (width == 0b001), + rd_idx: proc.get_rd(), + is_rd_written: false, + + // vtype + vlmul: clip(vtype, 0, 2), + vma: clip(vtype, 7, 7) != 0, + vta: clip(vtype, 6, 6) != 0, + vsew: clip(vtype, 3, 5), + vxrm: proc.vu_get_vxrm(), + vnf: proc.vu_get_vnf(), + + vill: proc.vu_get_vill(), + vxsat: proc.vu_get_vxsat(), + vl: proc.vu_get_vl(), + vstart: proc.vu_get_vstart(), + + // se info + disasm: spike.get_proc().disassemble(), + pc: proc.get_state().get_pc(), + is_load: opcode == 0b0000111, + is_store: opcode == 0b0100111, + is_whole: mop == 0 && lumop == 8, + is_widening: opcode == 0b1010111 && (funct6 >> 4) == 0b11, + is_mask_vd: opcode == 0b1010111 && (funct6 >> 3 == 0b011 || funct6 == 0b010001), + is_exit_insn: opcode == 0b1110011, + is_vfence_insn: false, + + is_issued: false, + ..Default::default() + }) } pub fn get_vrf_write_range(&self, vlen_in_bytes: u32) -> anyhow::Result<(u32, u32)> { @@ -170,7 +175,7 @@ impl SpikeEvent { let len = if self.vlmul & 0b100 != 0 { vlen_in_bytes * (1 + self.vnf) } else { - vlen_in_bytes * (1 + self.vnf) << self.vlmul + (vlen_in_bytes * (1 + self.vnf)) << self.vlmul }; return Ok((vd_bytes_start, len)); } @@ -187,7 +192,7 @@ impl SpikeEvent { vlen_in_bytes << self.vlmul }; - return Ok((vd_bytes_start, if self.is_widening { len * 2 } else { len })); + Ok((vd_bytes_start, if self.is_widening { len * 2 } else { len })) } pub fn pre_log_arch_changes(&mut self, spike: &Spike, vlen: u32) -> anyhow::Result<()> { @@ -284,7 +289,6 @@ impl SpikeEvent { self.rd_bits = data; self.is_rd_written = true; } - } _ => trace!("UnknownRegChange, idx={idx}, spike detect unknown reg change"), }); @@ -310,7 +314,7 @@ impl SpikeEvent { }) .writes .push(SingleMemWrite { - val: (value >> offset * 8) as u8, + val: (value >> (offset * 8)) as u8, executed: false, }); }); @@ -370,23 +374,25 @@ impl SpikeEvent { assert_eq!( record.num_completed_writes, record.writes.len(), - "[{cycle}] expect to write mem {addr:#x}, not executed when commit ({})", - format!("pc={:#x}, inst={}", self.pc, self.disasm) + "[{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 ({})", - format!("pc={:#x}, inst={}", self.pc, self.disasm) + "[{cycle}] expect to read 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, - "[{cycle}] expect to write vrf {idx}, not executed when commit ({})", - format!("pc={:#x}, inst={}", self.pc, self.disasm) + "[{cycle}] expect to write vrf {idx}, not executed when commit (pc={:#x}, inst={})", + self.pc, self.disasm ); } diff --git a/difftest/t1-simulator/src/main.rs b/difftest/t1-simulator/src/main.rs index 106b74bb0..86c9bd03c 100644 --- a/difftest/t1-simulator/src/main.rs +++ b/difftest/t1-simulator/src/main.rs @@ -20,7 +20,7 @@ struct Args { log_file: Option, /// Log level: trace, debug, info, warn, error - #[arg(short, long, default_value = "trace")] + #[arg(short, long, default_value = "info")] log_level: String, /// vlen config (default blastoise 512)