Added first draft of Runtime class
This commit is contained in:
parent
678bbf6381
commit
9a8d7d15a3
11 changed files with 449 additions and 33 deletions
|
|
@ -35,6 +35,9 @@ list(APPEND RUNTIME_SOURCE_FILES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/RAM.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/RAM.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/BUS.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/BUS.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/MMU.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/MMU.cpp
|
||||||
|
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/runtime/Runtime.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/runtime/ConfigLoader.cpp
|
||||||
)
|
)
|
||||||
list(APPEND DEBUGGER_SOURCE_FILES
|
list(APPEND DEBUGGER_SOURCE_FILES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/debugger/debugger_main.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/debugger/debugger_main.cpp
|
||||||
|
|
@ -43,6 +46,9 @@ list(APPEND DEBUGGER_SOURCE_FILES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/RAM.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/RAM.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/BUS.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/BUS.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hardware/MMU.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/hardware/MMU.cpp
|
||||||
|
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/runtime/Runtime.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/runtime/ConfigLoader.cpp
|
||||||
)
|
)
|
||||||
list(APPEND ASSEMBLER_SOURCE_FILES
|
list(APPEND ASSEMBLER_SOURCE_FILES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/assembler/assembler_main.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/assembler/assembler_main.cpp
|
||||||
|
|
|
||||||
2
build
2
build
|
|
@ -61,7 +61,7 @@ else
|
||||||
printf "\n\033[0;32mRunning DragonV2 runtime...\n\n\033[0m"
|
printf "\n\033[0;32mRunning DragonV2 runtime...\n\n\033[0m"
|
||||||
cd bin
|
cd bin
|
||||||
# ./reload_env.sh
|
# ./reload_env.sh
|
||||||
./dvm config/testMachine.dvm
|
./dvm config/testMachine.dvm --verbose-load
|
||||||
# backtrack_changes
|
# backtrack_changes
|
||||||
cd ..
|
cd ..
|
||||||
elif [[ "$1" == "ddb" ]]; then
|
elif [[ "$1" == "ddb" ]]; then
|
||||||
|
|
|
||||||
14
extra/config/testMachine.dvm
Normal file
14
extra/config/testMachine.dvm
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
Disks = dragon/disk1.dr
|
||||||
|
Bios = dragon/bios.bin
|
||||||
|
CMOS = dragon/cmos.dr
|
||||||
|
|
||||||
|
cpuext = extmov, extalu
|
||||||
|
fixed_clock = true
|
||||||
|
clock_rate_sec = 5000
|
||||||
|
memory_extension_pages = 16
|
||||||
|
|
||||||
|
screen_redraw_rate_per_second = 10
|
||||||
|
|
||||||
|
SingleColor_foreground = #009900FF
|
||||||
|
SingleColor_background = #111111FF
|
||||||
|
16Color_Palette = 0
|
||||||
|
|
@ -1 +1 @@
|
||||||
13
|
14
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,19 @@ namespace dragon
|
||||||
using PhysicalAddress = AddressType;
|
using PhysicalAddress = AddressType;
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
|
|
||||||
|
class MemoryMapAddresses
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline static constexpr AddressType BIOS_Start = 0x0000'0000;
|
||||||
|
inline static constexpr AddressType BIOS_End = 0x0001'0000; // 1 MiB
|
||||||
|
|
||||||
|
inline static constexpr AddressType CMOS_Start = 0x0001'0000;
|
||||||
|
inline static constexpr AddressType CMOS_End = 0x0001'1000; // 4 KiB
|
||||||
|
|
||||||
|
inline static constexpr AddressType Memory_Start = 0x0004'0000; // 4 Gib - 4 Mib
|
||||||
|
inline static constexpr AddressType Memory_End = 0xFFFF'FFFF;
|
||||||
|
};
|
||||||
|
|
||||||
enum class RegAccess {
|
enum class RegAccess {
|
||||||
UserReadWrite, // FL (if you split out I)
|
UserReadWrite, // FL (if you split out I)
|
||||||
UserReadOnly, // CORE_ID, CYCLE
|
UserReadOnly, // CORE_ID, CYCLE
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,7 @@ namespace dragon
|
||||||
// Core
|
// Core
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
|
|
||||||
Core::Core(CPU& cpu, BUS& bus, u32 core_id)
|
Core::Core(CPU& cpu, BUS& bus, u32 core_id) : m_cpu(cpu), m_bus(bus), m_coreId(core_id), m_mmu(bus, &m_accessMode)
|
||||||
: m_cpu(cpu)
|
|
||||||
, m_bus(bus)
|
|
||||||
, m_coreId(core_id)
|
|
||||||
, m_mmu(bus, &m_accessMode)
|
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
@ -159,8 +155,7 @@ namespace dragon
|
||||||
// CPU
|
// CPU
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
|
|
||||||
CPU::CPU(BUS& bus, u32 num_cores)
|
CPU::CPU(BUS& bus, u32 num_cores) : m_bus(bus)
|
||||||
: m_bus(bus)
|
|
||||||
{
|
{
|
||||||
m_cores.reserve(num_cores);
|
m_cores.reserve(num_cores);
|
||||||
for (u32 i = 0; i < num_cores; ++i)
|
for (u32 i = 0; i < num_cores; ++i)
|
||||||
|
|
|
||||||
69
src/runtime/ConfigLoader.cpp
Normal file
69
src/runtime/ConfigLoader.cpp
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include "ConfigLoader.hpp"
|
||||||
|
#include <ostd/io/File.hpp>
|
||||||
|
|
||||||
|
namespace dragon
|
||||||
|
{
|
||||||
|
const tMachineConfig MachineConfigLoader::loadConfig(const ostd::String& configFilePath)
|
||||||
|
{
|
||||||
|
tMachineConfig config;
|
||||||
|
ostd::TextFileBuffer file(configFilePath.cpp_str());
|
||||||
|
if (!file.exists()) return config; //TODO: Error
|
||||||
|
auto lines = file.getLines();
|
||||||
|
for (auto& line : lines)
|
||||||
|
{
|
||||||
|
ostd::String lineEdit = line;
|
||||||
|
if (!lineEdit.contains("=")) continue; //TODO: Warning
|
||||||
|
auto tokens = lineEdit.tokenize("=");
|
||||||
|
if (tokens.count() != 2) continue; //TODO: Warning
|
||||||
|
lineEdit = tokens.next();
|
||||||
|
lineEdit = lineEdit.toLower();
|
||||||
|
if (lineEdit == "disks")
|
||||||
|
{
|
||||||
|
lineEdit = tokens.next();
|
||||||
|
tokens = lineEdit.tokenize(",");
|
||||||
|
if (tokens.count() == 0) continue; //TODO: Warning
|
||||||
|
int32_t disk_nr = 0;
|
||||||
|
while (tokens.hasNext())
|
||||||
|
{
|
||||||
|
lineEdit = tokens.next();
|
||||||
|
config.vdisk_paths[disk_nr++] = lineEdit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lineEdit == "bios")
|
||||||
|
{
|
||||||
|
lineEdit = tokens.next();
|
||||||
|
config.bios_path = lineEdit;
|
||||||
|
}
|
||||||
|
else if (lineEdit == "cmos")
|
||||||
|
{
|
||||||
|
lineEdit = tokens.next();
|
||||||
|
config.cmos_path = lineEdit;
|
||||||
|
}
|
||||||
|
else if (lineEdit == "clock_rate_sec")
|
||||||
|
{
|
||||||
|
lineEdit = tokens.next();
|
||||||
|
lineEdit.trim().toLower();
|
||||||
|
if (!lineEdit.isNumeric()) continue; //TODO: Error
|
||||||
|
config.clock_rate_sec = lineEdit.toInt();
|
||||||
|
}
|
||||||
|
else if (lineEdit == "fixed_clock")
|
||||||
|
{
|
||||||
|
lineEdit = tokens.next();
|
||||||
|
lineEdit.trim().toLower();
|
||||||
|
if (lineEdit == "true")
|
||||||
|
config.fixed_clock = true;
|
||||||
|
else if (lineEdit == "false")
|
||||||
|
config.fixed_clock = false;
|
||||||
|
else continue; //TODO: Error
|
||||||
|
}
|
||||||
|
else continue; //TODO: Warning
|
||||||
|
}
|
||||||
|
return validate_machine_config(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tMachineConfig& MachineConfigLoader::validate_machine_config(tMachineConfig& config) //TODO: Implement config validation
|
||||||
|
{
|
||||||
|
config.m_valid = true;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/runtime/ConfigLoader.hpp
Normal file
32
src/runtime/ConfigLoader.hpp
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostd/data/Color.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace dragon
|
||||||
|
{
|
||||||
|
struct tMachineConfig
|
||||||
|
{
|
||||||
|
std::map<int32_t, ostd::String> vdisk_paths;
|
||||||
|
int32_t clock_rate_sec { 500 };
|
||||||
|
bool fixed_clock { true };
|
||||||
|
ostd::String bios_path;
|
||||||
|
ostd::String cmos_path;
|
||||||
|
|
||||||
|
inline bool isValid(void) const { return m_valid; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_valid { false };
|
||||||
|
|
||||||
|
friend class MachineConfigLoader;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MachineConfigLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const tMachineConfig loadConfig(const ostd::String& configFilePath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const tMachineConfig& validate_machine_config(tMachineConfig& config);
|
||||||
|
};
|
||||||
|
}
|
||||||
238
src/runtime/Runtime.cpp
Normal file
238
src/runtime/Runtime.cpp
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
#include "Runtime.hpp"
|
||||||
|
#include <ogfx/render/PixelRenderer.hpp>
|
||||||
|
#include <ostd/io/Memory.hpp>
|
||||||
|
#include <ostd/utils/Time.hpp>
|
||||||
|
|
||||||
|
namespace dragon
|
||||||
|
{
|
||||||
|
int32_t DragonRuntime::loadArguments(int argc, char** argv, tCommandLineArgs& args)
|
||||||
|
{
|
||||||
|
ostd::ConsoleOutputHandler out;
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
out.fg(ostd::ConsoleColors::Red).p("Error: too few arguments.").nl();
|
||||||
|
out.fg(ostd::ConsoleColors::Red).p("Use the --help option for more info.").reset().nl();
|
||||||
|
return dragon::DragonRuntime::RETURN_VAL_TOO_FEW_ARGUMENTS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
args.machine_config_path = argv[1];
|
||||||
|
if (args.machine_config_path == "--help")
|
||||||
|
{
|
||||||
|
__print_application_help();
|
||||||
|
return DragonRuntime::RETURN_VAL_CLOSE_RUNTIME;
|
||||||
|
}
|
||||||
|
for (int32_t i = 2; i < argc; i++)
|
||||||
|
{
|
||||||
|
ostd::String edit(argv[i]);
|
||||||
|
if (edit == "--verbose-load")
|
||||||
|
args.verbose_load = true;
|
||||||
|
else if (edit == "--force-load")
|
||||||
|
{
|
||||||
|
if ((argc - 1) - i < 2)
|
||||||
|
return RETURN_VAL_MISSING_PARAM;
|
||||||
|
i++;
|
||||||
|
args.force_load_file = argv[i];
|
||||||
|
i++;
|
||||||
|
edit = argv[i];
|
||||||
|
if (!edit.isNumeric())
|
||||||
|
return RETURN_VAL_PARAMETER_NOT_NUMERIC;
|
||||||
|
args.force_load_mem_offset = (AddressType)edit.toInt();
|
||||||
|
args.force_load = true;
|
||||||
|
}
|
||||||
|
else if (edit == "--help")
|
||||||
|
{
|
||||||
|
__print_application_help();
|
||||||
|
return RETURN_VAL_CLOSE_RUNTIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RETURN_VAL_EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t DragonRuntime::initMachine(const ostd::String& configFilePath,
|
||||||
|
bool verbose,
|
||||||
|
bool debugModeEnabled)
|
||||||
|
{
|
||||||
|
ostd::ConsoleOutputHandler out;
|
||||||
|
if (verbose)
|
||||||
|
out.fg(ostd::ConsoleColors::Magenta).p("Loading machine config: ").fg(ostd::ConsoleColors::BrightYellow).p(configFilePath.cpp_str()).nl();
|
||||||
|
machine_config = dragon::MachineConfigLoader::loadConfig(configFilePath);
|
||||||
|
if (!machine_config.isValid()) return RETURN_VAL_INVALID_MACHINE_CONFIG; //TODO: Error
|
||||||
|
|
||||||
|
if (machine_config.vdisk_paths.size() == 0) return RETURN_VAL_NO_DISK; //TODO: Error
|
||||||
|
// if (verbose)
|
||||||
|
// out.fg(ostd::ConsoleColors::Magenta).p(" Initializing virtual disks:").nl();
|
||||||
|
// for (auto const& disk_path : machine_config.vdisk_paths)
|
||||||
|
// {
|
||||||
|
// vDisks[disk_path.first] = dragon::hw::VirtualHardDrive(disk_path.second);
|
||||||
|
// vDiskInterface.connectDisk(vDisks[disk_path.first], disk_path.first);
|
||||||
|
// if (verbose)
|
||||||
|
// out.fg(ostd::ConsoleColors::BrightYellow).p(" Disk").p(disk_path.first).p(" connected: ").p(disk_path.second.cpp_str()).nl();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (verbose)
|
||||||
|
// out.fg(ostd::ConsoleColors::Magenta).p(" Loading vBIOS file: ").fg(ostd::ConsoleColors::BrightYellow).p(machine_config.bios_path.cpp_str()).nl();
|
||||||
|
// vBIOS.init(machine_config.bios_path);
|
||||||
|
|
||||||
|
// if (verbose)
|
||||||
|
// out.fg(ostd::ConsoleColors::Magenta).p(" Loading vCMOS file: ").fg(ostd::ConsoleColors::BrightYellow).p(machine_config.cmos_path.cpp_str()).nl();
|
||||||
|
// vCMOS.init(machine_config.cmos_path);
|
||||||
|
|
||||||
|
// if (verbose)
|
||||||
|
// {
|
||||||
|
// out.fg(ostd::ConsoleColors::Magenta).p(" Initializing BUS:").nl();
|
||||||
|
// out.fg(ostd::ConsoleColors::Magenta).p(" vBIOS: ");
|
||||||
|
// out.fg(ostd::ConsoleColors::BrightYellow);
|
||||||
|
// out.p(ostd::String::getHexStr(dragon::MemoryMapAddresses::BIOS_Start, true, 2).cpp_str());
|
||||||
|
// out.p(" to ");
|
||||||
|
// out.p(ostd::String::getHexStr(dragon::MemoryMapAddresses::BIOS_End, true, 2).cpp_str());
|
||||||
|
// out.p(" (remap=false)").nl();
|
||||||
|
// }
|
||||||
|
// bus.mapDevice(vBIOS, dragon::MemoryMapAddresses::BIOS_Start, dragon::MemoryMapAddresses::BIOS_End, false, "BIOS");
|
||||||
|
// if (verbose)
|
||||||
|
// {
|
||||||
|
// out.fg(ostd::ConsoleColors::Magenta).p(" vCMOS: ");
|
||||||
|
// out.fg(ostd::ConsoleColors::BrightYellow);
|
||||||
|
// out.p(ostd::String::getHexStr(dragon::MemoryMapAddresses::CMOS_Start, true, 2).cpp_str());
|
||||||
|
// out.p(" to ");
|
||||||
|
// out.p(ostd::String::getHexStr(dragon::MemoryMapAddresses::CMOS_End, true, 2).cpp_str());
|
||||||
|
// out.p(" (remap=true)").nl();
|
||||||
|
// }
|
||||||
|
// memMap.mapDevice(vCMOS, dragon::MemoryMapAddresses::CMOS_Start, dragon::MemoryMapAddresses::CMOS_End, true, "CMOS");
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
out.fg(ostd::ConsoleColors::Magenta).p(" RAM: ");
|
||||||
|
out.fg(ostd::ConsoleColors::BrightYellow);
|
||||||
|
out.p(ostd::String::getHexStr(dragon::MemoryMapAddresses::Memory_Start, true, 4).cpp_str());
|
||||||
|
out.p(" to ");
|
||||||
|
out.p(ostd::String::getHexStr(dragon::MemoryMapAddresses::Memory_End, true, 4).cpp_str());
|
||||||
|
out.p(" (remap=false)").nl();
|
||||||
|
}
|
||||||
|
bus.mapDevice(ram, dragon::MemoryMapAddresses::Memory_Start, dragon::MemoryMapAddresses::Memory_End, false, "RAM");
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
out.fg(ostd::ConsoleColors::BrightYellow).p(" Fixed clock enabled: ").p(STR_BOOL(machine_config.fixed_clock)).nl();
|
||||||
|
if (machine_config.fixed_clock)
|
||||||
|
out.fg(ostd::ConsoleColors::BrightYellow).p(" Clock speed: ").p(machine_config.clock_rate_sec).p(" Hz").nl();
|
||||||
|
}
|
||||||
|
|
||||||
|
// vCMOS.write16(CMOSRegisters::MemoryStart, MemoryMapAddresses::Memory_Start);
|
||||||
|
// vCMOS.write16(CMOSRegisters::MemorySize, MemoryMapAddresses::Memory_End);
|
||||||
|
// vCMOS.write16(CMOSRegisters::ClockSpeed, machine_config.clock_rate_sec);
|
||||||
|
// vCMOS.write8(CMOSRegisters::ScreenRedrawRate, machine_config.screen_redraw_rate_per_second);
|
||||||
|
// vCMOS.write16(CMOSRegisters::ScreenWidth, static_cast<int16_t>(ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H));
|
||||||
|
// vCMOS.write16(CMOSRegisters::ScreenHeight, static_cast<int16_t>(ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_V));
|
||||||
|
// vCMOS.write16(CMOSRegisters::StackSize, 0x1000);
|
||||||
|
// ostd::BitField_16 disk_list_bitfield;
|
||||||
|
// disk_list_bitfield.value = 0;
|
||||||
|
// for (int32_t i = 0; i < 16; i++)
|
||||||
|
// {
|
||||||
|
// if (vDisks.count(i) > 0)
|
||||||
|
// ostd::Bits::set(disk_list_bitfield, i);
|
||||||
|
// }
|
||||||
|
// vCMOS.write16(CMOSRegisters::DiskList, disk_list_bitfield.value);
|
||||||
|
// if (verbose)
|
||||||
|
// out.fg(ostd::ConsoleColors::BrightYellow).p(" Loading CMOS Machine info").nl();
|
||||||
|
|
||||||
|
out.nl().nl();
|
||||||
|
return RETURN_VAL_EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragonRuntime::runMachine(void)
|
||||||
|
{
|
||||||
|
cpu.run(); //TODO: CPU needs to run a single step, not have an internal loop
|
||||||
|
// double clock_speed_us = 1000000.0 / machine_config.clock_rate_sec;
|
||||||
|
// double acc = 0;
|
||||||
|
// double acc2 = 0;
|
||||||
|
// uint64_t avg_count = 0;
|
||||||
|
// uint64_t _time = 0;
|
||||||
|
// double avg_tot = 0;
|
||||||
|
// ostd::Counter clock_timer;
|
||||||
|
// bool running = true;
|
||||||
|
// bool fixed_clock = machine_config.fixed_clock;
|
||||||
|
// ostd::Counter _timer;
|
||||||
|
// while (running)
|
||||||
|
// {
|
||||||
|
// clock_timer.startCount(ostd::eTimeUnits::Microseconds);
|
||||||
|
// ostd::SignalHandler::handleDelegateSignals();
|
||||||
|
// AddressType addr = cpu.readRegister(dragon::Registers::IP);
|
||||||
|
// AddressType spAddr = cpu.readRegister(dragon::Registers::SP);
|
||||||
|
// uint8_t screenRedrawRate = vCMOS.read8(CMOSRegisters::ScreenRedrawRate);
|
||||||
|
// running = cpu.execute() && vDisplay.isRunning();
|
||||||
|
// if (acc == 500)
|
||||||
|
// {
|
||||||
|
// avg_count++;
|
||||||
|
// avg_tot += _time;
|
||||||
|
// s_avgInstTime = (uint64_t)std::round(avg_tot / avg_count);
|
||||||
|
// // out.fg(ostd::ConsoleColors::Red).p(getAvgClockSpeed()).nl().reset();
|
||||||
|
// acc = 0;
|
||||||
|
// }
|
||||||
|
// _time = clock_timer.endCount();
|
||||||
|
// acc++;
|
||||||
|
// acc2++;
|
||||||
|
// if (_time < clock_speed_us && fixed_clock)
|
||||||
|
// ostd::Time::sleep(clock_speed_us - _time, ostd::eTimeUnits::Microseconds);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DragonRuntime::runStep(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
// std::sort(trackedAddresses.begin(), trackedAddresses.end());
|
||||||
|
// __get_machine_footprint(&s_machineInfo, trackedAddresses, true);
|
||||||
|
// __track_call_stack(&s_machineInfo);
|
||||||
|
// bool running = cpu.execute() && vDisplay.isRunning();
|
||||||
|
// uint8_t screenRedrawRate = vCMOS.read8(CMOSRegisters::ScreenRedrawRate);
|
||||||
|
// vDisplay.mainLoop();
|
||||||
|
// if (s_enableScreenRedrawDelay && s_stepAcc2 == (1000.0 / screenRedrawRate))
|
||||||
|
// {
|
||||||
|
// vDisplay.redrawScreen();
|
||||||
|
// s_stepAcc2 = 0;
|
||||||
|
// }
|
||||||
|
// else if (!s_enableScreenRedrawDelay)
|
||||||
|
// {
|
||||||
|
// vDisplay.redrawScreen();
|
||||||
|
// }
|
||||||
|
// s_stepAcc2++;
|
||||||
|
// // vDisplay.redrawScreen(); // This is slow...maybe it should be on a 100ms rate, like in normal runtime mode
|
||||||
|
// vDiskInterface.cycleStep();
|
||||||
|
// __get_machine_footprint(&s_machineInfo, trackedAddresses, false);
|
||||||
|
// return running || vDiskInterface.isBusy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragonRuntime::forceLoad(const ostd::String& filePath, AddressType loadAddress)
|
||||||
|
{
|
||||||
|
ostd::ByteStream code;
|
||||||
|
ostd::Memory::loadByteStreamFromFile(filePath, code);
|
||||||
|
|
||||||
|
int16_t index = 0;
|
||||||
|
for (auto& b : code)
|
||||||
|
{
|
||||||
|
ram.store_i8(dragon::MemoryMapAddresses::Memory_Start + loadAddress + index, b);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragonRuntime::__print_application_help(void)
|
||||||
|
{
|
||||||
|
ostd::ConsoleOutputHandler out;
|
||||||
|
|
||||||
|
int32_t commandLength = 46;
|
||||||
|
|
||||||
|
out.nl().fg(ostd::ConsoleColors::Yellow).p("List of available parameters:").reset().nl();
|
||||||
|
ostd::String tmpCommand = "--verbose-load";
|
||||||
|
tmpCommand.addRightPadding(commandLength);
|
||||||
|
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Used to show more information while loading the virtual machine.").reset().nl();
|
||||||
|
tmpCommand = "--force-load <binary-file> <ram-offset>";
|
||||||
|
tmpCommand.addRightPadding(commandLength);
|
||||||
|
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Injects the specified binary into RAM at the specified offset.").reset().nl();
|
||||||
|
tmpCommand = "--help";
|
||||||
|
tmpCommand.addRightPadding(commandLength);
|
||||||
|
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Displays this help message.").reset().nl();
|
||||||
|
|
||||||
|
out.nl().fg(ostd::ConsoleColors::Magenta).p("Usage: ./dvm <machine-config-file> [...options...]").reset().nl();
|
||||||
|
out.nl();
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/runtime/Runtime.hpp
Normal file
53
src/runtime/Runtime.hpp
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../hardware/CPU.hpp"
|
||||||
|
#include "../hardware/RAM.hpp"
|
||||||
|
#include "ConfigLoader.hpp"
|
||||||
|
|
||||||
|
namespace dragon
|
||||||
|
{
|
||||||
|
class DragonRuntime
|
||||||
|
{
|
||||||
|
public: struct tCommandLineArgs
|
||||||
|
{
|
||||||
|
ostd::String machine_config_path = "";
|
||||||
|
bool verbose_load = false;
|
||||||
|
bool force_load = false;
|
||||||
|
ostd::String force_load_file = "";
|
||||||
|
uint16_t force_load_mem_offset = 0x00;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
static int32_t loadArguments(int argc, char** argv, tCommandLineArgs& args);
|
||||||
|
static int32_t initMachine(const ostd::String& configFilePath,
|
||||||
|
bool verbose = false,
|
||||||
|
bool debugModeEnabled = false);
|
||||||
|
static void runMachine(void);
|
||||||
|
static bool runStep(void);
|
||||||
|
static void forceLoad(const ostd::String& filePath, AddressType loadAddress);
|
||||||
|
|
||||||
|
inline static uint64_t getAvgClockSpeed(void) { return (uint64_t)std::round(1000000.0 / s_avgInstTime); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void __print_application_help(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline static hw::BUS bus;
|
||||||
|
inline static hw::CPU cpu { bus, 4 }; //TODO: hardcoded 4 cores, need a way to load core count from config file
|
||||||
|
inline static hw::RAM ram { 0xFFFFFF }; //TODO: 16 MiB hardcoded, need a way to configure from config file
|
||||||
|
|
||||||
|
inline static tMachineConfig machine_config;
|
||||||
|
|
||||||
|
inline static uint64_t s_avgInstTime { 0 };
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline static const int32_t RETURN_VAL_CLOSE_DEBUGGER = 128;
|
||||||
|
inline static const int32_t RETURN_VAL_CLOSE_RUNTIME = 256;
|
||||||
|
inline static const int32_t RETURN_VAL_INVALID_MACHINE_CONFIG = 1;
|
||||||
|
inline static const int32_t RETURN_VAL_NO_DISK = 2;
|
||||||
|
inline static const int32_t RETURN_VAL_TOO_FEW_ARGUMENTS = 3;
|
||||||
|
inline static const int32_t RETURN_VAL_MISSING_PARAM = 4;
|
||||||
|
inline static const int32_t RETURN_VAL_PARAMETER_NOT_NUMERIC = 5;
|
||||||
|
inline static const int32_t RETURN_VAL_EXIT_SUCCESS = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,28 +1,24 @@
|
||||||
/*
|
#include <ostd/utils/Defines.hpp>
|
||||||
DragonV2 - A collection of useful functionality
|
#include "Runtime.hpp"
|
||||||
Copyright (C) 2026 OmniaX-Dev
|
|
||||||
|
|
||||||
This file is part of DragonV2.
|
|
||||||
|
|
||||||
DragonV2 is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
DragonV2 is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with DragonV2. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ostd/ostd.hpp>
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
ostd::ConsoleOutputHandler out;
|
//Loading commandline arguments
|
||||||
out.fg(ostd::ConsoleColors::Green).p("TODO: Runtime!!").nl().reset();
|
dragon::DragonRuntime::tCommandLineArgs args;
|
||||||
return 0;
|
int32_t rValue = dragon::DragonRuntime::loadArguments(argc, argv, args);
|
||||||
|
if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_RUNTIME)
|
||||||
|
return 0;
|
||||||
|
if (rValue != 0) return rValue;
|
||||||
|
|
||||||
|
//Initializing the runtime
|
||||||
|
rValue = dragon::DragonRuntime::initMachine(args.machine_config_path, args.verbose_load);
|
||||||
|
if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_RUNTIME)
|
||||||
|
return 0;
|
||||||
|
if (rValue != 0) return rValue;
|
||||||
|
|
||||||
|
//Executing the runtime
|
||||||
|
if (args.force_load)
|
||||||
|
dragon::DragonRuntime::forceLoad(args.force_load_file, args.force_load_mem_offset);
|
||||||
|
dragon::DragonRuntime::runMachine();
|
||||||
|
return dragon::DragonRuntime::RETURN_VAL_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue