Skip to content

Commit

Permalink
#43 constant pool vm
Browse files Browse the repository at this point in the history
  • Loading branch information
levBagryansky authored Oct 29, 2023
1 parent 942e6fd commit a3d8a67
Show file tree
Hide file tree
Showing 15 changed files with 541 additions and 367 deletions.
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ CheckOptions:
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
- { key: readability-identifier-naming.FunctionCase, value: camelBack }
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
- { key: readability-identifier-naming.MemberCase, value: lower_case }
- { key: readability-identifier-naming.MemberCase, value: camelBack }
- { key: readability-identifier-naming.MemberSuffix, value: _ }
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
Expand Down
23 changes: 19 additions & 4 deletions bench/codeman-wrapper.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "ChaiVM/interpreter/executor.hpp"
#include "ChaiVM/utils/chai-file.hpp"
#include "ChaiVM/utils/instr2Raw.hpp"

using namespace chai::interpreter;
Expand All @@ -9,16 +10,30 @@ using namespace chai::utils;
class CodeManWrapper {

public:
const std::filesystem::path PATH{"./exec-testing.chai"};

~CodeManWrapper() { std::remove(PATH.c_str()); }

void load(Operation op, RegisterId r1, RegisterId r2 = 0) {
manager_.load(instr2Raw(op, r1, r2));
chaiFile_.addInstr(instr2Raw(op, r1, r2));
}

void loadWithConst(Operation op, int64_t data) {
chaiFile_.addWithConst(op, data);
}

void loadi(Operation op, Immidiate imm) {
manager_.load(instr2Raw(op, imm));
void loadWithConst(Operation op, double data) {
chaiFile_.addWithConst(op, data);
}

void load(Operation op) { manager_.load(instr2Raw(op)); }
void load(Operation op) { chaiFile_.addInstr(instr2Raw(op)); }

void update() {
chaiFile_.toFile(PATH);
manager_.load(PATH);
}

public:
CodeManager manager_;
ChaiFile chaiFile_;
};
8 changes: 4 additions & 4 deletions bench/sin_plus_cos_bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@ static void initSinPlusCos(CodeManWrapper &codeman) {
const RegisterId r3 = 3;
const RegisterId r4 = 4;

assert(sizeof(Immidiate) == sizeof(float));
// r1 = 314, r2 = 271, r3 = 60
codeman.loadi(Ldiaf, std::bit_cast<Immidiate>(314.0f));
codeman.loadWithConst(Ldiaf, 314.0);
codeman.load(Star, r1);
codeman.loadi(Ldiaf, std::bit_cast<Immidiate>(271.0f));
codeman.loadWithConst(Ldiaf, 271.0);
codeman.load(Star, r2);
codeman.loadi(Ldiaf, std::bit_cast<Immidiate>(60.0f));
codeman.loadWithConst(Ldiaf, 60.0);
codeman.load(Star, r3);

// r4 = sin(r3) * r1
Expand All @@ -47,4 +46,5 @@ static void initSinPlusCos(CodeManWrapper &codeman) {
// acc += r4
codeman.load(Addf, r4);
codeman.load(Ret);
codeman.update();
}
13 changes: 7 additions & 6 deletions bench/square_equation_bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ static void initSquareEquatino(CodeManWrapper &codeman) {
const RegisterId r11 = 11;

// r1 = 1.0, r2 = -5.0, r3 = 6.0
codeman.loadi(Ldiaf, std::bit_cast<Immidiate>(1.0f));
codeman.loadWithConst(Ldiaf, 1.0);
codeman.load(Star, r1);
codeman.loadi(Ldiaf, std::bit_cast<Immidiate>(-5.0f));
codeman.loadWithConst(Ldiaf, -5.0);
codeman.load(Star, r2);
codeman.loadi(Ldiaf, std::bit_cast<Immidiate>(+6.0f));
codeman.loadWithConst(Ldiaf, +6.0);
codeman.load(Star, r3);

// r4 = -4*r1*r3
codeman.loadi(Ldiaf, std::bit_cast<Immidiate>(-4.0f));
codeman.loadWithConst(Ldiaf, -4.0);
codeman.load(Mulf, r1);
codeman.load(Mulf, r3);
codeman.load(Star, r4);
Expand All @@ -64,7 +64,7 @@ static void initSquareEquatino(CodeManWrapper &codeman) {

// r7 = 2a
codeman.load(Ldra, r1);
codeman.loadi(chai::interpreter::Mulif, std::bit_cast<Immidiate>(2.0f));
codeman.loadWithConst(chai::interpreter::Mulif, 2.0);
codeman.load(Star, r7);

// r8 = r6 - r2
Expand All @@ -79,10 +79,11 @@ static void initSquareEquatino(CodeManWrapper &codeman) {

// acc = -r2 - r6
// r11 = acc / r7
codeman.load(Ldiaf, std::bit_cast<Immidiate>(0.0f));
codeman.load(Ldiaf, 0.0);
codeman.load(Subf, r2);
codeman.load(Subf, r6);
codeman.load(Divf, r7);
codeman.load(Star, r11);
codeman.load(Ret);
codeman.update();
}
30 changes: 27 additions & 3 deletions include/ChaiVM/interpreter/code-manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,44 @@ namespace chai::interpreter {
/**
* Class to manage bytecode. Similar to ClassLoader.
*/
class CodeManager {
class CodeManager final {
public:
void load(bytecode_t bytecode);
static constexpr int8_t CNST_I64 = 'l';
static constexpr int8_t CNST_F64 = 'd';

void load(std::istream &istream);
/**
* Loads one instruction.
* @param bytecode Raw instruction.
*/
void load(bytecode_t bytecode);

/**
* Parses and loads the full file.
* @param path Path to the .chai file.
*/
void load(const std::filesystem::path &path);

/**
* Loads stream of instructions only.
* @param istream
*/
void loadCode(std::istream &istream);

/**
* Loads stream of Constant pool.
* @param istream
*/
void loadPool(std::istream &istream);

chsize_t getCnst(chsize_t id);

bytecode_t getBytecode(chsize_t pc);

chsize_t startPC();

private:
std::vector<bytecode_t> raw_;
std::vector<chsize_t> constantPool_;
};

class BeyondCodeBoundaries : public std::runtime_error {
Expand Down
2 changes: 1 addition & 1 deletion include/ChaiVM/interpreter/instruction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace chai::interpreter {

using Opcode = uint8_t;
using RegisterId = uint8_t;
using Immidiate = uint32_t;
using Immidiate = uint16_t;

struct Instruction {
Operation operation;
Expand Down
61 changes: 61 additions & 0 deletions include/ChaiVM/utils/chai-file.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#pragma once

#include "constant.hpp"
#include "instr2Raw.hpp"

class ChaiFile {
public:
ChaiFile(std::vector<chai::bytecode_t> &&instrs,
std::vector<std::unique_ptr<Constant>> &&pool)
: rawInstrs_(instrs), pool_(std::move(pool)) {}

ChaiFile()
: ChaiFile(std::vector<chai::bytecode_t>{},
std::vector<std::unique_ptr<Constant>>{}) {}

chai::interpreter::Immidiate addInstr(chai::bytecode_t raw) {
rawInstrs_.push_back(raw);
return rawInstrs_.size() - 1;
}

chai::interpreter::Immidiate
addConst(std::unique_ptr<Constant> &&constant) {
pool_.push_back(std::move(constant));
return pool_.size() - 1;
}

void addWithConst(chai::interpreter::Operation op, int64_t data) {
chai::chsize_t id = addConst(std::make_unique<ConstI64>(data));
addInstr(chai::utils::instr2Raw(op, id));
}

void addWithConst(Operation op, double data) {
chai::chsize_t id = addConst(std::make_unique<ConstF64>(data));
addInstr(chai::utils::instr2Raw(op, id));
}

void toFile(const std::filesystem::path &path) {
std::ofstream ofs(path, std::ios::binary | std::ios::out);
if (ofs.good() && ofs.is_open()) {
Immidiate constants = pool_.size();
ofs.write(reinterpret_cast<const char *>(&constants),
sizeof(constants));
for (const std::unique_ptr<Constant> &cnst : pool_) {
cnst->putType(ofs);
cnst->write(ofs);
}
for (const auto &ins : rawInstrs_) {
ofs.write(reinterpret_cast<const char *>(&ins),
sizeof(chai::bytecode_t));
}
ofs.close();
} else {
throw std::invalid_argument(std::string{"Invalid path "} +
path.string());
}
}

private:
std::vector<chai::bytecode_t> rawInstrs_;
std::vector<std::unique_ptr<Constant>> pool_;
};
40 changes: 40 additions & 0 deletions include/ChaiVM/utils/constant.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include "ChaiVM/interpreter/code-manager.hpp"
#include "ChaiVM/interpreter/instruction.hpp"
#include "ChaiVM/types.hpp"

struct Constant {
void putType(std::ofstream &ofs) { ofs.put(this->getType()); }

virtual void write(std::ofstream &ofs) = 0;
virtual int8_t getType() = 0;
virtual ~Constant() = default;
;
};

struct ConstI64 : public Constant {
int64_t data_;

ConstI64(int64_t data) : data_(data){};

void write(std::ofstream &ofs) override {
ofs.write(reinterpret_cast<const char *>(&data_), sizeof(int64_t));
}
int8_t getType() override {
return chai::interpreter::CodeManager::CNST_I64;
}
~ConstI64() override = default;
};

struct ConstF64 : public Constant {
double data_;
ConstF64(double data) : data_(data){};
void write(std::ofstream &ofs) override {
ofs.write(reinterpret_cast<const char *>(&data_), sizeof(double));
}
int8_t getType() override {
return chai::interpreter::CodeManager::CNST_F64;
}
~ConstF64() override = default;
};
48 changes: 43 additions & 5 deletions src/ChaiVM/interpreter/code-manager.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#include <bit>
#include <cassert>

#include "ChaiVM/interpreter/code-manager.hpp"

namespace chai::interpreter {

void CodeManager::load(bytecode_t bytecode) { raw_.push_back(bytecode); }

void CodeManager::load(std::istream &istream) {
void CodeManager::loadCode(std::istream &istream) {
if (!istream.good()) {
throw std::invalid_argument(std::string{"Bad input stream"});
}
Expand All @@ -15,17 +18,52 @@ void CodeManager::load(std::istream &istream) {
}
}

void CodeManager::loadPool(std::istream &istream) {
if (!istream.good()) {
throw std::invalid_argument(std::string{"Bad input stream"});
}
Immidiate constants = 0;
istream.read(reinterpret_cast<char *>(&constants), sizeof constants);
for (int i = 0; i < constants; ++i) {
char type;
istream.read(&type, sizeof type);
switch (type) {
case CNST_I64:
int64_t next_long;
istream.read(reinterpret_cast<char *>(&next_long),
sizeof next_long);
constantPool_.push_back(next_long);
break;
case CNST_F64:
double next_d;
istream.read(reinterpret_cast<char *>(&next_d), sizeof next_d);
constantPool_.push_back(std::bit_cast<chsize_t>(next_d));
break;
default:
throw std::invalid_argument(std::string{"Type cannot be "} +
std::to_string(type));
break;
}
}
}

void CodeManager::load(const std::filesystem::path &path) {
std::ifstream inputFile(path, std::ios::binary | std::ios::in);
if (inputFile.good() && inputFile.is_open()) {
load(inputFile);
inputFile.close();
std::ifstream input_file(path, std::ios::binary | std::ios::in);
if (input_file.good() && input_file.is_open()) {
loadPool(input_file);
loadCode(input_file);
input_file.close();
} else {
throw std::invalid_argument(std::string{"Invalid path "} +
path.string());
}
}

chsize_t CodeManager::getCnst(chsize_t id) {
assert(id < constantPool_.size());
return constantPool_[id];
}

bytecode_t CodeManager::getBytecode(chsize_t pc) {
if (pc / sizeof(bytecode_t) >= raw_.size() ||
pc % sizeof(bytecode_t) != 0) {
Expand Down
2 changes: 1 addition & 1 deletion src/ChaiVM/interpreter/decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Instruction parse(bytecode_t word) {
const Opcode opcode = utils::ExtractBits<bytecode_t, 8, 0>(word);
return Instruction{
.operation = opcodes2operation[opcode],
.immidiate = utils::ExtractBits<bytecode_t, Immidiate, 32, 8>(word),
.immidiate = utils::ExtractBits<bytecode_t, Immidiate, 16, 16>(word),
.r1 = utils::ExtractBits<bytecode_t, RegisterId, 8, 8>(word),
.r2 = utils::ExtractBits<bytecode_t, RegisterId, 8, 16>(word),
};
Expand Down
Loading

0 comments on commit a3d8a67

Please sign in to comment.