added loading

This commit is contained in:
zanostro 2025-11-17 15:21:25 +01:00
parent 598865d216
commit 7b79c35f63
8 changed files with 84 additions and 14 deletions

View file

@ -46,3 +46,15 @@ message(STATUS "Output directory: ${OUTPUT_DIR}")
if(EXISTS "${CMAKE_SOURCE_DIR}/gui/qt/CMakeLists.txt") if(EXISTS "${CMAKE_SOURCE_DIR}/gui/qt/CMakeLists.txt")
add_subdirectory(gui/qt) add_subdirectory(gui/qt)
endif() endif()
# Copy resources directory (if present) to target/res so build output includes them
if(EXISTS "${CMAKE_SOURCE_DIR}/res")
add_custom_target(copy_resources
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/target/res
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/res ${CMAKE_SOURCE_DIR}/target/res
COMMENT "Copying resources from res/ to target/res/"
)
if(TARGET simulator_exec)
add_dependencies(simulator_exec copy_resources)
endif()
endif()

View file

@ -26,7 +26,7 @@ build: configure
run: build run: build
@echo "Running primary target..." @echo "Running primary target..."
# Prefer GUI if available, otherwise fall back to console executable # Prefer GUI if avail able, otherwise fall back to console executable
@if [ -x "$(GUI_TARGET)" ]; then \ @if [ -x "$(GUI_TARGET)" ]; then \
echo "Launching GUI: $(GUI_TARGET)"; \ echo "Launching GUI: $(GUI_TARGET)"; \
sh -c 'nohup env QT_QPA_PLATFORM=xcb ./$(GUI_TARGET) >/dev/null 2>&1 & echo $! > "$(BUILD_DIR)/simulator_qt.pid"'; \ sh -c 'nohup env QT_QPA_PLATFORM=xcb ./$(GUI_TARGET) >/dev/null 2>&1 & echo $! > "$(BUILD_DIR)/simulator_qt.pid"'; \

View file

@ -4,6 +4,8 @@
#include "../../include/machine.h" #include "../../include/machine.h"
#include "../../include/instructions.h" #include "../../include/instructions.h"
#include "../../include/opcode.h" #include "../../include/opcode.h"
#include "../../include/constants.h"
#include "../../../include/loader.h"
#include <QIntValidator> #include <QIntValidator>
#include <QLineEdit> #include <QLineEdit>
@ -16,6 +18,10 @@
#include <QLabel> #include <QLabel>
#include <QFont> #include <QFont>
class Loader;
std::shared_ptr<Loader> g_loader;
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui(new Ui::MainWindow), ui(new Ui::MainWindow),
@ -93,7 +99,9 @@ MainWindow::MainWindow(QWidget *parent) :
setupMemoryDisplay(); setupMemoryDisplay();
setupDisassemblyDisplay(); setupDisassemblyDisplay();
loadDemoProgram(); //loadDemoProgram();
g_loader = std::make_shared<Loader>(machine(), std::string(PATH_RESOURCES) + "demo_program.obj");
g_loader->load();
updateRegisterDisplays(); updateRegisterDisplays();
updateMemoryDisplay(); updateMemoryDisplay();

View file

@ -1,6 +1,7 @@
#ifndef CONSTANTS_H #ifndef CONSTANTS_H
#define CONSTANTS_H #define CONSTANTS_H
#include <string>
// ============================== // ==============================
// SIC/XE Architecture Constants // SIC/XE Architecture Constants
// ============================== // ==============================
@ -39,5 +40,13 @@ constexpr int BIT_E_MASK = 0x10; // mask for e bit in F4 and F3 instructions
constexpr bool USE_EXTENDED_MODE = true; constexpr bool USE_EXTENDED_MODE = true;
constexpr int VECTOR_REG_SIZE = 4; constexpr int VECTOR_REG_SIZE = 4;
/* if structure is
/target/
|-> bin/simulator_exec
|-> res/
*/
// When running from project root (./target/bin/simulator_exec), resources are in ./target/res/
constexpr char PATH_RESOURCES[] = "./target/res/";
constexpr bool FILE_CONTAINS_WHITE_SPACES = true;
#endif // CONSTANTS_H #endif // CONSTANTS_H

