pub struct Hg51b { /* private fields */ }Expand description
The HG51B S169 core (CX4’s CPU).
Free-runs synchronously to its next halt/wait state via Hg51b::run_until_halt — the same
run-to-completion host-sync pattern this project’s GSU (Go-bit) and DSP-1 (RQM) engines
use, since the pc-write trigger ($7f4f while halted) is the only observable coupling to the
S-CPU (docs/cart.md §CX4).
Implementations§
Source§impl Hg51b
impl Hg51b
Sourcepub fn new() -> Self
pub fn new() -> Self
Construct a powered-off HG51B (inert until Hg51b::load_data_rom supplies the constant
table — docs/adr/0003).
Sourcepub fn load_data_rom(&mut self, bytes: &[u8]) -> bool
pub fn load_data_rom(&mut self, bytes: &[u8]) -> bool
Load the 3072-byte (1024 x 24-bit, 3 bytes/word little-endian) data-ROM constant table
(cx4.rom). Returns false (and leaves the chip inert) if the dump is the wrong size.
Sourcepub const fn data_rom_loaded(&self) -> bool
pub const fn data_rom_loaded(&self) -> bool
Whether the data-ROM constant table has been supplied (the chip is functional).
Sourcepub const fn instructions_run(&self) -> u64
pub const fn instructions_run(&self) -> u64
Total instructions executed since power-on (debugger/diagnostics).
Sourcepub fn read_dram(&self, offset: u32) -> u8
pub fn read_dram(&self, offset: u32) -> u8
Read the 3 KiB data RAM at a chip-relative offset ($000-$FFF, folded per the >=$C00
hardware quirk — see fold_dram).
Sourcepub fn write_dram(&mut self, offset: u32, data: u8)
pub fn write_dram(&mut self, offset: u32, data: u8)
Write the 3 KiB data RAM at a chip-relative offset (see Self::read_dram).
Sourcepub fn read_io(&mut self, local: u32) -> u8
pub fn read_io(&mut self, local: u32) -> u8
Read the fixed IO register block ($7F40-$7FEF, DMA/cache/wait/IRQ/vector/GPR-mirror
controls — ares HitachiDSP::readIO). local is the address already folded to
0x7C00 | (address & 0x3FF) by the caller (the board owns the bus-window decode).
Sourcepub fn write_io(&mut self, local: u32, data: u8, bus: &mut impl Hg51bBus)
pub fn write_io(&mut self, local: u32, data: u8, bus: &mut impl Hg51bBus)
Write the fixed IO register block (see Self::read_io). bus supplies the chip-ROM
access this may need to kick off (a cache-page refill on the pc-write trigger).
Sourcepub const fn running(&self) -> bool
pub const fn running(&self) -> bool
Whether the chip is doing anything at all (cache/dma/bus pending, or not halted).
Sourcepub const fn busy(&self) -> bool
pub const fn busy(&self) -> bool
Whether the chip is mid-cache/dma/bus-access (narrower than Self::running).
Sourcepub const fn irq_pending(&self) -> bool
pub const fn irq_pending(&self) -> bool
Whether the host IRQ line should be asserted (raised when the chip halts with IRQs
enabled — docs/cart.md §CX4’s execution-model note).
Sourcepub fn run_until_halt(&mut self, bus: &mut impl Hg51bBus)
pub fn run_until_halt(&mut self, bus: &mut impl Hg51bBus)
Run the chip to its next halt (or RUN_CAP instructions, whichever comes first) —
the host-sync run-to-completion pattern (see the struct doc).
Sourcepub fn save_state(&self, w: &mut SaveWriter)
pub fn save_state(&self, w: &mut SaveWriter)
Write this core’s mutable state — every register, the IO block, the two cached program
pages, the 3 KiB data RAM, and the 8-deep call stack — into an "HG51" section. The data
ROM (cx4.rom, firmware) is deliberately NOT written, per docs/adr/0003’s “never embed a
chip-ROM dump in a save-state” posture: it is reloaded fresh via Self::load_data_rom
before a matching Self::load_state call. instructions_run (a debugger counter, not
emulated-hardware state) is also omitted.
Sourcepub fn load_state(
&mut self,
r: &mut SaveReader<'_>,
) -> Result<(), SaveStateError>
pub fn load_state( &mut self, r: &mut SaveReader<'_>, ) -> Result<(), SaveStateError>
The inverse of Self::save_state.
§Errors
SaveStateError on truncated/corrupt input (the section framing itself already rejects
a wrong tag or a truncated read) or a section with unconsumed trailing bytes. Every
hardware register narrower than its Rust storage type is masked to its real width on load
(pb/p/cache.pb are 15-bit, a/mdr/rom/ram/mar/dpr/gpr are 24-bit, mul
is 48-bit, wait.rom/wait.ram are 3-bit) — the same “apply the engine’s own
normal-operation width invariant on load” reasoning already applied to the NEC DSP engine’s
pc/rp/dp/sp, extended here to every register (this core happens to have no field
whose valid range is narrower than its type in a way that risks an out-of-bounds array
index, but an unmasked wide value would still desync subsequent arithmetic from hardware
behavior, which matters for save-state fidelity even without a panic risk).