Adding a Processor¶
In general the goal for emulation is to provide an accurate representation of hardware (as seen
by the software AKA the TargetProgram
as we call it). But at the end of the day the goal is
to be able to run or debug your TargetProgram
, so practically you only need the peripheral
support required to run and debug said TargetProgram
.
Thankfully, styx
provides a defined structure for your custom emulation by supplying a collection
of interfaces to build on. One of the hardest parts of emulating a TargetProgram
is knowing
what you need to do, and in what order to do it. (The problem best part with providing a
realistic hardware emulation is that you really don’t know the minimum set of things you need
to emulated until you need it now).
The Process¶
In styx
(and in general) by and large emulating every new processor follows the same process,
with a little context-dependent flair tossed in for each new chip. Unlike most other frameworks,
there is not only a checklist, but a solidified set of generic interfaces that together provide
adequate flexibility to implement most any type of computation engine. This in turn, should allow
you to be able to get away with following this checklist to add processor support for any processor
that the codebase already provides the “foundational support” for.
In our terms, “foundational support” is:
the ISA is known by, and supported by
styx
the
GdbArchSupport
trait is implemented for your processor variantany of the
CpuBackend
’s support executing instructions for your ISA
Once the foundational support is present in `styx
, then any contributor (along with their
nearest CPU reference manual) should be able to add support for emulating a Processor, and in
turn, build that into a picture perfect emulated digital twin of their target machine.
Quick Reference Frequently Asked Questions¶
What files do I need to touch to add Gdb Support¶
Create or modify styx/core/styx-cpu-type/src/arch/<arch>/gdb_targets.rs
.
This provides the mapping from gdb register index to styx register. This is
assuming you have the TargetDescription struct which includes the register map
and gdb xml specification. You may need to add your gdb xml to
styx/core/styx-util/src/gdb_xml.rs
How do I add a Processor Variant¶
Add your variant to styx/core/styx-cpu-type/src/arch/<arch>/variants.rs
.
You may need to add your variant to the cpu backend you want to use. If a
similar variant exists in Styx already then this will be easy. If your
processor variant is not supported by Styx or Unicorn then you will have to do
some work to add it to the pcode backend.
Backend Support¶
Unicorn Support¶
If unicorn supports your processor/variant then it should Just Work if you
instantiate a UnicornBackend, but be sure to check
styx/core/styx-cpu-type/src/backend_compat/unicorn.rs
to add the styx ->
unicorn processor conversion.
If unicorn does not support your processor variant you could use a similar supported one or add it to unicorn yourself. Your best bet is to instead use the pcode backend.
Pcode Backend Support¶
If your processor has the same ISA as another processor already implemented in
the pcode backend then just use the already supported variant or add your
variant to styx/core/styx-cpu-pcode-backend/src/arch_spec/mod.rs
build_arch_spec()
and map to the correct arch spec.
If you need to add a new ISA entirely then check out Adding a New Architecture (Pcode Backend) for detailed instructions on adding new architectures to the pcode backend.
To modify architecture specific behavior in the pcode backend, check out its
architecture specification in
styx/core/styx-cpu-pcode-backend/src/arch_spec/<arch>/mod.rs
. Here there is
the PcManager, user op handlers, and register handlers that can be changed.
Special Register vs Styx Abstraction¶
Most CPU registers are easily represented as a simple data store that can be read or written to without side effects. The most challenging registers to model are ones with external state side effects or are not statically defined, also known as model specific registers.
Examples of registers controlling external state include PowerPC MSR, ARM CPSR, and PowerQuicc IMMR registers. Writes to these register may change processor behavior.
Examples of model specific registers are ARM’s coprocessor registers and PowerPC’s special registers (SPRs).
External state registers should be modeled as normal cpu registers (i.e. in ArmRegister, Ppc32Register, etc) and external behavior should be modeled through Styx features. There are several ones to do this including register hooks (pcode backend only), register handlers (pcode backend internal), interrupt hooks (i.e. event controller sets a “saved machine state” register), and the PcManager (pcode backend internal, e.g. thumb mode state).
Model specific registers should be modeled as a SpecialRegister variant in Styx. This allows them to be defined by variable parameters, i.e. for PowerPC the Special Registers can be modeled as a struct with a single integer representing the SPR number it is.
The Complete Processor Checklist (ARM Example)¶
styx-cpu
ISA supportstyx-cpu::GdbArchSupport
ISA supportA
CpuBackend
supports your ISAImplement
ProcessorImpl
trait inside your new processor definition crateInterrupt Controller (
EventController
instyx
-terms) implementedWe have implemented a couple common ARM interrupt controllers, namely support for
ARM Cortex-M
(NVIC
), and someARM Cortex-A/R
(GIC
).NVIC
GICv1
GICv2
GICv3
GICv4
VIC
(akaPrimeCell VIC
)
Create new baseline End to End (E2E) tests in
styx-integration-tests/tests
Create behavior tests for the E2E test suite
TBD integration + e2e test guide (see
./styx-integration-tests
in the interim)Simple
while (true);
spinning.
This tests that input files can load, and that
styx-trace
events can be emittedMore as needed + peripherals are implemented
Implement peripherals (TBD peripherals + devices guide)
This step is definitely the most arduous, and ill-defined of all the steps. In general you don’t want to waste time emulating hardware you aren’t going to need, and you are going to take some liberties with emulation because
styx
is not real hardware and is confined by the same constraints.As
styx
continues to mature we will unify peripheral events forstyx-trace
in order to provide a cleaner, more auto-magic test suite generation for peripherals and interactions between them. For now, make sure that the process for peripheral emulation is documented to reference which manuals and specification sections are referenced for which part, and reasoning behind omitting emulated behavior for one feature or another.IN GENERAL, the order of peripherals you want to implement is:
Clocks/Timers
GPIO
I2C
UART
SPI
any others needed
This roughly follows “least complex first,” and also generally follows many RTOS/OS boot patterns. So in theory you will be able to emulate your target program further and further as you emulate more.
It will also significantly help you (and your sanity) if you create test binaries to utilize your emulated hardware as you go along. See (TDB ref link) “adding test binaries” for more information.