From 654141fb1a5806f36e61875092ec27c751468df7 Mon Sep 17 00:00:00 2001 From: Paul Scheffler Date: Thu, 23 Nov 2023 14:39:06 +0100 Subject: [PATCH] Add TCDM alias feature --- src/configuration.rs | 4 ++++ src/engine.rs | 39 +++++++++++++++++++++++++++++++++++ src/tran.rs | 49 +++++++++++++++++++++++++++++--------------- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/configuration.rs b/src/configuration.rs index 9047651..a423d4a 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -116,6 +116,8 @@ pub struct Memories { pub tcdm: Memory, pub dram: Memory, pub periphs: MemoryCallback, + pub tcdm_alias: bool, + pub tcdm_alias_start: u32, } impl Default for Memories { @@ -140,6 +142,8 @@ impl Default for Memories { latency: 2, callbacks: vec![], }, + tcdm_alias: false, + tcdm_alias_start: 0, } } } diff --git a/src/engine.rs b/src/engine.rs index 08b7f19..cc2969c 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -747,6 +747,23 @@ impl<'a, 'b> Cpu<'a, 'b> { } // cluster_base_hartid x if x == self.engine.config.address.cluster_num => self.engine.num_clusters as u32, // cluster_num x if x == self.engine.config.address.cluster_id => self.cluster_id as u32, // cluster_id + // TCDM alias + x if (self.engine.config.memory.tcdm_alias + && x >= self.engine.config.memory.tcdm_alias_start + && x < (self.engine.config.memory.tcdm_alias_start + + self.engine.config.memory.tcdm.size)) => + { + debug!("TCDM Alias Binary Load"); + debug!("Binary load address: 0x{:x}", x); + let tcdm_addr = addr + - (self.engine.config.memory.tcdm.start + + self.engine.config.memory.tcdm.offset * self.cluster_id as u32); + let word_addr = tcdm_addr / 4; + let word_offs = tcdm_addr - 4 * word_addr; + let ptr: *const u32 = self.tcdm_ptr[self.cluster_id]; + let word = unsafe { *ptr.offset(word_addr as isize) }; + (word >> (8 * word_offs)) & ((((1 as u64) << (8 << size)) - 1) as u32) + } // TCDM x if (0..self.engine.num_clusters).any(|i| { x >= (self.engine.config.memory.tcdm.start @@ -887,6 +904,28 @@ impl<'a, 'b> Cpu<'a, 'b> { buffer.push(value as u8); } } + // TCDM alias + x if (self.engine.config.memory.tcdm_alias + && x >= self.engine.config.memory.tcdm_alias_start + && x < (self.engine.config.memory.tcdm_alias_start + + self.engine.config.memory.tcdm.size)) => + { + debug!("TCDM Alias Binary Store"); + debug!("Binary store address: 0x{:x}", x); + let tcdm_addr = addr + - (self.engine.config.memory.tcdm.start + + self.engine.config.memory.tcdm.offset * self.cluster_id as u32); + let word_addr = tcdm_addr / 4; + let word_offs = tcdm_addr - 4 * word_addr; + let ptr = self.tcdm_ptr[self.cluster_id] as *const u32; + let ptr_mut = ptr as *mut u32; + let wmask = ((((1 as u64) << (8 << size)) - 1) as u32) << (8 * word_offs); + unsafe { + let word_ptr = ptr_mut.offset(word_addr as isize); + let word = *word_ptr; + *word_ptr = (word & !wmask) | ((value << (8 * word_offs)) & wmask); + } + } // TCDM // TODO: this is *not* thread-safe and *will* lead to undefined behavior on simultaneous access // by 2 harts. However, changing `tcdm_ptr` to a locked structure would require pervasive redesign. diff --git a/src/tran.rs b/src/tran.rs index 866b9d9..9fd5828 100644 --- a/src/tran.rs +++ b/src/tran.rs @@ -150,6 +150,12 @@ pub struct ElfTranslator<'a> { pub tcdm_start: u32, /// End address of the fast local scratchpad. pub tcdm_end: u32, + /// Whether a fast local scratchpad alias exists. + pub tcdm_alias: bool, + /// Start address of the fast local scratchpad alias. + pub tcdm_alias_start: u32, + /// End address of the fast local scratchpad alias. + pub tcdm_alias_end: u32, /// External TCDM range (Cluster id, start, end) pub tcdm_range: Vec<(u32, u32, u32)>, /// Cluster ID @@ -229,6 +235,10 @@ impl<'a> ElfTranslator<'a> { tcdm_end: engine.config.memory.tcdm.start + engine.config.memory.tcdm.offset * cluster_id as u32 + engine.config.memory.tcdm.size, + tcdm_alias: engine.config.memory.tcdm_alias, + tcdm_alias_start: engine.config.memory.tcdm_alias_start, + tcdm_alias_end: engine.config.memory.tcdm_alias_start + + engine.config.memory.tcdm.size, tcdm_range, cluster_id, } @@ -1107,9 +1117,9 @@ impl<'a> InstructionTranslator<'a> { let mut values: Vec = Vec::with_capacity(phi_size); let mut bbs: Vec = Vec::with_capacity(phi_size); - // Check if the address is in the TCDM, and emit a fast access. + // Check if the address is in the TCDM alias range, and emit a fast access. LLVMPositionBuilderAtEnd(self.builder, bb_valid); - let (is_tcdm, tcdm_ptr) = self.emit_tcdm_check(addr); + let (is_tcdm, tcdm_ptr) = self.emit_tcdm_alias_check(addr); let mut bb_yes = LLVMCreateBasicBlockInContext(self.section.engine.context, NONAME); let mut bb_no = LLVMCreateBasicBlockInContext(self.section.engine.context, NONAME); LLVMInsertExistingBasicBlockAfterInsertBlock(self.builder, bb_yes); @@ -1249,7 +1259,7 @@ impl<'a> InstructionTranslator<'a> { // Check if the address is in the TCDM, and emit a fast access. LLVMPositionBuilderAtEnd(self.builder, bb_valid); - let (is_tcdm, tcdm_ptr) = self.emit_tcdm_check(addr); + let (is_tcdm, tcdm_ptr) = self.emit_tcdm_alias_check(addr); let mut bb_yes = LLVMCreateBasicBlockInContext(self.section.engine.context, NONAME); let mut bb_no = LLVMCreateBasicBlockInContext(self.section.engine.context, NONAME); LLVMInsertExistingBasicBlockAfterInsertBlock(self.builder, bb_yes); @@ -6222,7 +6232,7 @@ impl<'a> InstructionTranslator<'a> { let latency = if let Some(access) = mem_access { // Check config - let (is_tcdm, _tcdm_ptr) = self.emit_tcdm_check(access.1); + let (is_tcdm, _tcdm_ptr) = self.emit_tcdm_alias_check(access.1); LLVMBuildSelect( self.builder, is_tcdm, @@ -6401,7 +6411,7 @@ impl<'a> InstructionTranslator<'a> { let mut bbs: Vec = Vec::with_capacity(phi_size); // Check if the address is in the TCDM, and emit a fast access. - let (is_tcdm, tcdm_ptr) = self.emit_tcdm_check(aligned_addr); + let (is_tcdm, tcdm_ptr) = self.emit_tcdm_alias_check(aligned_addr); let mut bb_yes = LLVMCreateBasicBlockInContext(self.section.engine.context, NONAME); let mut bb_no = LLVMCreateBasicBlockInContext(self.section.engine.context, NONAME); LLVMInsertExistingBasicBlockAfterInsertBlock(self.builder, bb_yes); @@ -6514,7 +6524,7 @@ impl<'a> InstructionTranslator<'a> { LLVMInsertExistingBasicBlockAfterInsertBlock(self.builder, bb_end); // Check if the address is in the TCDM, and emit a fast access. - let (is_tcdm, tcdm_ptr) = self.emit_tcdm_check(addr); + let (is_tcdm, tcdm_ptr) = self.emit_tcdm_alias_check(addr); let mut bb_yes = LLVMCreateBasicBlockInContext(self.section.engine.context, NONAME); let mut bb_no = LLVMCreateBasicBlockInContext(self.section.engine.context, NONAME); LLVMInsertExistingBasicBlockAfterInsertBlock(self.builder, bb_yes); @@ -6618,19 +6628,25 @@ impl<'a> InstructionTranslator<'a> { LLVMPositionBuilderAtEnd(self.builder, bb_end); } - /// Emit the code to check if an address is within the TCDM. + /// Emit the code to check if an address is within the TCDM alias if it exists. /// /// Returns an `i1` indicating whether it is as first result, and a pointer /// to that location in the TCDM. - unsafe fn emit_tcdm_check(&self, addr: LLVMValueRef) -> (LLVMValueRef, LLVMValueRef) { - let tcdm_start = LLVMConstInt(LLVMInt32Type(), self.section.elf.tcdm_start as u64, 0); - // let tcdm_end = LLVMConstInt(LLVMInt32Type(), self.section.elf.tcdm_end as u64, 0); - // let mut in_range = LLVMBuildAnd( - // self.builder, - // LLVMBuildICmp(self.builder, LLVMIntUGE, addr, tcdm_start, NONAME), - // LLVMBuildICmp(self.builder, LLVMIntULT, addr, tcdm_end, NONAME), - // NONAME, - // ); + unsafe fn emit_tcdm_alias_check(&self, addr: LLVMValueRef) -> (LLVMValueRef, LLVMValueRef) { + if !self.section.elf.tcdm_alias { + // No TCDM alias defined: return static false + let in_range = LLVMConstInt(LLVMInt1Type(), 0, 0); + let ptr = LLVMConstInt(LLVMInt32Type(), 0, 0); + return (in_range, ptr) + } + let tcdm_start = LLVMConstInt(LLVMInt32Type(), self.section.elf.tcdm_alias_start as u64, 0); + let tcdm_end = LLVMConstInt(LLVMInt32Type(), self.section.elf.tcdm_alias_end as u64, 0); + let in_range = LLVMBuildAnd( + self.builder, + LLVMBuildICmp(self.builder, LLVMIntUGE, addr, tcdm_start, NONAME), + LLVMBuildICmp(self.builder, LLVMIntULT, addr, tcdm_end, NONAME), + NONAME, + ); let index = LLVMBuildSub(self.builder, addr, tcdm_start, NONAME); let pty32 = LLVMPointerType(LLVMInt32Type(), 0); let pty8 = LLVMPointerType(LLVMInt8Type(), 0); @@ -6642,7 +6658,6 @@ impl<'a> InstructionTranslator<'a> { b"ptr_tcdm\0".as_ptr() as *const _, ); let ptr = LLVMBuildBitCast(self.builder, ptr, pty32, NONAME); - let in_range = LLVMConstInt(LLVMInt1Type(), 0, 0); (in_range, ptr) }