POWER9 emulator in Nim implementing the ISA as specified in this document.
This simulator is designed such that it is easy to understand and follow. The hope is that by studying it, the motivated individual should be able to confidently design a POWER CPU in an HDL or RTL of their choice.
The simulator is also moderately fast, executing up to 2.5M+ instructions per second if compiled with lots of nice optimizations(on apple silicon at least):
You'll need to have nim installed.
Installing Nim from source is also pretty easy.
if you want to run the loopback example, you'll need to change the contents of
config.json
to the following:
{
"firmware" : "resources/loopback_asm/firmware.bin",
"ram_size" : 16,
"little_endian" : true
}
You'll also need to build the binary firmware from source.
pushd resources/loopback_asm/
make
popd
nim c -r src/nimulatorPPC.nim
nim c -d:release --passC:-flto --passL:-flto -r src/nimulatorPPC
nim c -d:release -d:lto -r src/nimulatorPPC
Press ctrl+c
to end a simulation. At the end of sim, you should
get some stats such as :
SIMULATED FOR 9249776 CYCLES AT ROUGHLY 2583931 CYCLES PER SECOND
Simple incrementing loopback working. I.E., you type 'a' and you get back 'b'.
- full decoder with field select for all mnemonics
- support for virtual memory(hopefully to be added in early July).
Supported instructions listed in docs/supported_instructions.md.
- gcc-powerpc64le-linux-gnu
- nim
apt-get update && apt-get install -y gcc-powerpc64le-linux-gnu make nim
Modify config.json
with desired simulator configuration.
git clone https://github.com/BracketMaster/nimulatorPPC
cd nimulatorPPC
pushd resources/loopback
make
popd
nimble install print itertools
nim c -r src/nimulatorPPC.nim
You can also simulate the CPU with a debug mode that dumps CPU state to a value change dump(VCD) file. You can view VCD files with software such as GTKWave.
The default location the waveform gets dumped to is ./trace.vcd
.
nim c -d:itrace -r src/nimulatorPPC.nim
The architecture of this simulator is very simple at the moment. We fetch an instruction, determine its associated mnemonic, and finally execute that instruction. This loop repeats until the simulator is terminated.
See adding a new instruction for more details.
- populate .gitignore with all binaries to possibly be generated
- working preliminary instruction dump trace to VCD
- opcode names in waveform
- proper support for endian change in instruction fetch
- go through and add docs to sources
- make opcode error message red
- dockerfile
- read binaries
- pass path argument
- support bi-endian reads
- MnemonicEnum -> bitPat
- MnemonicEnum -> FormEnum
- start decoding
- use xor for pattern matching(should work?)
- test endianness with decode
- FormEnum -> FieldSelect
- Add list of supported instructions
- Add sane debug and logging facilities
- support bi-endian writes
- convert from seq to arr
- replace bitslice with use non-mutating bitsliced
- determine whether or not binary fits in memory
- rework loadMemory to take a file
- reword loadMemory to have docs
- add docs to repository
- support quad reads
- find pages in POWER manual with info on register
- move debug to VCD
- cast to int64 for BiggestInt
- mvtspr needs to redirect when it hits a dedicated special SPR such as XER for example
- does CRO:3 need to be preserved across instructions that do compares for example but can't have overflows by definition?