Hello
I have been making an emulator for 6502 for the past week but i am stuck at an issue.
WARNING: this question is not entirely about 6502, but more about emulator design in general.
The CPU emulation code can currently run at ~70-80MHz on average, but i am having trouble controlling the frequency precisely. I want my code to work multiplatform but Afaik windows api does not allow for nanosecond precision timers unlike unix so i cannot set the emulator to run precisely at a few MHz.
It is kind of ironic that the issue is running code slower than its max speed.
What would be the preferred approach to control emulator frequency? I want to be able to at least run it at the max datasheet frequency of 14MHz if its possible
Need help designing an emulator
-
White Flame
- Posts: 704
- Joined: 24 Jul 2012
Re: Need help designing an emulator
Consider your "speed" as the number of cycles you take in some larger sensible time period. For many video-oriented machines, you'd run a frame at a time, then sync to the wall clock to a 1/50th or 1/60th second delta from the last time, outputting the single generated frame & any audio buffers.
Say you're going to run at 1MHz, and you wanted to sync time every 10ms; so you'd check the current time, run 10,000 clock cycles flat-out, then wait for 10ms to have elapsed, and loop. For 2MHz, run 20,000 cycles and sync on 10ms. If your target time has already elapsed, that means your emulation isn't keeping up in real-time. You don't need high-resolution timers in this approach.
You don't need every cycle to line up with the wall clock, unless your code is interfacing with actual hardware peripherals (say, emulating a serial port connected to real pins).
Say you're going to run at 1MHz, and you wanted to sync time every 10ms; so you'd check the current time, run 10,000 clock cycles flat-out, then wait for 10ms to have elapsed, and loop. For 2MHz, run 20,000 cycles and sync on 10ms. If your target time has already elapsed, that means your emulation isn't keeping up in real-time. You don't need high-resolution timers in this approach.
You don't need every cycle to line up with the wall clock, unless your code is interfacing with actual hardware peripherals (say, emulating a serial port connected to real pins).
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
Re: Need help designing an emulator
JustClaire wrote:
Hello
The CPU emulation code can currently run at ~70-80MHz on average, but i am having trouble controlling the frequency precisely. I want my code to work multiplatform but Afaik windows api does not allow for nanosecond precision timers unlike unix so i cannot set the emulator to run precisely at a few MHz.
The CPU emulation code can currently run at ~70-80MHz on average, but i am having trouble controlling the frequency precisely. I want my code to work multiplatform but Afaik windows api does not allow for nanosecond precision timers unlike unix so i cannot set the emulator to run precisely at a few MHz.
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
Re: Need help designing an emulator
If you have any kind of user interface, you might be using (or consider using) the SDL cross-platform library, which offers timers.
If White Flame's idea of syncing at approx a video frame rate is too coarse, consider syncing at approx a video horizontal line rate.
If White Flame's idea of syncing at approx a video frame rate is too coarse, consider syncing at approx a video horizontal line rate.
Re: Need help designing an emulator
JustClaire wrote:
Hello
I have been making an emulator for 6502 for the past week but i am stuck at an issue.
WARNING: this question is not entirely about 6502, but more about emulator design in general.
The CPU emulation code can currently run at ~70-80MHz on average, but i am having trouble controlling the frequency precisely. I want my code to work multiplatform but Afaik windows api does not allow for nanosecond precision timers unlike unix so i cannot set the emulator to run precisely at a few MHz.
It is kind of ironic that the issue is running code slower than its max speed.
What would be the preferred approach to control emulator frequency? I want to be able to at least run it at the max datasheet frequency of 14MHz if its possible
I have been making an emulator for 6502 for the past week but i am stuck at an issue.
WARNING: this question is not entirely about 6502, but more about emulator design in general.
The CPU emulation code can currently run at ~70-80MHz on average, but i am having trouble controlling the frequency precisely. I want my code to work multiplatform but Afaik windows api does not allow for nanosecond precision timers unlike unix so i cannot set the emulator to run precisely at a few MHz.
It is kind of ironic that the issue is running code slower than its max speed.
What would be the preferred approach to control emulator frequency? I want to be able to at least run it at the max datasheet frequency of 14MHz if its possible
One thing I did for my cycle-accurate PDP-8 emulator a while back was to bypass the kernel and use a hardware timer because the system I was running it on only had a resolution of 1µS and I needed something quicker - that was on a Raspberry Pi Zero and obviously isn't possibly on all platforms. So my strategy was:
- Read the hardware timer (A)
- execute my C code to Interpret the instruction
- Read the hardware timer again and use it to calculate the time left to the next clock tick (cycleTime - (current - A))
- Busy loop for this time, reading/comparing the hardware timer
Personally, cycle accurate is the way to go because (other than the fun with a PiTubeDirect - 65C02 @ 300Mhz) then if you want faster you might as well use a different CPU IMO ... (although there are scenarios like ... that obscure bug that only happens once a day where speeding up the emulating might help debug it, etc. but then how did they do it on the old days...)
Cheers,
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
-
jmthompson
- Posts: 127
- Joined: 30 Dec 2017
- Location: Detroit, Michigan, USA
- Contact:
Re: Need help designing an emulator
In pretty much any full system emulation there will be a need to match the emulated CPU speed with the emulated hardware, and so the CPU speed needs to be controlled at that level, not inside the CPU emulation. All you really need is to provide a single method that takes as input the maximum number of CPU cycles to execute, and that then returns the number of actual cycles that were executed. This is what I did with M65816, the CPU emulator inside XGS.
With this setup, you can set your timer to a more reasonable period, and just keep the CPU speed constant by making sure you run about the same number of cycles for each timer period. XGS for example runs its timer at the video frame rate, and then runs the CPU emulation in between generating the scan lines of the current frame. The frame rate is fixed to real time (50 or 60 fps), and so as long as it's running about the right number of CPU cycles per timer period the CPU emulation will stay at the selected speed.
With this setup, you can set your timer to a more reasonable period, and just keep the CPU speed constant by making sure you run about the same number of cycles for each timer period. XGS for example runs its timer at the video frame rate, and then runs the CPU emulation in between generating the scan lines of the current frame. The frame rate is fixed to real time (50 or 60 fps), and so as long as it's running about the right number of CPU cycles per timer period the CPU emulation will stay at the selected speed.
Re: Need help designing an emulator
You can still use relatively coarse wall-clock timing while accurately simulating a full system. You advance all the hardware at the same time, not just the CPU, until your designated cycle count has elapsed. That is then the moment to synchronise the internal machine state with the external view of it, including real time.