Why emulate for certain number of cycles?
Asked Answered
E

3

5

I have seen in more than one places - the following way of emulating

i.e cycles is passed into emulate function

int CPU_execute(int cycles) {
    int cycle_count;

    cycle_count = cycles;
    do {

         /* OPCODE execution here */

    } while(cycle_count > 0);

    return cycles - cycle_count;
}     

I am having hard time understand why would you do this approach for emulating i.e why would you emulate for certain number of cycles? Can you give some scenarios where this approach is useful.

Any help is heartily appreciated !!!

Edwardoedwards answered 4/12, 2012 at 6:44 Comment(0)
V
7

Emulators tend to be interested in fooling the software written for multiple chip devices — in terms of the Z80 and the best selling devices you're probably talking about at least a graphics chip and a sound chip in addition to the CPU.

In the real world those chips all act concurrently. There'll be some bus logic to allow them all to communicate but they're otherwise in worlds of their own.

You don't normally run emulation of the different chips as concurrent processes because the cost of enforcing synchronisation events is too great, especially in the common arrangement where something like the same block of RAM is shared between several of the chips.

So instead the most basic approach is to cooperatively multitask the different chips — run the Z80 for a few cycles, then run the graphics chip for the same amount of time, etc, ad infinitum. That's where the approach of running for n cycles and returning comes from.

It's usually not an accurate way of reproducing the behaviour of a real computer bus but it's easy to implement and often you can fool most software.

In the specific code you've posted the author has further decided that the emulation will round the number of cycles up to the end of the next whole instruction. Again that's about simplicity of implementation rather than being anything to do with the actual internals of a real machine. The number of cycles actually run for is returned so that other subsystems can attempt to adapt.

Varnado answered 5/12, 2012 at 7:32 Comment(7)
"It's usually not an accurate way of reproducing the behaviour of a real computer..." It can still be accurate, since a chip oftentimes doesn't need to be synchronized for a certain amount of cycles. For example, the gameboy graphics chip does only draw one scanline every 456 cycles, and therefore, CPU cycles can be run in between each time the graphics are updated while still maintaining accuracy.Ashcroft
@Profetylen it's inaccurate to say that the chip sits and does nothing for 456 cycles, then instantaneously fetches all the data it needs to output a line and instantaneously outputs it. It's therefore inaccurate to simulate it as doing so — it doesn't match how the real hardware acts. What I think you're arguing is "a user usually isn't aware of the inaccuracy", which I think is a helpful point to make for the original poster. Emulator authors often produce a deliberately inaccurate emulation based on optimising the three issues of effort, computing power and perceived accuracy.Varnado
I would call an emulator that shows on the screen and emits from the speakers the same stuff as the hardware does for the same input accurate. Altough, I see what you mean and I argue that your definition of accuracy would be better suited for a simulator than an emulator (see this question: Simulator or Emulator? What is the difference?). In the extreme, would you call any emulator that does not take into account the electrical currents flowing through the wires of the hardware inaccurate?Ashcroft
@Profetylen it doesn't show the same things, it shows things that are hard to differentiate for the subset of applications that perform 'as expected'. 95% of the time when emulator authors make some simplification assumption they then find an edge case that doesn't work, add a few thousand lines to work around that, find something else that doesn't work, etc. Example: Elite works on Nesticle only if you manually adjust the horizontal cycle count because it's cleverly rewriting the tile map as the display flows. Where on the real hardware is the dial to adjust the horizontal cycle count?Varnado
@Profetylen I'd further say that emulators are accurate to a stated precision. If you make the subjective value judgment that being 'accurate to the scanline' is good enough then great. From my part I've worked at that level, at the cycle accurate level (see, e.g. github.com/TomHarte/ElectrEm), at the bus transition accurate level (github.com/TomHarte/Clock-Signal) and all the way back at the opcode accurate level (github.com/TomHarte/CP-M-for-OS-X). Of those the CP/M one is probably technically most accurate because that's exactly the level CP/M is specified at.Varnado
I'm still not convinced that something that needs to be synchronized is happening between those 456 cycles. I've been working on a gameboy emulator for years (semi-functional as of now) and haven't seen any reason to why it cannot be separated while maintaining accuracy. I might just have missed it though, but I still find it likely that for such a simple system as the gameboy it is possible that this optimization doesn't affect accuracy.Ashcroft
let us continue this discussion in chatVarnado
C
3

Since you mentioned z80, I happen to know just the perfect example of the platform where this kind of precise emulation is sometimes necessary: ZX Spectrum. The standard graphics output area on ZX Spectrum was a box of 256 x 192 pixels situated in the centre of the screen, surrounded by a fairly wide "border" area filled by a solid color. The color of the border was controlled by outputing a value into a special output port. The computer designer's idea was that one would simply choose the border color that is the most appropriate to what is happening on the main screen.

ZX Spectrum did not have a precision timer. But programmers quickly realised that the "rigid" (by modern standards) timings of z80 allowed one to do drawing that was synchronised with the movement of the monitor's beam. On ZX Spectrum one could wait for the interrupt produced at the beginning of each frame and then literally count the precise number of cycles necessary to achieve various effects. For example, a single full scanline on ZX Spectrum was scanned in 224 cycles. Thus, one could change the border color every 224 cycles and generate pixel-thick lines on the border.

Graphics capacity of the ZX Spectrum was limited in a sense that the screen was divided into 8x8 blocks of pixels, which could only use two colors at any given time. Programmers overcame this limitation by changing these two colors every 224 cycles, hence, effectively, increasing the color resolution 8-fold.

I can see that the discussion under another answer focuses on whether one scanline may be a sufficiently accurate resolution for an emulator. Well, some of the border scroller effects I've seen on ZX Spectrum are, basically, timed to a single z80-cycle. Emulator that wants to reproduce the correct output of such codes would also have to be precise to a single machine cycle.

Category answered 12/3, 2013 at 22:18 Comment(0)
A
2

If you want to sync your processor with other hardware it could be useful to do it like that. For instance, if you want to sync it with a timer you would like to control how many cycles can pass before the timer interrupts the CPU.

Ashcroft answered 4/12, 2012 at 8:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.