nobody's blog

ponyo - a framework for ISA simulation

Margret Riegert3 Mar 2022 views


I took a class last fall on Computer Engineering, where we delved into the intricacies of processor design and tradeoffs, from simple single-cycle processors to 5 stage pipelined processors and beyond. As part of the lab, we implemented a processor in VHDL for the LEGv8 ISA, and in the very first week learning about the basics of the ISA, I knew I wanted to make a simulator for it. Purely for fun (at first), but also to better learn the ISA and as a sanity-check for the results I was getting from my VHDL simulations. I wanted to scratch the engineering-itch.

I had already implemented a simulator for a different ISA previously, but the code was too inflexible to reuse for this (and was a little broken); and while there do exist other CPU simulators out there such as Unicorn, none of them had the simplicity or flexibility I was looking for, and none of them seemed like I could pick them up and just start instantly building out an ISA. Thus, I created ponyo.


The original idea behind ponyo was to have a simulator that:

The simulator was implemented and fleshed out over the course, with more instructions being added, bugs being fixed, and better functionality being implemented as needed. For each ISA, there are 3 files that are implemented:

Then there is a simple top-level file that handles the command-line interface and calling each of the ISA’s functions.


Here is a simple example of ponyo in action:

    ADDI X16, XZR, 10 // Number of fib iterations
    ADDI X15, XZR, 0  // Mem addr for storing
    ADDI X5, XZR, 0   // Initial values
    ADDI X6, XZR, 1
    ADD  X7, X6, X5   // Calc next fib number
    ADDI X5, X6, 0
    ADDI X6, X7, 0
    SUBI X16, X16, 1  // Dec fib iterator
    ADDI X0, X5, 0

    STUR X0, [X15, 0] // Store fib value
    ADDI X15, X15, 8

    CBNZ X16, =fib


Throughout the project, I also investigated how fast the simulator was performing, and whether I could make it faster. One improvement I made that seems obvious now was to decode the source once instead of every instruction execution. Another improvement I made was to run the simulator with pypy3 instead of CPython, which often ran the simulation anywhere from 2x-10x faster, varying based on where I was in development of ponyo. Anyone looking to use ponyo should use pypy3 on performance grounds alone, if available.

Adding a new ISA

The 3 files mentioned above just need to be placed in a subfolder of the main ponyo folder (/ponyo/ponyo/MY_ISA/{decode,execr,mem}.py) along with an, and the necessary imports and connections need to be made in the main ponyo executable (/ponyo/ Then when executing ponyo, you just need to set the proper --isa flag.

Future improvements

If I ever get around to messing with ISAs again in the future, there are definitely a lot of potential improvements I would want to make to this, including:

Fishbowl icon created by Becris - Flaticon

© 2020-2022 Margret Riegert
Unless otherwise noted, content is under a CC BY 4.0 license.