6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Sep 21, 2024 1:52 pm

All times are UTC




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Mon Sep 07, 2020 10:01 am 
Offline

Joined: Thu Feb 27, 2020 9:15 am
Posts: 18
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


Top
 Profile  
Reply with quote  
PostPosted: Mon Sep 07, 2020 10:25 am 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 674
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).

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Mon Sep 07, 2020 10:26 am 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
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.

You could write a Windows implementation of 'usleep' using the Windows function 'QueryPerformanceCounter' to delay your code based on the cycle length of the emulated instruction. Sadly its a busy wait.

_________________
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


Top
 Profile  
Reply with quote  
PostPosted: Mon Sep 07, 2020 10:38 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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.


Top
 Profile  
Reply with quote  
PostPosted: Mon Sep 07, 2020 10:54 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1467
Location: Scotland
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


One thing to note is that not all Unixes/Linuxes/BSDs/etc. have nanosecond resolution and sometimes other means have to be employed. And even if you do have seemingly ns timing, you should always check the minimum interval possible - use the clock_getres(2) system call to see what's possible. also check the minimum duration of a system call - especially things like sleep(), nanosleep(), etc. you may well find that they are much longer than you're expecting.

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

That works remarkably well and I was able to check my cycle timing against a real PDP-8 and they matched.

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/


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 09, 2020 5:00 am 
Offline

Joined: Sat Dec 30, 2017 3:19 pm
Posts: 116
Location: Detroit, Michigan, USA
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.


Top
 Profile  
Reply with quote  
PostPosted: Sat Sep 12, 2020 5:27 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: