Writing emulators [Was: Re: VCF PNW 2018: Pictures!]

Ray Arachelian ray at arachelian.com
Wed Feb 21 10:52:03 CST 2018

On 02/21/18 09:41, Paul Koning via cctalk wrote:
> SIMH in principle allows the writing of cycle-accurate CPU simulators, but I don't believe anyone has bothered.  It's hard to see why that would be all that interesting.  For some CPUs, the full definition of how long instructions take is extremely complex.  Take a look at the instruction timing appendix in a PDP-11 processor handbook, for example; there are dozens of possibilities even for simple instructions like MOV, and things get more interesting still on machines that have caches.
It's not really that hard to get cycle accurate counts (well, outside of
things like caching), typically you wouldn't emulate a CPU by doing a
big giant case statement, rather, you'd do something that has a lot of
in memory tables, and your instruction decode process will use those to
pick a pointer to a function call.  One of those fields in that big
array can be a set of cycles based on which kind of opcode and what its
operands are.  And then the function at the end of that function pointer
would update a global variable called maybe cycle_count with that
value.  It won't be perfect, but it will be close enough for most
situations, even those that track the position of a raster beam on a CRT
(which isn't likely to be the case in this particular thread.)

You'd also likely have some main loop that executes a certain number of
cycles - that's say linked to one frame of a CRT - to continue down that
metaphor (and marks any overflow which is subtracted from the next
frame), then allows other things to run, and then returns back to the
CPU.  So you'd also update the virtual clock based on CPU cycles and set
a throttle that limits the CPU to a certain MHz.  After a few of these
frames, you'd reach homeostasis and your emulator will run very close to
a machine of that MHz.  Usually you'll want the frames to be some
fraction of a second, in the CRT example 60Hz is ok, but maybe on a
mainframe, I don't know, maybe 1/100th of a second is better, etc.

It will likely never be perfectly cycle accurate without a ton of work,
but you only need that for video games where the CPU is used to draw on
a moving raster beam CRT, anyway.

Now, you don't want to run your emulated guest CPU(s) at full speed on
the host machine, because you'll overheat it, and typically, it'll run a
multi-process OS anyway and you don't want to starve the GUI, network
stack, and daemons of CPU cycles, so once you reach your goal MHz in
your guest CPU, you'd sleep and yield to the host OS for a bit, or maybe
do some background stuff like see if any I/Os or IRQs are pending (such
as maybe a keystroke from the user, or an incoming network packet, or
maybe the disk sector or tape sector your guest OS requested has
arrived), and handle those.

More information about the cctalk mailing list