From 5a06b2bc0baa08d5b6d48b868ded69bc5f668dd0 Mon Sep 17 00:00:00 2001 From: privsk Date: Thu, 27 Nov 2025 08:17:43 +0100 Subject: [PATCH] created basic simulator --- ass2/Device.cpp | 12 +++ ass2/Device.h | 15 +++ ass2/FileDevice.cpp | 44 ++++++++ ass2/FileDevice.h | 22 ++++ ass2/InputDevice.cpp | 13 +++ ass2/InputDevice.h | 16 +++ ass2/Machine.cpp | 234 ++++++++++++++++++++++++++++++++++++++++++ ass2/Machine.h | 73 +++++++++++++ ass2/Opcode.h | 67 ++++++++++++ ass2/OutputDevice.cpp | 10 ++ ass2/OutputDevice.h | 19 ++++ ass2/main.cpp | 16 +++ 12 files changed, 541 insertions(+) create mode 100644 ass2/Device.cpp create mode 100644 ass2/Device.h create mode 100644 ass2/FileDevice.cpp create mode 100644 ass2/FileDevice.h create mode 100644 ass2/InputDevice.cpp create mode 100644 ass2/InputDevice.h create mode 100644 ass2/Machine.cpp create mode 100644 ass2/Machine.h create mode 100644 ass2/Opcode.h create mode 100644 ass2/OutputDevice.cpp create mode 100644 ass2/OutputDevice.h create mode 100644 ass2/main.cpp diff --git a/ass2/Device.cpp b/ass2/Device.cpp new file mode 100644 index 0000000..1d40bfe --- /dev/null +++ b/ass2/Device.cpp @@ -0,0 +1,12 @@ +#include "Device.h" + +bool Device::test() const { + return true; +} + +uint8_t Device::read() { + return 0; +} + +void Device::write(uint8_t value) { +} diff --git a/ass2/Device.h b/ass2/Device.h new file mode 100644 index 0000000..ad1e23f --- /dev/null +++ b/ass2/Device.h @@ -0,0 +1,15 @@ +#ifndef DEVICE_H +#define DEVICE_H + +#include + +class Device { + public: + virtual ~Device() {} + + virtual bool test() const; + virtual uint8_t read(); + virtual void write(uint8_t value); +}; + +#endif // DEVICE_H diff --git a/ass2/FileDevice.cpp b/ass2/FileDevice.cpp new file mode 100644 index 0000000..8e8441a --- /dev/null +++ b/ass2/FileDevice.cpp @@ -0,0 +1,44 @@ +#include "FileDevice.h" +#include + +FileDevice::FileDevice(const std::string& fname) : filename(fname) { + file.open(filename, std::ios::in | std::ios::out | std::ios::binary); + + if (!file.is_open()) { + file.clear(); + file.open(filename, std::ios::out | std::ios::binary); + file.close(); + file.open(filename, std::ios::in | std::ios::out | std::ios::binary); + } +} + +FileDevice::~FileDevice() { + if (file.is_open()) { + file.close(); + } +} + +bool FileDevice::test() const { + return file.is_open() && file.good(); +} + +uint8_t FileDevice::read() { + char c; + if (file.is_open()) { + if (file.get(c)) { + uint8_t byte = (uint8_t)c; + return byte; + } else { + return 0; + } + } + return 0; +} + +void FileDevice::write(uint8_t value) { + if (file.is_open()) { + char c = (char)value; + file.put(c); + file.flush(); + } +} diff --git a/ass2/FileDevice.h b/ass2/FileDevice.h new file mode 100644 index 0000000..5fcd18f --- /dev/null +++ b/ass2/FileDevice.h @@ -0,0 +1,22 @@ +#ifndef FILEDEVICE_H +#define FILEDEVICE_H + +#include "Device.h" +#include +#include + +class FileDevice : public Device { +private: + std::string filename; + std::fstream file; + +public: + FileDevice(const std::string& fname); + ~FileDevice(); + + bool test() const override; + uint8_t read() override; + void write(uint8_t value) override; +}; + +#endif // FILEDEVICE_H diff --git a/ass2/InputDevice.cpp b/ass2/InputDevice.cpp new file mode 100644 index 0000000..26f6b36 --- /dev/null +++ b/ass2/InputDevice.cpp @@ -0,0 +1,13 @@ +#include "InputDevice.h" + +InputDevice::InputDevice(std::istream& in) : input(in) { +} + +uint8_t InputDevice::read() { + char c; + if (input.get(c)) { + uint8_t result = (uint8_t)c; + return result; + } + return 0; +} diff --git a/ass2/InputDevice.h b/ass2/InputDevice.h new file mode 100644 index 0000000..3f7a852 --- /dev/null +++ b/ass2/InputDevice.h @@ -0,0 +1,16 @@ +#ifndef INPUTDEVICE_H +#define INPUTDEVICE_H + +#include "Device.h" +#include + +class InputDevice : public Device { +private: + std::istream& input; + +public: + InputDevice(std::istream& in); + uint8_t read() override; +}; + +#endif // INPUTDEVICE_H diff --git a/ass2/Machine.cpp b/ass2/Machine.cpp new file mode 100644 index 0000000..92a2456 --- /dev/null +++ b/ass2/Machine.cpp @@ -0,0 +1,234 @@ +#include "Machine.h" + +#include +#include + +#include "FileDevice.h" +#include "InputDevice.h" +#include "OutputDevice.h" + +Machine::Machine() { + A = 0; + X = 0; + L = 0; + B = 0; + S = 0; + T = 0; + F = 0.0; + PC = 0; + SW = 0; + + for (int i = 0; i <= MAX_ADDRESS; i++) { + memory[i] = 0; + } + + for (int i = 0; i < MAX_DEVICES; i++) { + devices[i] = nullptr; + } + + devices[0] = new InputDevice(std::cin); + devices[1] = new OutputDevice(std::cout); + devices[2] = new OutputDevice(std::cerr); +} + +Machine::~Machine() { + for (int i = 0; i < MAX_DEVICES; i++) { + if (devices[i] != nullptr) { + delete devices[i]; + devices[i] = nullptr; + } + } +} + +int Machine::getA() const { + return A; +} + +int Machine::getX() const { + return X; +} + +int Machine::getL() const { + return L; +} + +int Machine::getB() const { + return B; +} + +int Machine::getS() const { + return S; +} + +int Machine::getT() const { + return T; +} + +double Machine::getF() const { + return F; +} + +int Machine::getPC() const { + return PC; +} + +int Machine::getSW() const { + return SW; +} + +// mask to 24 bits + +void Machine::setA(int val) { + A = val & 0xFFFFFF; +} + +void Machine::setX(int val) { + X = val & 0xFFFFFF; +} + +void Machine::setL(int val) { + L = val & 0xFFFFFF; +} + +void Machine::setB(int val) { + B = val & 0xFFFFFF; +} + +void Machine::setS(int val) { + S = val & 0xFFFFFF; +} + +void Machine::setT(int val) { + T = val & 0xFFFFFF; +} + +void Machine::setF(double val) { + F = val; +} + +void Machine::setPC(int val) { + PC = val & 0xFFFFFF; +} + +void Machine::setSW(int val) { + SW = val & 0xFFFFFF; +} + +void Machine::setCC_less() { + SW = (SW & 0xFFFF3F) | 0x0; +} + +void Machine::setCC_equal() { + SW = (SW & 0xFFFF3F) | 0x40; +} + +void Machine::setCC_greater() { + SW = (SW & 0xFFFF3F) | 0x80; +} + +int Machine::getCC() const { + return SW & 0xC0; +} + +int Machine::getReg(int reg) const { + switch (reg) { + case 0: + return A; + case 1: + return X; + case 2: + return L; + case 3: + return B; + case 4: + return S; + case 5: + return T; + case 6: + return (int)F; + case 8: + return PC; + case 9: + return SW; + default: + return 0; + } +} + +void Machine::setReg(int reg, int val) { + switch (reg) { + case 0: + setA(val); + break; + case 1: + setX(val); + break; + case 2: + setL(val); + break; + case 3: + setB(val); + break; + case 4: + setS(val); + break; + case 5: + setT(val); + break; + case 6: + setF((double)val); + break; + case 8: + setPC(val); + break; + case 9: + setSW(val); + break; + default: + break; + } +} + +int Machine::getByte(int addr) const { + if (addr < 0 || addr > MAX_ADDRESS) { + return 0; + } + return memory[addr]; +} + +void Machine::setByte(int addr, int val) { + if (addr >= 0 && addr <= MAX_ADDRESS) { + memory[addr] = val & 0xFF; + } +} + +int Machine::getWord(int addr) const { + if (addr < 0 || addr + 2 > MAX_ADDRESS) { + return 0; + } + // big-endian + return (memory[addr] << 16) | (memory[addr + 1] << 8) | memory[addr + 2]; +} + +void Machine::setWord(int addr, int val) { + if (addr >= 0 && addr + 2 <= MAX_ADDRESS) { + val = val & 0xFFFFFF; + // big-endian + memory[addr] = (val >> 16) & 0xFF; + memory[addr + 1] = (val >> 8) & 0xFF; + memory[addr + 2] = val & 0xFF; + } +} + +Device* Machine::getDevice(int num) const { + if (num < 0 || num >= MAX_DEVICES) { + return nullptr; + } + return devices[num]; +} + +void Machine::setDevice(int num, Device* device) { + if (num >= 0 && num < MAX_DEVICES) { + devices[num] = device; + } +} diff --git a/ass2/Machine.h b/ass2/Machine.h new file mode 100644 index 0000000..aef0c7f --- /dev/null +++ b/ass2/Machine.h @@ -0,0 +1,73 @@ +#ifndef MACHINE_H +#define MACHINE_H + +#include + +#include "Device.h" + +const int MAX_ADDRESS = 0xFFFFF; +const int MAX_DEVICES = 256; + +class Machine { + private: + uint8_t memory[MAX_ADDRESS + 1]; + Device* devices[MAX_DEVICES]; + + // registers + int A; // Accumulator (24-bit) + int X; // Index (24-bit) + int L; // Linkage (24-bit) + int B; // Base (24-bit) + int S; // General purpose (24-bit) + int T; // General purpose (24-bit) + double F; // Floating point accumulator (48-bit) + int PC; // Program Counter (24-bit) + int SW; // Status Word (24-bit) + + public: + Machine(); + ~Machine(); + + // getters + int getA() const; + int getX() const; + int getL() const; + int getB() const; + int getS() const; + int getT() const; + double getF() const; + int getPC() const; + int getSW() const; + + // setters + void setA(int val); + void setX(int val); + void setL(int val); + void setB(int val); + void setS(int val); + void setT(int val); + void setF(double val); + void setPC(int val); + void setSW(int val); + + // condition codes for SW + void setCC_less(); + void setCC_equal(); + void setCC_greater(); + int getCC() const; + + // 0=A, 1=X, 2=L, 3=B, 4=S, 5=T, 6=F, 8=PC, 9=SW + int getReg(int reg) const; + void setReg(int reg, int val); + + int getByte(int addr) const; + void setByte(int addr, int val); + + int getWord(int addr) const; + void setWord(int addr, int val); + + Device* getDevice(int num) const; + void setDevice(int num, Device* device); +}; + +#endif // MACHINE_H diff --git a/ass2/Opcode.h b/ass2/Opcode.h new file mode 100644 index 0000000..be71cc4 --- /dev/null +++ b/ass2/Opcode.h @@ -0,0 +1,67 @@ +#ifndef OPCODE_H +#define OPCODE_H + +class Opcode { + public: + static const int ADD = 0x18; + static const int ADDF = 0x58; + static const int ADDR = 0x90; + static const int AND = 0x40; + static const int CLEAR = 0xB4; + static const int COMP = 0x28; + static const int COMPF = 0x88; + static const int COMPR = 0xA0; + static const int DIV = 0x24; + static const int DIVF = 0x64; + static const int DIVR = 0x9C; + static const int FIX = 0xC4; + static const int FLOAT = 0xC0; + static const int HIO = 0xF4; + static const int J = 0x3C; + static const int JEQ = 0x30; + static const int JGT = 0x34; + static const int JLT = 0x38; + static const int JSUB = 0x48; + static const int LDA = 0x00; + static const int LDB = 0x68; + static const int LDCH = 0x50; + static const int LDF = 0x70; + static const int LDL = 0x08; + static const int LDS = 0x6C; + static const int LDT = 0x74; + static const int LDX = 0x04; + static const int LPS = 0xD0; + static const int MUL = 0x20; + static const int MULF = 0x60; + static const int MULR = 0x98; + static const int NORM = 0xC8; + static const int OR = 0x44; + static const int RD = 0xD8; + static const int RMO = 0xAC; + static const int RSUB = 0x4C; + static const int SHIFTL = 0xA4; + static const int SHIFTR = 0xA8; + static const int SIO = 0xF0; + static const int SSK = 0xEC; + static const int STA = 0x0C; + static const int STB = 0x78; + static const int STCH = 0x54; + static const int STF = 0x80; + static const int STI = 0xD4; + static const int STL = 0x14; + static const int STS = 0x7C; + static const int STSW = 0xE8; + static const int STT = 0x84; + static const int STX = 0x10; + static const int SUB = 0x1C; + static const int SUBF = 0x5C; + static const int SUBR = 0x94; + static const int SVC = 0xB0; + static const int TD = 0xE0; + static const int TIO = 0xF8; + static const int TIX = 0x2C; + static const int TIXR = 0xB8; + static const int WD = 0xDC; +}; + +#endif diff --git a/ass2/OutputDevice.cpp b/ass2/OutputDevice.cpp new file mode 100644 index 0000000..6a7d490 --- /dev/null +++ b/ass2/OutputDevice.cpp @@ -0,0 +1,10 @@ +#include "OutputDevice.h" + +OutputDevice::OutputDevice(std::ostream& out) : output(out) { +} + +void OutputDevice::write(uint8_t value) { + char c = (char)value; + output.put(c); + output.flush(); +} diff --git a/ass2/OutputDevice.h b/ass2/OutputDevice.h new file mode 100644 index 0000000..be54f8b --- /dev/null +++ b/ass2/OutputDevice.h @@ -0,0 +1,19 @@ +#ifndef OUTPUTDEVICE_H +#define OUTPUTDEVICE_H + +#include + +#include "Device.h" + +class OutputDevice : public Device { + private: + std::ostream& output; + + public: + OutputDevice(std::ostream& out); + + // override write method to write to output stream + void write(uint8_t value) override; +}; + +#endif // OUTPUTDEVICE_H diff --git a/ass2/main.cpp b/ass2/main.cpp new file mode 100644 index 0000000..f8db1a1 --- /dev/null +++ b/ass2/main.cpp @@ -0,0 +1,16 @@ +#include +#include "Machine.h" + +int main() { + Machine machine; + + machine.setA(0x123456); + machine.setX(0xABCDEF); + machine.setPC(0x1000); + + std::cout << "Register A: 0x" << std::hex << machine.getA() << std::endl; + std::cout << "Register X: 0x" << std::hex << machine.getX() << std::endl; + std::cout << "Program Counter: 0x" << std::hex << machine.getPC() << std::endl; + + return 0; +}