View file

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "file_reader.h" #include "file_reader.h"
#include <stdexcept>
class Machine; class Machine;
@ -16,6 +17,9 @@ class Loader {
public: public:
Loader( shared_ptr<Machine> machine, string filename) : _machine(machine), _filename(filename) { Loader( shared_ptr<Machine> machine, string filename) : _machine(machine), _filename(filename) {
_file_reader = std::make_shared<FileReader>(filename, std::ios::in); _file_reader = std::make_shared<FileReader>(filename, std::ios::in);
if (!_file_reader->good()) {
throw std::runtime_error("Loader: failed to open file: " + filename);
}
} }
~Loader(); ~Loader();

View file

@ -2,6 +2,7 @@
#include "file_reader.h" #include "file_reader.h"
#include "machine.h" #include "machine.h"
#include "constants.h" #include "constants.h"
#include <algorithm>
Loader::~Loader() Loader::~Loader()
{ {
@ -49,15 +50,22 @@ Loader::RecordType Loader::parseRecordType(char c)
Loader::HeaderMetadata Loader::readHeader() Loader::HeaderMetadata Loader::readHeader()
{ {
RecordType type = parseRecordType(static_cast<char>(_file_reader->readByte())); RecordType type = parseRecordType(static_cast<char>(_file_reader->readByte()));
if (type != RecordType::HEADER) { if (type != RecordType::HEADER) {
throw std::runtime_error("Expected HEADER record"); throw std::runtime_error("Expected HEADER record");
} }
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
HeaderMetadata header; HeaderMetadata header;
// Read program name (6 bytes) // Read program name (6 bytes)
header.program_name = _file_reader->readString(6); header.program_name = _file_reader->readString(6);
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
// Read start address (6 hex digits) // Read start address (6 hex digits)
header.start_address = std::stoi(_file_reader->readString(6), nullptr, 16); header.start_address = std::stoi(_file_reader->readString(6), nullptr, 16);
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
// Read length (6 hex digits) // Read length (6 hex digits)
header.length = std::stoi(_file_reader->readString(6), nullptr, 16); header.length = std::stoi(_file_reader->readString(6), nullptr, 16);
// consume newline // consume newline
@ -67,35 +75,40 @@ Loader::HeaderMetadata Loader::readHeader()
Loader::TextRecord Loader::readTextRecord() Loader::TextRecord Loader::readTextRecord()
{ {
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
TextRecord record; TextRecord record;
// Assume 'T' has already been read // Assume 'T' has already been read
record.start_address = std::stoi(_file_reader->readString(6), nullptr, 16); record.start_address = std::stoi(_file_reader->readString(6), nullptr, 16);
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
// Read length (1 byte, 2 hex digits) // Read length (1 byte, 2 hex digits)
int length = std::stoi(_file_reader->readString(2), nullptr, 16); int length = std::stoi(_file_reader->readString(2), nullptr, 16);
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
// Read data bytes
record.data.resize(length); record.data.resize(length);
for(int i = 0; i < length; ++i) { int index = 0;
unsigned char buffer[2]; string byteStr = _file_reader->readLine();
_file_reader->readBytes(buffer, 2); // Remove spaces, newlines, and other whitespace characters
record.data[i] = static_cast<uint8_t>(std::stoi(std::string(reinterpret_cast<char*>(buffer), 2), nullptr, 16)); byteStr.erase(std::remove_if(byteStr.begin(), byteStr.end(), ::isspace), byteStr.end());
for (int i = 0; i < length; ++i) {
std::string byteHex = byteStr.substr(i * 2, 2);
record.data[i] = static_cast<uint8_t>(std::stoi(byteHex, nullptr, 16));
} }
// consume newline return record;
_file_reader->readLine();
} }
Loader::EndRecord Loader::readEndRecord() Loader::EndRecord Loader::readEndRecord()
{ {
EndRecord record; EndRecord record;
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
// Assume 'E' has already been read // Assume 'E' has already been read
std::string addrStr = _file_reader->readString(6); std::string addrStr = _file_reader->readString(6);
if (!addrStr.empty()) { if (!addrStr.empty()) {
record.execution_start_address = std::stoi(addrStr, nullptr, 16); record.execution_start_address = std::stoi(addrStr, nullptr, 16);
} else { } else {
record.execution_start_address = 0; // default start address record.execution_start_address = 0;
} }
// consume newline // consume newline
_file_reader->readLine(); _file_reader->readLine();
@ -106,8 +119,8 @@ bool Loader::load_into_memory(int start_address, const std::vector<uint8_t> &dat
{ {
for(size_t i = 0; i < data.size(); ++i) { for(size_t i = 0; i < data.size(); ++i) {
int addr = start_address + static_cast<int>(i); int addr = start_address + static_cast<int>(i);
if (addr < 0 || addr >= MEMORY_SIZE) { // 24-bit address space if (addr < 0 || addr >= MEMORY_SIZE) {
return false; // Address out of bounds return false;
} }
_machine->setByte(addr, data[i]); _machine->setByte(addr, data[i]);
} }

View file

@ -5,6 +5,8 @@
#include "file_device.h" #include "file_device.h"
#include "opcode.h" #include "opcode.h"
#include "instructions.h" #include "instructions.h"
#include "constants.h"
#include "loader.h"
using std::cout; using std::cout;
using std::endl; using std::endl;
@ -17,6 +19,7 @@ struct VectorAddProgram {
int main() int main()
{ {
/*
loadInstructionSet(); loadInstructionSet();
Machine machine; Machine machine;
cout << "SIC/XE Program: Accumulator Loop" << endl; cout << "SIC/XE Program: Accumulator Loop" << endl;
@ -88,6 +91,20 @@ int main()
int val = machine.getWord(VR_ADDR + i * 3); int val = machine.getWord(VR_ADDR + i * 3);
cout << val << (i + 1 < VECTOR_REG_SIZE ? ", " : "\n"); cout << val << (i + 1 < VECTOR_REG_SIZE ? ", " : "\n");
} }
*/
loadInstructionSet();
std::shared_ptr<Machine> machine = std::make_shared<Machine>();
Loader loader(machine, std::string(PATH_RESOURCES) + "test.obj");
loader.load();
machine->execute();
machine->execute();
machine->execute();
machine->execute();
machine->execute();
machine->execute();
cout << "Register A after execution: " << machine->getA() << endl;
return 0; return 0;
} }

7
test.asm Normal file
View file

@ -0,0 +1,7 @@
test START 0
LDA #1
LDB #2
ADDR B, A
halt J halt
END test