Browse Source

Emu: Add cycle accurate timing

master
Frank 2 years ago
parent
commit
fa066cbd04
  1. 3
      src/cpu.cpp
  2. 20
      src/emu.cpp
  3. 16
      src/emu.h
  4. 15
      src/main.cpp
  5. 3
      src/ppu.cpp

3
src/cpu.cpp

@ -8,7 +8,6 @@
#include <cstdint> // uint8_t, uint32_t #include <cstdint> // uint8_t, uint32_t
#include "cpu.h" #include "cpu.h"
#include "emu.h"
#include "ruc/format/print.h" #include "ruc/format/print.h"
CPU::CPU(uint32_t frequency) CPU::CPU(uint32_t frequency)
@ -28,8 +27,6 @@ void CPU::update()
} }
print("This is an update from the CPU\n"); print("This is an update from the CPU\n");
Emu::the().writeMemory("RAM", 123, 42);
print("fff");
} }
void CPU::add(uint8_t opcode, uint8_t immediate) void CPU::add(uint8_t opcode, uint8_t immediate)

20
src/emu.cpp

@ -7,32 +7,38 @@
void Emu::init(uint32_t frequency) void Emu::init(uint32_t frequency)
{ {
m_frequency = frequency; m_frequency = frequency;
m_timestep = 1.0 / m_frequency * 1000000;
} }
void Emu::update() void Emu::update()
{ {
double time = m_timer.elapsedNanoseconds() / 1000.0;
m_cycle_time += (time - m_previous_time);
m_previous_time = time;
if (m_cycle_time > m_timestep) {
for (auto unit : m_processing_units) { for (auto unit : m_processing_units) {
if (m_cycle % (m_frequency / unit->frequency()) == 0) { if (m_cycle % (m_frequency / unit.second->frequency()) == 0) {
unit->update(); unit.second->update();
} }
} }
m_cycle_time -= m_timestep;
m_cycle++; m_cycle++;
}
} }
void Emu::addProcessingUnit(ProcessingUnit* processing_unit) void Emu::addProcessingUnit(const char* name, ProcessingUnit* processing_unit)
{ {
m_processing_units.push_back(processing_unit); m_processing_units.emplace(name, processing_unit);
} }
void Emu::addMemorySpace(const char* name, uint32_t size) void Emu::addMemorySpace(const char* name, uint32_t size)
{ {
std::vector<uint8_t> memory(size); std::vector<uint32_t> memory(size);
m_memory_spaces.emplace(name, memory); m_memory_spaces.emplace(name, memory);
} }
void Emu::writeMemory(const char* memory_space, uint32_t location, uint8_t value) void Emu::writeMemory(const char* memory_space, uint32_t location, uint32_t value)
{ {
print("{} {} {}\n", memory_space, location, value);
m_memory_spaces[memory_space][location] = value; m_memory_spaces[memory_space][location] = value;
} }

16
src/emu.h

@ -6,6 +6,7 @@
#include "processing-unit.h" #include "processing-unit.h"
#include "ruc/singleton.h" #include "ruc/singleton.h"
#include "ruc/timer.h"
class Emu final : public ruc::Singleton<Emu> { class Emu final : public ruc::Singleton<Emu> {
public: public:
@ -15,17 +16,22 @@ public:
void update(); void update();
void addProcessingUnit(ProcessingUnit* processing_unit); void addProcessingUnit(const char* name, ProcessingUnit* processing_unit);
void addMemorySpace(const char* name, uint32_t size); void addMemorySpace(const char* name, uint32_t size);
void writeMemory(const char* memory_space, uint32_t location, uint8_t value); void writeMemory(const char* memory_space, uint32_t location, uint32_t value);
uint8_t readMemory(const char* memory_space, uint32_t location); uint8_t readMemory(const char* memory_space, uint32_t location);
private: private:
uint32_t m_frequency; uint32_t m_frequency = 0;
double m_timestep = 0;
uint32_t m_cycle = 0; uint32_t m_cycle = 0;
double m_cycle_time = 0;
double m_previous_time = 0;
std::vector<ProcessingUnit*> m_processing_units; ruc::Timer m_timer;
std::unordered_map<const char*, std::vector<uint8_t>> m_memory_spaces;
std::unordered_map<const char*, ProcessingUnit*> m_processing_units;
std::unordered_map<const char*, std::vector<uint32_t>> m_memory_spaces;
}; };

15
src/main.cpp

@ -11,17 +11,20 @@ int main(int argc, char* argv[])
printf("%fms\n", t.elapsedNanoseconds() / 1000000.0); printf("%fms\n", t.elapsedNanoseconds() / 1000000.0);
Emu::the().init(4000000); Emu::the().init(8000000);
CPU cpu(1000000); CPU cpu(8000000);
PPU ppu(2000000); PPU ppu(4000000);
Emu::the().addProcessingUnit(&cpu); Emu::the().addProcessingUnit("cpu", &cpu);
Emu::the().addProcessingUnit(&ppu); Emu::the().addProcessingUnit("ppu", &ppu);
Emu::the().addMemorySpace("RAM", 1024); Emu::the().addMemorySpace("RAM", 1024);
Emu::the().addMemorySpace("VRAM", 1024);
Emu::the().addMemorySpace("ROM", 1024);
Emu::the().addMemorySpace("CARDROM", 1024);
for (int i = 0; i < 1000; i++) { while (true) {
Emu::the().update(); Emu::the().update();
} }

3
src/ppu.cpp

@ -6,6 +6,7 @@
*/ */
#include "ppu.h" #include "ppu.h"
#include "ruc/format/print.h"
#include <iostream> #include <iostream>
PPU ::PPU(unsigned int frequency) PPU ::PPU(unsigned int frequency)
@ -19,5 +20,5 @@ PPU ::~PPU()
void PPU::update() void PPU::update()
{ {
printf("ppu update\n"); print("ppu update\n");
} }

Loading…
Cancel
Save