feat: fix compile error and update demo
This commit is contained in:
92
demo/alu.cpp
92
demo/alu.cpp
@ -1,8 +1,6 @@
|
|||||||
#include "../include/tools.h"
|
#include "tools.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <unordered_map>
|
||||||
bool reset;
|
|
||||||
bool ready;
|
|
||||||
|
|
||||||
// RISC-V
|
// RISC-V
|
||||||
enum class Opcode : dark::max_size_t {
|
enum class Opcode : dark::max_size_t {
|
||||||
@ -22,7 +20,6 @@ enum class Opcode : dark::max_size_t {
|
|||||||
SNEQ
|
SNEQ
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Normally, only wire can be used in the input.
|
// Normally, only wire can be used in the input.
|
||||||
struct AluInput {
|
struct AluInput {
|
||||||
Wire<8> opcode;
|
Wire<8> opcode;
|
||||||
@ -36,13 +33,9 @@ struct AluOutput {
|
|||||||
Register<1> done;
|
Register<1> done;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AluModule : AluInput, AluOutput {
|
struct AluModule : dark::Module<AluInput, AluOutput> {
|
||||||
using Tags = SyncTags<AluInput, AluOutput>;
|
void work() override {
|
||||||
|
if (issue) {
|
||||||
void work() {
|
|
||||||
if (reset) {
|
|
||||||
done <= 0;
|
|
||||||
} else if(ready && issue) {
|
|
||||||
switch (static_cast<Opcode>(static_cast<unsigned>(opcode))) {
|
switch (static_cast<Opcode>(static_cast<unsigned>(opcode))) {
|
||||||
using enum Opcode;
|
using enum Opcode;
|
||||||
case ADD: out <= (rs1 + rs2); break;
|
case ADD: out <= (rs1 + rs2); break;
|
||||||
@ -62,16 +55,14 @@ struct AluModule : AluInput, AluOutput {
|
|||||||
default: dark::debug::assert(false, "Invalid opcode");
|
default: dark::debug::assert(false, "Invalid opcode");
|
||||||
}
|
}
|
||||||
done <= 1;
|
done <= 1;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
done <= 0;
|
done <= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
signed main() {
|
int main() {
|
||||||
AluModule alu;
|
|
||||||
|
|
||||||
std::string opstring;
|
std::string opstring;
|
||||||
|
|
||||||
max_size_t opcode;
|
max_size_t opcode;
|
||||||
@ -79,53 +70,42 @@ signed main() {
|
|||||||
max_size_t rs1;
|
max_size_t rs1;
|
||||||
max_size_t rs2;
|
max_size_t rs2;
|
||||||
|
|
||||||
ready = 1;
|
dark::CPU cpu;
|
||||||
|
AluModule alu;
|
||||||
alu.opcode = [&]() { return opcode; };
|
alu.opcode = [&]() { return opcode; };
|
||||||
alu.issue = [&]() { return issue; };
|
alu.issue = [&]() { return issue; };
|
||||||
alu.rs1 = [&]() { return rs1; };
|
alu.rs1 = [&]() { return rs1; };
|
||||||
alu.rs2 = [&]() { return rs2; };
|
alu.rs2 = [&]() { return rs2; };
|
||||||
|
cpu.add_module(&alu);
|
||||||
|
|
||||||
|
std::unordered_map<std::string, Opcode> cmd2op = {
|
||||||
|
{"add", Opcode::ADD},
|
||||||
|
{"sub", Opcode::SUB},
|
||||||
|
{"sll", Opcode::SLL},
|
||||||
|
{"src", Opcode::SRL},
|
||||||
|
{"sra", Opcode::SRA},
|
||||||
|
{"and", Opcode::AND},
|
||||||
|
{"or", Opcode::OR},
|
||||||
|
{"xor", Opcode::XOR},
|
||||||
|
{"slt", Opcode::SLT},
|
||||||
|
{"sltu", Opcode::SLTU},
|
||||||
|
{"sge", Opcode::SGE},
|
||||||
|
{"sgeu", Opcode::SGEU},
|
||||||
|
{"seq", Opcode::SEQ},
|
||||||
|
{"sneq", Opcode::SNEQ}};
|
||||||
while (std::cin >> opstring) {
|
while (std::cin >> opstring) {
|
||||||
issue = 1;
|
if (cmd2op.find(opstring) == cmd2op.end()) {
|
||||||
std::cin >> rs1 >> rs2;
|
|
||||||
if (opstring == "add") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::ADD);
|
|
||||||
} else if (opstring == "sub") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SUB);
|
|
||||||
} else if (opstring == "sll") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SLL);
|
|
||||||
} else if (opstring == "srl") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SRL);
|
|
||||||
} else if (opstring == "sra") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SRA);
|
|
||||||
} else if (opstring == "and") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::AND);
|
|
||||||
} else if (opstring == "or") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::OR);
|
|
||||||
} else if (opstring == "xor") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::XOR);
|
|
||||||
} else if (opstring == "slt") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SLT);
|
|
||||||
} else if (opstring == "sltu") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SLTU);
|
|
||||||
} else if (opstring == "sge") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SGE);
|
|
||||||
} else if (opstring == "sgeu") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SGEU);
|
|
||||||
} else if (opstring == "seq") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SEQ);
|
|
||||||
} else if (opstring == "sneq") {
|
|
||||||
opcode = static_cast <max_size_t> (Opcode::SNEQ);
|
|
||||||
} else {
|
|
||||||
std::cout << "Invalid opcode" << std::endl;
|
std::cout << "Invalid opcode" << std::endl;
|
||||||
issue = 0;
|
issue = 0;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
alu.work();
|
issue = 1;
|
||||||
|
std::cin >> rs1 >> rs2;
|
||||||
std::cout << to_unsigned(alu.out) << std::endl;
|
|
||||||
sync_member(alu);
|
|
||||||
}
|
}
|
||||||
|
opcode = static_cast<max_size_t>(cmd2op[opstring]);
|
||||||
|
cpu.run_once();
|
||||||
|
std::cout << "out: " << static_cast<unsigned int>(alu.out) << std::endl;
|
||||||
|
std::cout << "done: " << static_cast<unsigned int>(alu.done) << std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -43,7 +43,9 @@ concept int_type = !has_length<_Tp> && implicit_convertible_to<_Tp, max_size_t>;
|
|||||||
|
|
||||||
template<typename _Lhs, typename _Rhs>
|
template<typename _Lhs, typename _Rhs>
|
||||||
concept bit_match =
|
concept bit_match =
|
||||||
(bit_type<_Lhs> && bit_type<_Rhs> && _Lhs::_Bit_Len == _Rhs::_Bit_Len) || (int_type<_Lhs> || int_type<_Rhs>);
|
(bit_type<_Lhs> && bit_type<_Rhs> && _Lhs::_Bit_Len == _Rhs::_Bit_Len) // prevent format
|
||||||
|
|| (int_type<_Lhs> && bit_type<_Rhs>) //
|
||||||
|
|| (bit_type<_Lhs> && int_type<_Rhs>);
|
||||||
|
|
||||||
template<typename _Tp, std::size_t _Len>
|
template<typename _Tp, std::size_t _Len>
|
||||||
concept bit_convertible =
|
concept bit_convertible =
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -7,7 +9,8 @@ namespace dark {
|
|||||||
|
|
||||||
class CPU {
|
class CPU {
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<ModuleBase>> modules;
|
std::vector<std::unique_ptr<ModuleBase>> mod_owned;
|
||||||
|
std::vector<ModuleBase *> modules;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned long long cycles = 0;
|
unsigned long long cycles = 0;
|
||||||
@ -19,9 +22,21 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void add_module(std::unique_ptr<ModuleBase> module) {
|
/// @attention the pointer will be moved. you SHOULD NOT use it after calling this function.
|
||||||
modules.push_back(std::move(module));
|
template<typename _Tp>
|
||||||
|
requires std::derived_from<_Tp, ModuleBase>
|
||||||
|
void add_module(std::unique_ptr<_Tp> &module) {
|
||||||
|
modules.push_back(module.get());
|
||||||
|
mod_owned.emplace_back(std::move(module));
|
||||||
}
|
}
|
||||||
|
void add_module(std::unique_ptr<ModuleBase> module) {
|
||||||
|
modules.push_back(module.get());
|
||||||
|
mod_owned.emplace_back(std::move(module));
|
||||||
|
}
|
||||||
|
void add_module(ModuleBase *module) {
|
||||||
|
modules.push_back(module);
|
||||||
|
}
|
||||||
|
|
||||||
void run_once() {
|
void run_once() {
|
||||||
++cycles;
|
++cycles;
|
||||||
for (auto &module: modules)
|
for (auto &module: modules)
|
||||||
@ -30,10 +45,7 @@ public:
|
|||||||
}
|
}
|
||||||
void run_once_shuffle() {
|
void run_once_shuffle() {
|
||||||
static std::default_random_engine engine;
|
static std::default_random_engine engine;
|
||||||
std::vector<ModuleBase *> shuffled;
|
std::vector<ModuleBase *> shuffled = modules;
|
||||||
shuffled.reserve(modules.size());
|
|
||||||
for (auto &module: modules)
|
|
||||||
shuffled.push_back(module.get());
|
|
||||||
std::shuffle(shuffled.begin(), shuffled.end(), engine);
|
std::shuffle(shuffled.begin(), shuffled.end(), engine);
|
||||||
|
|
||||||
++cycles;
|
++cycles;
|
||||||
|
@ -1,13 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
#include "synchronize.h"
|
#include "synchronize.h"
|
||||||
namespace dark {
|
namespace dark {
|
||||||
|
|
||||||
|
namespace details {
|
||||||
|
struct empty_class {
|
||||||
|
void sync() { /* do nothing */ }
|
||||||
|
};
|
||||||
|
} // namespace details
|
||||||
|
|
||||||
struct ModuleBase {
|
struct ModuleBase {
|
||||||
virtual void work() = 0;
|
virtual void work() = 0;
|
||||||
virtual void sync() = 0;
|
virtual void sync() = 0;
|
||||||
virtual ~ModuleBase() = default;
|
virtual ~ModuleBase() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename _Tinput, typename _Toutput, typename _Tprivate>
|
template<typename _Tinput, typename _Toutput, typename _Tprivate = details::empty_class>
|
||||||
|
requires std::is_aggregate_v<_Tinput> && std::is_aggregate_v<_Toutput> && std::is_aggregate_v<_Tprivate>
|
||||||
struct Module : public ModuleBase, public _Tinput, public _Toutput, protected _Tprivate {
|
struct Module : public ModuleBase, public _Tinput, public _Toutput, protected _Tprivate {
|
||||||
void sync() override final {
|
void sync() override final {
|
||||||
sync_member(static_cast<_Tinput &>(*this));
|
sync_member(static_cast<_Tinput &>(*this));
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
explicit operator max_size_t() const { return this->_M_old; }
|
explicit operator max_size_t() const { return this->_M_old; }
|
||||||
|
explicit operator bool() const { return this->_M_old; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dark
|
} // namespace dark
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "register.h"
|
#include "register.h"
|
||||||
#include "synchronize.h"
|
#include "synchronize.h"
|
||||||
#include "wire.h"
|
#include "wire.h"
|
||||||
|
#include "module.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
using dark::Bit;
|
using dark::Bit;
|
||||||
using dark::sign_extend;
|
using dark::sign_extend;
|
||||||
|
@ -107,6 +107,10 @@ public:
|
|||||||
this->_M_func.reset(_M_new_func(std::forward<_Fn>(fn)));
|
this->_M_func.reset(_M_new_func(std::forward<_Fn>(fn)));
|
||||||
this->sync();
|
this->sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return static_cast<max_size_t>(*this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user