Post by gtoal on Feb 22, 2021 19:36:53 GMT -5
Over on the PiTrex mailing list, Malban has been working on a version of vecx, greatly improving its cycle-accuracy so that many of the issues that make vector timing a problem under an emulator work better.
The ARM in the PiTrex (it's a Pi Zero piggybacked on top of the PiTrex board) emulates the CPU of a 6809 Vectrex but uses all of the Vectrex's real devices and peripherals.
If all goes well, this means it can act identically to the Vectrex itself, when running Vectrex code - as long as the emulated timing matches the native 6809 timing. This is how we make the PiTrex behave like a multicart... (the pitrex cart hardware is too simple to allow the 6809 to load rom data from it directly, so we halt the 6809 and let the ARM do the work, since it has direct access to the SD on the Pi Zero...)
Malban has done really well given the constraints of a traditional emulator structure and the emulation looks absolutely perfect, but when we get to emulating various peripherals, it may be that a traditional instruction-stepped emulator is going to have problems when real hardware devices (such as the 3D imager) have to perform actions at specific times within an instruction cycle.
There is a method of writing emulators that works in these circumstances, but at the moment it is only used by FPGA implementations of CPUs or (as far as I know) in only one soft emulator, the 6502 at floooh.github.io/2019/12/13/cycle-stepped-6502.html - worth a read if you haven't seen it before...
So... here's a crude sketch of a cycle-ticked 6809 emulator...
Unfortunately, our existing emulator (based on vecx) may be cycle-counting, but it is instruction-ticked rather than cycle-ticked, but we can fake cycle-ticking by not doing anything in the emulation procedure for the other clock cycles, eg something like this...
Clearly this isn't *really* a cycle-stepped emulation, because everything happens at the very first clock tick when executing each instruction, and the CPU sits idle and no pins change on the subsequent clock ticks when inputs and outputs should be changing, but at least now the framework is in place.
But... at this point you can identify the few instructions where cycle-accuracy is required and migrate those instructions from being instruction-ticked to being cycle-ticked, leaving ones where it is not critical to be executed the old way, and thus migrate an existing emulator slowly without breaking it... With enough effort such an emulator might eventually become genuinely cycle-ticked completely.
I'm not suggesting we do that right now for the Vectrex/PiTrex, but I wanted to get my thoughts in writing, and come back to it some day...
G
The ARM in the PiTrex (it's a Pi Zero piggybacked on top of the PiTrex board) emulates the CPU of a 6809 Vectrex but uses all of the Vectrex's real devices and peripherals.
If all goes well, this means it can act identically to the Vectrex itself, when running Vectrex code - as long as the emulated timing matches the native 6809 timing. This is how we make the PiTrex behave like a multicart... (the pitrex cart hardware is too simple to allow the 6809 to load rom data from it directly, so we halt the 6809 and let the ARM do the work, since it has direct access to the SD on the Pi Zero...)
Malban has done really well given the constraints of a traditional emulator structure and the emulation looks absolutely perfect, but when we get to emulating various peripherals, it may be that a traditional instruction-stepped emulator is going to have problems when real hardware devices (such as the 3D imager) have to perform actions at specific times within an instruction cycle.
There is a method of writing emulators that works in these circumstances, but at the moment it is only used by FPGA implementations of CPUs or (as far as I know) in only one soft emulator, the 6502 at floooh.github.io/2019/12/13/cycle-stepped-6502.html - worth a read if you haven't seen it before...
So... here's a crude sketch of a cycle-ticked 6809 emulator...
m6809_t *cpu = init_6809();
hires_clock_t now = hires_timer();
// E is the external clock that drives the system...
for(;;) {
cpu->pins->E = 1;
wait_until_realtime(now+HALF_CLOCK_CYCLE);
// tick the CPU for one half clock cycle
m6809_tick(&cpu); // do any state changes that are triggered on falling E
cpu->pins->E = 0;
wait_until_realtime(now+CLOCK_CYCLE);
// tick the CPU for one half clock cycle
m6809_tick(&cpu); // do any state changes that are triggered on rising E
now += CLOCK_CYCLE;
}
Unfortunately, our existing emulator (based on vecx) may be cycle-counting, but it is instruction-ticked rather than cycle-ticked, but we can fake cycle-ticking by not doing anything in the emulation procedure for the other clock cycles, eg something like this...
int emulate_m6809_instruction(m6809_t *cpu) {
// standard emulator, returns cycles used
}
void m6809_tick(m6809_t *cpu) {
switch (cpu->half_clock_ticks_remaining) {
case 0: cpu->half_clock_ticks = emulate_m6809_instruction(cpu) * 2;
break;
case 1: cpu->half_clock_ticks_remaining -= 1;
break;
case 2: cpu->half_clock_ticks_remaining -= 1;
break;
case 3: cpu->half_clock_ticks_remaining -= 1;
break;
// ... up to max number of clock edges used by any instruction...
default: cpu->half_clock_ticks_remaining -= 1;
break;
}
}
Clearly this isn't *really* a cycle-stepped emulation, because everything happens at the very first clock tick when executing each instruction, and the CPU sits idle and no pins change on the subsequent clock ticks when inputs and outputs should be changing, but at least now the framework is in place.
But... at this point you can identify the few instructions where cycle-accuracy is required and migrate those instructions from being instruction-ticked to being cycle-ticked, leaving ones where it is not critical to be executed the old way, and thus migrate an existing emulator slowly without breaking it... With enough effort such an emulator might eventually become genuinely cycle-ticked completely.
I'm not suggesting we do that right now for the Vectrex/PiTrex, but I wanted to get my thoughts in writing, and come back to it some day...
G