diff --git a/simulation/test_alu.cpp b/simulation/test_alu.cpp index ed77946..91b6f0f 100644 --- a/simulation/test_alu.cpp +++ b/simulation/test_alu.cpp @@ -2,17 +2,112 @@ #include "verilated.h" #include +const std::string ANSI_RESET = "\033[0m"; +const std::string ANSI_GREEN = "\033[38;5;2m"; +const std::string ANSI_RED = "\033[38;5;1m"; +const std::string ANSI_YELLOW = "\033[38;5;11m"; + +class Tester { + private: + int succeeded, failed; + std::string name; + public: + Tester(std::string test_name) : name(test_name), succeeded(0), failed(0) { + printf("[ %s ] - %sstarting%s\n", name.c_str(), ANSI_YELLOW.c_str(), ANSI_RESET.c_str()); + } + + template + void assert_eq(std::string test_name, T got, U expected) { + printf("[ %s ] - %30s - ", name.c_str(), test_name.c_str()); + if (got == expected) { + printf("%ssuccess%s\n", ANSI_GREEN.c_str(), ANSI_RESET.c_str()); + succeeded++; + } else { + printf("%sfailed%s - got %08x, expected %08x\n", ANSI_RED.c_str(), ANSI_RESET.c_str(), got, expected); + failed++; + } + } + + ~Tester() { finish(); } + + void finish() { + if (failed == 0) { + printf("[ %s ] - %sall succeeded%s, out of %d total\n", name.c_str(), ANSI_GREEN.c_str(), ANSI_RESET.c_str(), succeeded + failed); + } else { + printf("[ %s ] - %s%d failed, %d succeeded%s, out of %d total\n", name.c_str(), ANSI_RED.c_str(), failed, succeeded, ANSI_RESET.c_str(), succeeded + failed); + } + } +}; + int main(int argc, char **argv) { VerilatedContext *vctx = new VerilatedContext; - Valu *valu = new Valu(vctx); - valu->A = 0x2137; - valu->B = 0x1234; - valu->op = 0b000; - valu->eval(); - printf("A = %04x + B = %04x = O = %04x\n", valu->A, valu->B, valu->O); - valu->op = 0b001; - valu->eval(); - printf("A = %04x - B = %04x = O = %04x\n", valu->A, valu->B, valu->O); + Valu *valu = new Valu(vctx); + + { + Tester add_t("add"); + + valu->op = 0b000; + valu->A = 0x2137; + valu->B = 0x1234; + valu->eval(); + add_t.assert_eq("0x2137 + 0x1234 == 0x336b", valu->O, 0x336b); + add_t.assert_eq("0x2137 + 0x1234 no overflow", valu->Fflow, 0x0); + add_t.assert_eq("0x2137 + 0x1234 no Fzero", valu->Fzero, 0x0); + + valu->op = 0b000; + valu->A = 0x9; + valu->B = 0x10; + valu->eval(); + add_t.assert_eq("0x9 + 0x10 == 0x19", valu->O, 0x19); + add_t.assert_eq("0x9 + 0x10 no overflow", valu->Fflow, 0x0); + add_t.assert_eq("0x9 + 0x10 no Fzero", valu->Fzero, 0x0); + + valu->op = 0b000; + valu->A = 0xffffffff; + valu->B = 0x1; + valu->eval(); + add_t.assert_eq("0xffffffff + 0x1 == 0x0", valu->O, 0x0); + add_t.assert_eq("0xffffffff + 0x1 has overflow", valu->Fflow, 0x1); + add_t.assert_eq("0xffffffff + 0x1 has Fzero", valu->Fzero, 0x1); + } + + { + Tester add_t("sub"); + + valu->op = 0b001; + valu->A = 0x2137; + valu->B = 0x0420; + valu->eval(); + add_t.assert_eq("0x2137 - 0x0420 == 0x1d17", valu->O, 0x1d17); + add_t.assert_eq("0x2137 - 0x1234 no underflow", valu->Fflow, 0x0); + add_t.assert_eq("0x2137 - 0x1234 no Fzero", valu->Fzero, 0x0); + + valu->op = 0b001; + valu->A = 0x100; + valu->B = 0x200; + valu->eval(); + add_t.assert_eq("0x100 - 0x200 == 0xffffff00", valu->O, 0xffffff00); + add_t.assert_eq("0x100 - 0x200 has underflow", valu->Fflow, 0x1); + add_t.assert_eq("0x100 - 0x200 no Fzero", valu->Fzero, 0x0); + + valu->op = 0b001; + valu->A = 0x0; + valu->B = 0x1; + valu->eval(); + add_t.assert_eq("0x0 - 0x1 == 0xffffffff", valu->O, 0xffffffff); + add_t.assert_eq("0x0 - 0x1 has underflow", valu->Fflow, 0x1); + add_t.assert_eq("0x0 - 0x1 no Fzero", valu->Fzero, 0x0); + + valu->op = 0b001; + valu->A = 0x20; + valu->B = 0x20; + valu->eval(); + add_t.assert_eq("0x20 - 0x20 == 0x0", valu->O, 0x0); + add_t.assert_eq("0x20 - 0x20 no underflow", valu->Fflow, 0x0); + add_t.assert_eq("0x20 - 0x20 has Fzero", valu->Fzero, 0x1); + } + + } diff --git a/verilog-src/alu.v b/verilog-src/alu.v index 3fde343..2a1465c 100644 --- a/verilog-src/alu.v +++ b/verilog-src/alu.v @@ -15,14 +15,17 @@ module alu( input [31:0] B, input [2:0] op, output [31:0] O, - output Cout, + output Fflow, output Fzero ); wire subtraction = op == 3'b001; wire [31:0] adder_B = subtraction ? ~B : B; +wire adder_cout; -carry_select_adder a(A, adder_B, subtraction, O, Cout); -assign Fzero = & O; +carry_select_adder a(A, adder_B, subtraction, O, adder_cout); + +assign Fflow = subtraction ? ~adder_cout : adder_cout; +assign Fzero = ~ (| O); endmodule