From ef6280882113e36085a04bbb79ecb0acceaa9535 Mon Sep 17 00:00:00 2001 From: xenia Date: Wed, 17 Jan 2024 13:58:25 +0100 Subject: [PATCH] Automated tests --- simulation/test_alu.cpp | 112 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 7 deletions(-) diff --git a/simulation/test_alu.cpp b/simulation/test_alu.cpp index da6ace2..474ad42 100644 --- a/simulation/test_alu.cpp +++ b/simulation/test_alu.cpp @@ -1,7 +1,9 @@ #include "Valu.h" #include "verilated.h" #include "tester.hpp" + #include +#include struct alu_testcase { std::string name; @@ -16,6 +18,18 @@ struct alu_testcase { std::optional max_cycles; }; +std::string fmt_hex(uint32_t n) { + char hex[100]; + if (n < 0x100) + snprintf(hex, sizeof hex, "0x%02x", n); + else if (n < 0x10000) + snprintf(hex, sizeof hex, "0x%04x", n); + else + snprintf(hex, sizeof hex, "0x%08x", n); + + return hex; +} + void test_op(Valu *valu, Tester *tester, alu_testcase test) { Tester subtester(tester, test.name); @@ -26,13 +40,9 @@ void test_op(Valu *valu, Tester *tester, alu_testcase test) { valu->eval(); - char o_name[100]; - if (test.O < 0x100) - snprintf(o_name, sizeof o_name, "O == 0x%02x", test.O); - if (test.O < 0x10000) - snprintf(o_name, sizeof o_name, "O == 0x%04x", test.O); - else - snprintf(o_name, sizeof o_name, "O == 0x%08x", test.O); + std::string o_name("O == "); + o_name.append(fmt_hex(test.O)); + subtester.assert_eq(o_name, valu->O, test.O); if (test.overflow.has_value()) { @@ -165,4 +175,92 @@ int main(int argc, char **argv) { .O = 0x0, .zero = true, }); } + + { + Tester auto_t(&alu_t, "auto", true); + + std::default_random_engine eng; + std::uniform_int_distribution op_gen(0, 5); + std::uniform_int_distribution gen(0, 0xffffffff); + + for (int i = 0; i < 100; i++) { + uint32_t A = gen(eng); + uint32_t B = gen(eng); + std::string name; + + switch (op_gen(eng)) { + case 0: // Add + name.append(fmt_hex(A)); + name.append("+"); + name.append(fmt_hex(B)); + + test_op(valu, &auto_t, { + .name = name, + .A = A, .B = B, .op = 0b000, + .O = A + B, .overflow = (A + B < A), .zero = (A + B == 0), + }); + + break; + case 1: // Subtract + name.append(fmt_hex(A)); + name.append("-"); + name.append(fmt_hex(B)); + + test_op(valu, &auto_t, { + .name = name, + .A = A, .B = B, .op = 0b001, + .O = A - B, .overflow = (B > A), .zero = (A == B), + }); + + break; + case 2: // Bitwise AND + name.append(fmt_hex(A)); + name.append("&"); + name.append(fmt_hex(B)); + + test_op(valu, &auto_t, { + .name = name, + .A = A, .B = B, .op = 0b100, + .O = A & B, .overflow = 0, .zero = ((A & B) == 0), + }); + + break; + case 3: // Bitwise OR + name.append(fmt_hex(A)); + name.append("|"); + name.append(fmt_hex(B)); + + test_op(valu, &auto_t, { + .name = name, + .A = A, .B = B, .op = 0b101, + .O = A | B, .overflow = 0, .zero = ((A | B) == 0), + }); + + break; + case 4: // Bitwise XOR + name.append(fmt_hex(A)); + name.append("^"); + name.append(fmt_hex(B)); + + test_op(valu, &auto_t, { + .name = name, + .A = A, .B = B, .op = 0b110, + .O = A ^ B, .overflow = 0, .zero = ((A ^ B) == 0), + }); + + break; + case 5: // Bitwise NOT + name.append("~"); + name.append(fmt_hex(A)); + + test_op(valu, &auto_t, { + .name = name, + .A = A, .B = B, .op = 0b111, + .O = ~A, .overflow = 0, .zero = (A == 0xffffffff), + }); + + break; + } + } + } }