Track HALT

This commit is contained in:
2025-08-27 22:49:44 -04:00
parent 7f819d080f
commit 8aab90f024
2 changed files with 80 additions and 34 deletions
+54 -30
View File
@@ -96,10 +96,11 @@ struct ProfileSession {
struct StackFrame {
#[expect(dead_code)]
address: Option<u32>,
address: u32,
cycles: u64,
}
const RESET_CODE: u16 = 0xfff0;
impl ProfileSession {
async fn new(file_path: PathBuf) -> Self {
let symbol_manager = SymbolManager::with_config(Default::default());
@@ -109,22 +110,24 @@ impl ProfileSession {
.expect("cannae load symbols");
let mut call_stacks = HashMap::new();
call_stacks.insert(
0,
RESET_CODE,
vec![StackFrame {
address: None,
address: 0xfffffff0,
cycles: 0,
}],
);
Self {
symbol_map,
call_stacks,
context_stack: vec![],
context_stack: vec![RESET_CODE],
}
}
fn track_elapsed_cycles(&mut self, cycles: u32) {
let code = self.context_stack.last().copied().unwrap_or(0);
let Some(stack) = self.call_stacks.get_mut(&code) else {
let Some(code) = self.context_stack.last() else {
return; // program is halted, CPU is idle
};
let Some(stack) = self.call_stacks.get_mut(code) else {
panic!("missing stack {code:04x}");
};
for frame in stack {
@@ -134,42 +137,63 @@ impl ProfileSession {
fn track_event(&mut self, event: SimEvent) {
match event {
SimEvent::Interrupt(code) => {
self.context_stack.push(code);
if self.call_stacks.insert(code, vec![]).is_some() {
panic!("{code:04x} fired twice");
}
}
SimEvent::Reti => {
let Some(code) = self.context_stack.pop() else {
panic!("reti when not in interrupt");
SimEvent::Call(address) => {
let Some(code) = self.context_stack.last() else {
panic!("How did we call anything when we're halted?");
};
if self.call_stacks.remove(&code).is_none() {
panic!("{code:04x} popped but never called")
}
}
SimEvent::Call(addr) => {
let code = self.context_stack.last().copied().unwrap_or(0);
let Some(stack) = self.call_stacks.get_mut(&code) else {
let Some(stack) = self.call_stacks.get_mut(code) else {
panic!("missing stack {code:04x}");
};
let name = self
.symbol_map
.lookup_sync(wholesym::LookupAddress::Svma(addr as u64));
println!("depth {}: {:?}", stack.len(), name);
stack.push(StackFrame {
address: Some(addr),
cycles: 0,
});
.lookup_sync(wholesym::LookupAddress::Svma(address as u64));
println!("depth {}: {:x?}", stack.len(), name);
stack.push(StackFrame { address, cycles: 0 });
}
SimEvent::Return => {
let code = self.context_stack.last().copied().unwrap_or(0);
let Some(stack) = self.call_stacks.get_mut(&code) else {
let Some(code) = self.context_stack.last() else {
panic!("how did we return when we're halted?");
};
let Some(stack) = self.call_stacks.get_mut(code) else {
panic!("missing stack {code:04x}");
};
if stack.pop().is_none() {
panic!("returned from {code:04x} but stack was empty");
}
if stack.is_empty() {
panic!("returned to oblivion");
}
}
SimEvent::Halt => {
let Some(RESET_CODE) = self.context_stack.pop() else {
panic!("halted when not in an interrupt");
};
}
SimEvent::Interrupt(code, address) => {
// if the CPU was halted before, wake it up now
if self.context_stack.is_empty() {
self.context_stack.push(RESET_CODE);
}
self.context_stack.push(code);
if self
.call_stacks
.insert(code, vec![StackFrame { address, cycles: 0 }])
.is_some()
{
panic!("{code:04x} fired twice");
}
}
SimEvent::Reti => {
let Some(code) = self.context_stack.pop() else {
panic!("RETI when halted");
};
if code == RESET_CODE {
panic!("RETI when not in interrupt");
}
if self.call_stacks.remove(&code).is_none() {
panic!("{code:04x} popped but never called");
}
}
}
}