Skip to content

Commit a371663

Browse files
authored
Refactor DAP request handling and optimize bus lookups (#6)
1 parent 90692bc commit a371663

18 files changed

Lines changed: 705 additions & 245 deletions

File tree

Cargo.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,28 @@ panic = "abort"
5252
[profile.release]
5353
panic = "abort"
5454
lto = true
55+
56+
[profile.release.package.firmware-ci-fixture]
57+
codegen-units = 1
58+
debug = true
59+
opt-level = "s"
60+
61+
[profile.release.package.firmware-h563-demo]
62+
codegen-units = 1
63+
debug = true
64+
opt-level = "s"
65+
66+
[profile.release.package.firmware-h563-io-demo]
67+
codegen-units = 1
68+
debug = true
69+
opt-level = "s"
70+
71+
[profile.release.package.firmware-h563-fullchip-demo]
72+
codegen-units = 1
73+
debug = true
74+
opt-level = "s"
75+
76+
[profile.release.package.riscv-ci-fixture]
77+
codegen-units = 1
78+
debug = true
79+
opt-level = "s"

crates/core/src/bus/mod.rs

Lines changed: 139 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::peripherals::uart::UartRegisterLayout;
1313
use crate::{Bus, DmaRequest, Peripheral, SimResult, SimulationError};
1414
use anyhow::Context;
1515
use labwired_config::{parse_size, ChipDescriptor, PeripheralConfig, SystemManifest};
16+
use std::cell::Cell;
1617
use std::path::{Path, PathBuf};
1718
use std::str::FromStr;
1819
use std::sync::atomic::Ordering;
@@ -33,6 +34,15 @@ pub struct SystemBus {
3334
pub peripherals: Vec<PeripheralEntry>,
3435
pub nvic: Option<Arc<NvicState>>,
3536
pub observers: Vec<Arc<dyn crate::SimulationObserver>>,
37+
peripheral_ranges: Vec<PeripheralRange>,
38+
peripheral_hint: Cell<Option<usize>>,
39+
}
40+
41+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42+
struct PeripheralRange {
43+
start: u64,
44+
end: u64,
45+
index: usize,
3646
}
3747

3848
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -48,7 +58,7 @@ impl Default for SystemBus {
4858
}
4959

5060
impl SystemBus {
51-
fn profile_name<'a>(p_cfg: &'a PeripheralConfig) -> anyhow::Result<Option<&'a str>> {
61+
fn profile_name(p_cfg: &PeripheralConfig) -> anyhow::Result<Option<&str>> {
5262
if let Some(value) = p_cfg.config.get("profile") {
5363
return value.as_str().map(Some).ok_or_else(|| {
5464
anyhow::anyhow!("Peripheral '{}' config.profile must be a string", p_cfg.id)
@@ -88,18 +98,88 @@ impl SystemBus {
8898

8999
fn resolve_peripheral_path(manifest: &SystemManifest, descriptor_path: &str) -> PathBuf {
90100
let raw = PathBuf::from(descriptor_path);
91-
if raw.is_absolute() || raw.exists() {
101+
if raw.is_absolute() {
92102
return raw;
93103
}
94104

95105
let chip_path = Path::new(&manifest.chip);
96106
let chip_dir = chip_path.parent().unwrap_or_else(|| Path::new("."));
97-
chip_dir.join(descriptor_path)
107+
let chip_relative = chip_dir.join(descriptor_path);
108+
if chip_relative.exists() {
109+
chip_relative
110+
} else {
111+
raw
112+
}
113+
}
114+
115+
fn is_peripheral_addr(p: &PeripheralEntry, addr: u64) -> bool {
116+
addr >= p.base && addr < p.base + p.size
117+
}
118+
119+
fn rebuild_peripheral_ranges(&mut self) {
120+
self.peripheral_ranges = self
121+
.peripherals
122+
.iter()
123+
.enumerate()
124+
.map(|(index, p)| PeripheralRange {
125+
start: p.base,
126+
end: p.base.saturating_add(p.size),
127+
index,
128+
})
129+
.collect();
130+
self.peripheral_ranges.sort_by_key(|r| r.start);
131+
self.peripheral_hint.set(None);
132+
}
133+
134+
pub fn refresh_peripheral_index(&mut self) {
135+
self.rebuild_peripheral_ranges();
136+
}
137+
138+
fn find_peripheral_index(&self, addr: u64) -> Option<usize> {
139+
if let Some(idx) = self.peripheral_hint.get() {
140+
if let Some(p) = self.peripherals.get(idx) {
141+
if Self::is_peripheral_addr(p, addr) {
142+
return Some(idx);
143+
}
144+
}
145+
}
146+
147+
let mut idx = if self.peripheral_ranges.len() == self.peripherals.len() {
148+
let pos = self
149+
.peripheral_ranges
150+
.partition_point(|range| range.start <= addr);
151+
if pos == 0 {
152+
None
153+
} else {
154+
let candidate = self.peripheral_ranges[pos - 1];
155+
if addr < candidate.end {
156+
Some(candidate.index)
157+
} else {
158+
None
159+
}
160+
}
161+
} else {
162+
None
163+
};
164+
165+
let needs_fallback = match idx.and_then(|i| self.peripherals.get(i)) {
166+
Some(p) => !Self::is_peripheral_addr(p, addr),
167+
None => true,
168+
};
169+
if needs_fallback {
170+
idx = self
171+
.peripherals
172+
.iter()
173+
.position(|p| Self::is_peripheral_addr(p, addr));
174+
}
175+
176+
self.peripheral_hint.set(idx);
177+
idx
98178
}
99179

100180
pub fn new() -> Self {
101181
// Default initialization for tests
102-
Self {
182+
let mut bus = Self {
103183
flash: LinearMemory::new(1024 * 1024, 0x0),
104184
ram: LinearMemory::new(1024 * 1024, 0x2000_0000),
105185
peripherals: vec![
@@ -211,7 +291,11 @@ impl SystemBus {
211291
],
212292
nvic: None,
213293
observers: Vec::new(),
214-
}
294+
peripheral_ranges: Vec::new(),
295+
peripheral_hint: Cell::new(None),
296+
};
297+
bus.rebuild_peripheral_ranges();
298+
bus
215299
}
216300

217301
/// Attach a UART TX capture sink to any UART peripherals on this bus.
@@ -239,6 +323,8 @@ impl SystemBus {
239323
peripherals: Vec::new(),
240324
nvic: None,
241325
observers: Vec::new(),
326+
peripheral_ranges: Vec::new(),
327+
peripheral_hint: Cell::new(None),
242328
};
243329

244330
for p_cfg in &chip.peripherals {
@@ -415,6 +501,7 @@ impl SystemBus {
415501
});
416502
}
417503

504+
bus.rebuild_peripheral_ranges();
418505
Ok(bus)
419506
}
420507

@@ -596,10 +683,9 @@ impl crate::Bus for SystemBus {
596683
}
597684

598685
// Dynamic Peripherals
599-
for p in &self.peripherals {
600-
if addr >= p.base && addr < p.base + p.size {
601-
return p.dev.read(addr - p.base);
602-
}
686+
if let Some(idx) = self.find_peripheral_index(addr) {
687+
let p = &self.peripherals[idx];
688+
return p.dev.read(addr - p.base);
603689
}
604690

605691
Err(SimulationError::MemoryViolation(addr))
@@ -619,10 +705,10 @@ impl crate::Bus for SystemBus {
619705
.or_else(|| self.flash.read_u8(addr))
620706
.or(flash_alias_old)
621707
.or_else(|| {
622-
self.peripherals
623-
.iter()
624-
.find(|p| addr >= p.base && addr < p.base + p.size)
625-
.and_then(|p| p.dev.peek(addr - p.base))
708+
self.find_peripheral_index(addr).and_then(|idx| {
709+
let p = &self.peripherals[idx];
710+
p.dev.peek(addr - p.base)
711+
})
626712
})
627713
.unwrap_or(0);
628714

@@ -637,17 +723,9 @@ impl crate::Bus for SystemBus {
637723
Ok(())
638724
} else {
639725
// Dynamic Peripherals
640-
let mut found = false;
641-
let mut p_res = Ok(());
642-
for p in &mut self.peripherals {
643-
if addr >= p.base && addr < p.base + p.size {
644-
p_res = p.dev.write(addr - p.base, value);
645-
found = true;
646-
break;
647-
}
648-
}
649-
if found {
650-
p_res
726+
if let Some(idx) = self.find_peripheral_index(addr) {
727+
let p = &mut self.peripherals[idx];
728+
p.dev.write(addr - p.base, value)
651729
} else {
652730
Err(SimulationError::MemoryViolation(addr))
653731
}
@@ -804,6 +882,8 @@ mod tests {
804882
peripherals: Vec::new(),
805883
nvic: None,
806884
observers: Vec::new(),
885+
peripheral_ranges: Vec::new(),
886+
peripheral_hint: Cell::new(None),
807887
};
808888

809889
bus.flash.write_u8(0x0800_0000, 0x12);
@@ -817,4 +897,39 @@ mod tests {
817897
bus.write_u8(0x0000_0001, 0xAB).unwrap();
818898
assert_eq!(bus.flash.read_u8(0x0800_0001), Some(0xAB));
819899
}
900+
901+
#[test]
902+
fn test_peripheral_range_index_lookup() {
903+
let mut bus = SystemBus {
904+
flash: LinearMemory::new(256, 0x0800_0000),
905+
ram: LinearMemory::new(256, 0x2000_0000),
906+
peripherals: vec![
907+
PeripheralEntry {
908+
name: "high".to_string(),
909+
base: 0x5000_0000,
910+
size: 0x1000,
911+
irq: None,
912+
dev: Box::new(crate::peripherals::uart::Uart::new()),
913+
},
914+
PeripheralEntry {
915+
name: "low".to_string(),
916+
base: 0x4000_0000,
917+
size: 0x1000,
918+
irq: None,
919+
dev: Box::new(crate::peripherals::uart::Uart::new()),
920+
},
921+
],
922+
nvic: None,
923+
observers: Vec::new(),
924+
peripheral_ranges: Vec::new(),
925+
peripheral_hint: Cell::new(None),
926+
};
927+
928+
bus.rebuild_peripheral_ranges();
929+
let low_idx = bus.find_peripheral_index(0x4000_0004);
930+
let high_idx = bus.find_peripheral_index(0x5000_0004);
931+
932+
assert_eq!(low_idx, Some(1));
933+
assert_eq!(high_idx, Some(0));
934+
}
820935
}

0 commit comments

Comments
 (0)