pub struct Bus { /* private fields */ }Expand description
A checked bus: the CPU, the memory map, and every peripheral instance with its register file.
It answers where an address lands and what that register holds. It doesn’t answer what the peripheral does. That’s the model, which is a field of the MCU built on this bus.
Implementations§
Source§impl Bus
impl Bus
Sourcepub fn builder(
cpu: Cpu,
memory: &'static [Region],
peripherals: impl IntoIterator<Item = Peripheral>,
) -> Builder
pub fn builder( cpu: Cpu, memory: &'static [Region], peripherals: impl IntoIterator<Item = Peripheral>, ) -> Builder
Starts assembling a bus from its CPU, memory map, and peripheral instances.
Sourcepub fn slots(&self) -> &[Slot]
pub fn slots(&self) -> &[Slot]
Every slot, in address order. The index is what crate::mcu::Mcu::split dispatches on.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
The part as a system reset leaves it: every register at its reset value and nothing scheduled, driven, or waiting for an answer.
Sourcepub fn slot_of(&self, name: &str) -> Option<usize>
pub fn slot_of(&self, name: &str) -> Option<usize>
The slot index of the instance called name, which an MCU resolves once at construction so
that nothing after it looks a peripheral up by string.
Sourcepub fn slot(&self, name: &'static str) -> Result<usize, Error>
pub fn slot(&self, name: &'static str) -> Result<usize, Error>
The slot index of the instance called name, as Bus::slot_of finds it, or
Error::UnknownInstance where the bus carries none.
§Errors
If no instance is called name.
Sourcepub fn slot_at(&self, address: u64) -> Option<usize>
pub fn slot_at(&self, address: u64) -> Option<usize>
The slot an address falls in, or None where no instance covers it.
The same search an access decodes with, for a caller that wants to know which instance an address belongs to without making the access.
Sourcepub fn memory(&self) -> &[Region]
pub fn memory(&self) -> &[Region]
The memory regions, the description’s and then each one a board added.
Sourcepub fn add_region(&mut self, region: Region) -> Result<(), Error>
pub fn add_region(&mut self, region: Region) -> Result<(), Error>
Adds a region of memory a board fits outside the part, like RAM or flash on its external memory interface. The emulator maps it as it maps the part’s own, an image can be placed in it, and a model’s requested access reaches it.
Fails when the region shares a name or an address with a region, an instance or a window already there, runs past the last address, its erase blocks don’t add up to its size, or it names a programmer the part doesn’t have or is RAM with one.
Sourcepub fn add_window(&mut self, window: Window) -> Result<usize, Error>
pub fn add_window(&mut self, window: Window) -> Result<usize, Error>
Adds a window for a board’s chip and returns its slot. The slot comes after every existing
slot, so no slot a part already resolved moves. Fails like Bus::add_region, and also
when the gate or an interrupt names something the bus doesn’t have.
Sourcepub fn keep_added(&mut self, from: &Bus) -> Result<(), Error>
pub fn keep_added(&mut self, from: &Bus) -> Result<(), Error>
Copies the regions and windows a board added to from onto this bus, with each window in
the same slot, and goes on numbering events from where from stood, so an id a chip kept
from before is never a new event’s. A part that rebuilds its bus on reset uses this to keep
them.
Fails, with nothing copied, unless self is fresh from the same description as from: the
same CPU, regions and instances, and nothing added yet. Otherwise a window would land on
another slot than the one its chip answers for.
Sourcepub fn peripherals(&self) -> impl Iterator<Item = &Peripheral>
pub fn peripherals(&self) -> impl Iterator<Item = &Peripheral>
Every peripheral instance, by ascending base address.
Sourcepub fn peripheral(&self, name: &str) -> Option<&Peripheral>
pub fn peripheral(&self, name: &str) -> Option<&Peripheral>
The instance with this name.
Sourcepub fn registers(&self, name: &str) -> Option<&RegisterFile>
pub fn registers(&self, name: &str) -> Option<&RegisterFile>
The register file of the instance with this name.
Sourcepub fn drive(
&mut self,
at: VirtualNanos,
slot: usize,
) -> (&mut RegisterFile, DeviceContext<'_>)
pub fn drive( &mut self, at: VirtualNanos, slot: usize, ) -> (&mut RegisterFile, DeviceContext<'_>)
The registers of the instance at slot and a context for its model at at, as an access hands
them over, for an input the bus doesn’t carry: a level on a pin, a sample, a word from a chip.
A part’s drive_ method is this with its model’s field named beside it. What the model does
with the context, an event, an interrupt or a request, settles when the run resumes from the
stop the input was handed over at, so the firmware sees it at that same stop.
§Panics
If slot is past the end of Bus::slots.
Sourcepub fn slot_mut(&mut self, index: usize) -> &mut Slot
pub fn slot_mut(&mut self, index: usize) -> &mut Slot
The slot at index, for the MCU that owns its model. A part’s setter that changes what its
registers hold with no instant to schedule from, like a supply that sets a status bit, writes
through it. One that schedules or raises goes through Bus::drive.
§Panics
If index is past the end of Bus::slots.
Sourcepub fn next_event(&self) -> Option<VirtualNanos>
pub fn next_event(&self) -> Option<VirtualNanos>
The instant of the earliest pending event, which is when the emulator next needs to stop.