Z80 Emu Evolution

By Sylvester

Champion (377)

Sylvester's picture

11-12-2017, 21:54

Just found this blog post about Z80 emulation: https://floooh.github.io/2017/12/10/z80-emu-evolution.html
Not sure if it's really an evolution, but it contains lots of information if you want to know more about the Z80 and emulation :)

Login or register to post comments

By TomH

Master (217)

TomH's picture

11-12-2017, 23:24

Speaking as the author of a modern Z80 emulator plus several historic ones...

He makes a false dichotomy in instruction-ticked versus cycle-ticked, and makes a mistake in implying the latter is a panacea.

Cycle ticked is not in itself sufficient because the Z80 neither samples all of its inputs nor signals all of its output only on cycle boundaries. And I'm not just talking about tolerances or brief delays: WAIT, for example, is documented to be sampled halfway through a cycle. If you lock your emulator into cycle stepping, you promise that you will always sample WAIT at the wrong time.

Given that the objective is merely to time inputs and outputs properly, reductively tying yourself to the idea of a fixed-length tick is also problematic because it makes you promise to do a lot of irrelevant work. Suppose you're cycle ticked and your machine runs at 3.5Mhz. So that's 3.5 million function calls a second. You suddenly realise that your incorrect sampling of WAIT is a problem. You switch to half-cycle ticked. Now you're suddenly doing 7 million function calls a second, with the vast majority of them being duplicative of their immediate predecessors.

So I've personally evolved from fixed ticks to event-based emulation. My Z80 talks to the bus (more or less) only when it actually samples something. So e.g. it might send a series of messages like:

  • I just spent 1.5 cycles signalling the start of an M1;
  • oh, WAIT is signalled? Then I just spent 1 cycle waiting;
  • WAIT isn't signalled any more? Then I just spent half a cycle signalling the rest of the opcode fetch;
  • Now I just spent 2 cycles performing a refresh cycle with this address;
  • etc, etc.

100% of the information is retained. If a particular bus wants to break that down in terms of individual level transitions then it can, with 100% fidelity. For most machines that's completely unnecessary.

The further implication in that author's article that ticks must always propagate to all devices is also something I strongly contest, and would likely be deleterious for most modern processors as you thrash the caches by constantly jumping into different components for tiny amounts of time. For example, I've been adding MSX 1 emulation to one of my projects. Here's my implementation of the bus's interaction with the VDP:

  • if the processor does anything other than talk to the VDP, just continue to count how many cycles it's been since the last communication;
  • if the processor talks to the VDP, tell it to run for the number of cycles since the last communication, then do the communication;
  • special reverse feature: after each communication, ask the VDP how many cycles it will be until it wants to talk to the processor (i.e. signal an interrupt). Make sure it receives an update after that amount of time.

So it's a couple of counters owned by the bus to avoid a huge number of jumps and cache flushes. But, again, 100% fidelity.

As evidence that I'm not just mouthing off (for once):

(i) https://github.com/tomharte/clock-signal, which I wrote in 2011. It's a ZX80/81 emulator. Exactly the only thing it propagates between things on the bus is the current bus state. It ticks half a cycle at a time — i.e. one clock transition at a time. It's a little slow not just because of that but because I tried to come up with a generic way to implement a bus — in principle you'd build any computer by just supplying the component list and wiring;

(ii) https://github.com/tomharte/clk, which overwhelmingly inherits the same name and is now a couple of years or so of continuous development on. It's mostly event based, by which I mean that some components really do just have a fixed cadence of doing something interesting every cycle. So they're effectively working on a fixed tick, but only by virtue of that being the proper spacing of events. One actually spells out the custom bus logic for each machine, which is less fun but both easier to follow and for your CPU to manage.

By Grauw

Enlighted (7405)

Grauw's picture

11-12-2017, 23:40

Nice elaboration! I think openMSX is also event-based, though not sure if it has that level of partial-cycle accuracy.

That clk is a very nice project btw (nice license, too), are you planning to add MSX support at some point in the future as well? In case I ever want to publish a game on say itch.io with both an MSX ROM and an Mac/Linux/Win executable to expand the player base, it seems like a perfect fit. Of course I first have to finish a game Wink.

By ren

Paragon (1153)

ren's picture

11-12-2017, 23:48

Grauw wrote:

Of course I first have to finish a game Wink.

(wild suggestion) Collaborate with Louthrax and create a bunch of tools to create your game with Wink

By Grauw

Enlighted (7405)

Grauw's picture

12-12-2017, 00:15

That never ending trap of tools Big smile. I try to escape it!

(p.s. I actually haven’t had the time to read the article from the original post yet, but certainly will do that as well Smile.)

By TomH

Master (217)

TomH's picture

12-12-2017, 01:30

Grauw wrote:

Nice elaboration! I think openMSX is also event-based, though not sure if it has that level of partial-cycle accuracy.

I guess I failed to finish my thought: if you're event based in the sense of "x amount of time passed, then event y happened" and you realise you need more precision, just increase the precision with which you're describing x. If it's still the same number of events, it probably doesn't increase the calling costs at all or, at worst, you're doing it because you've two things happening at the same time that are meant to happen at different times, it increases a little. Rather than scaling up by (new precision) / (old precision).

Grauw wrote:

That clk is a very nice project btw (nice license, too), are you planning to add MSX support at some point in the future as well? In case I ever want to publish a game on say itch.io with both an MSX ROM and an Mac/Linux/Win executable to expand the player base, it seems like a perfect fit. Of course I first have to finish a game Wink.

I'm working on the MSX 1, at least. Since MSX emulation is already very well served I can't imagine it's ever going to be all that interesting for anybody else but I'll announce when it's downloadable.

My MSX profile