From ec8b3895ff3ca896d26158db8330d03f4a974da6 Mon Sep 17 00:00:00 2001 From: DarkSharpness <2040703891@qq.com> Date: Fri, 12 Jul 2024 11:36:09 +0800 Subject: [PATCH] feat(alu): add an alu demo --- demo/alu.cpp | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 demo/alu.cpp diff --git a/demo/alu.cpp b/demo/alu.cpp new file mode 100644 index 0000000..0a5d18a --- /dev/null +++ b/demo/alu.cpp @@ -0,0 +1,131 @@ +#include "../include/tools" +#include + +bool reset; +bool ready; + +// RISC-V +enum class Opcode : dark::max_size_t { + ADD, + SUB, + SLL, + SRL, + SRA, + AND, + OR, + XOR, + SLT, + SLTU, + SGE, + SGEU, + SEQ, + SNEQ +}; + + +// Normally, only wire can be used in the input. +struct AluInput { + Wire <8> opcode; + Wire <1> issue; + Wire <32> rs1; + Wire <32> rs2; +}; + +struct AluOutput { + Register <32> out; + Register <1> done; +}; + +struct AluModule : AluInput, AluOutput { + using Tags = SyncTags; + + void work() { + if (reset) { + done <= 0; + } else if(ready && issue) { + switch (static_cast (static_cast (opcode))) { + using enum Opcode; + case ADD: out <= (rs1 + rs2); break; + case SUB: out <= (rs1 - rs2); break; + case SLL: out <= (rs1 << rs2); break; + case SRL: out <= (rs1 >> rs2); break; + case SRA: out <= (to_signed(rs1) >> to_unsigned(rs2)); + case AND: out <= (rs1 & rs2); break; + case OR: out <= (rs1 | rs2); break; + case XOR: out <= (rs1 ^ rs2); break; + case SLT: out <= (to_signed(rs1) < to_signed(rs2)); break; + case SLTU: out <= (rs1 < rs2); break; + case SGE: out <= (to_signed(rs1) >= to_signed(rs2)); break; + case SGEU: out <= (rs1 >= rs2); break; + case SEQ: out <= (rs1 == rs2); break; + case SNEQ: out <= (rs1 != rs2); break; + default: dark::debug::assert(false, "Invalid opcode"); + } + done <= 1; + } else { + done <= 0; + } + } + +}; + +signed main() { + AluModule alu; + + std::string opstring; + + max_size_t opcode; + max_size_t issue; + max_size_t rs1; + max_size_t rs2; + + ready = 1; + + alu.opcode = [&]() { return opcode; }; + alu.issue = [&]() { return issue; }; + alu.rs1 = [&]() { return rs1; }; + alu.rs2 = [&]() { return rs2; }; + + while (std::cin >> opstring) { + issue = 1; + std::cin >> rs1 >> rs2; + if (opstring == "add") { + opcode = static_cast (Opcode::ADD); + } else if (opstring == "sub") { + opcode = static_cast (Opcode::SUB); + } else if (opstring == "sll") { + opcode = static_cast (Opcode::SLL); + } else if (opstring == "srl") { + opcode = static_cast (Opcode::SRL); + } else if (opstring == "sra") { + opcode = static_cast (Opcode::SRA); + } else if (opstring == "and") { + opcode = static_cast (Opcode::AND); + } else if (opstring == "or") { + opcode = static_cast (Opcode::OR); + } else if (opstring == "xor") { + opcode = static_cast (Opcode::XOR); + } else if (opstring == "slt") { + opcode = static_cast (Opcode::SLT); + } else if (opstring == "sltu") { + opcode = static_cast (Opcode::SLTU); + } else if (opstring == "sge") { + opcode = static_cast (Opcode::SGE); + } else if (opstring == "sgeu") { + opcode = static_cast (Opcode::SGEU); + } else if (opstring == "seq") { + opcode = static_cast (Opcode::SEQ); + } else if (opstring == "sneq") { + opcode = static_cast (Opcode::SNEQ); + } else { + std::cout << "Invalid opcode" << std::endl; + issue = 0; + } + + alu.work(); + + std::cout << to_unsigned(alu.out) << std::endl; + sync_member(alu); + } + +} \ No newline at end of file