// For std::unique_ptr #include #include #include // Include common routines #include // Include model header, generated from Verilating "top.v" #include "Valu.h" #include "tbalu.h" int shift_right_a(const std::unique_ptr & dut, const std::unique_ptr & contextp); int shift_right_l(const std::unique_ptr & dut, const std::unique_ptr & contextp); int shift_left(const std::unique_ptr & dut, const std::unique_ptr & contextp); int add(const std::unique_ptr & dut, const std::unique_ptr & contextp); int sub(const std::unique_ptr & dut, const std::unique_ptr & contextp); int slt(const std::unique_ptr & dut, const std::unique_ptr & contextp); int sltu(const std::unique_ptr & dut, const std::unique_ptr & contextp); int shift_right_a(const std::unique_ptr & dut, const std::unique_ptr & contextp) { // Set Vtop's input signals dut->A = 0x80080080; dut->B = 0x00000000; dut->OP = SRA; // Simulate until $finish // while (!contextp->gotFinish()) { int mistake = 0; for (int i = 0; i < 32; i++) { dut->B = i; contextp->timeInc(1); int A = (int) dut->A; int B = (int) dut->B; int D = (int) A >> B; dut->eval(); if (D != dut->C) { std::cout << "TEST FAILED SRA\n"; std::bitset<32> x(dut->A); std::bitset<32> y(dut->B); std::bitset<32> z(dut->C); std::bitset<32> a(D); std::cout << "Current: " << x << " >>> " << y << " = " << z << '\n'; std::cout << "Expected: " << x << " >>> " << y << " = " << a << '\n'; mistake = 1; } } if(!mistake) { std::cout << "PASSED SRA\n"; } return mistake; } int shift_right_l(const std::unique_ptr & dut, const std::unique_ptr & contextp) { // Set Vtop's input signals dut->A = 0x80000000; dut->B = 0x00000000; dut->OP = SRL; // Simulate until $finish // while (!contextp->gotFinish()) { int mistake = 0; for (int i = 0; i < 32; i++) { dut->B = i; contextp->timeInc(1); unsigned int A = (unsigned int) dut->A; unsigned int B = (unsigned int) dut->B; unsigned int D = (unsigned int) A >> B; dut->eval(); if (D != dut->C) { std::cout << "TEST FAILED SRL\n"; std::bitset<32> x(dut->A); std::bitset<32> y(dut->B); std::bitset<32> z(dut->C); std::bitset<32> a(D); std::cout << "Current: " << x << " >>> " << y << " = " << z << '\n'; std::cout << "Expected: " << x << " >>> " << y << " = " << a << '\n'; mistake = 1; } } if(!mistake) { std::cout << "PASSED SRL\n"; } return mistake; } int shift_left(const std::unique_ptr & dut, const std::unique_ptr & contextp) { // Set Vtop's input signals dut->A = 0x00000001; dut->B = 0x00000000; dut->OP = SLL; // Simulate until $finish // while (!contextp->gotFinish()) { int mistake = 0; for (int i = 0; i < 32; i++) { dut->B = i; contextp->timeInc(1); int A = (int) dut->A; int B = (int) dut->B; int D = (int) A << B; dut->eval(); if (D != dut->C) { std::cout << "TEST FAILED SL\n"; std::bitset<32> x(dut->A); std::bitset<32> y(dut->B); std::bitset<32> z(dut->C); std::bitset<32> a(D); std::cout << "Current: " << x << " <<< " << y << " = " << z << '\n'; std::cout << "Expected: " << x << " <<< " << y << " = " << a << '\n'; mistake = 1; } } if(!mistake) { std::cout << "PASSED SL\n"; } return mistake; } int add(const std::unique_ptr & dut, const std::unique_ptr & contextp) { // Set Vtop's input signals dut->A = 0x00000000; dut->B = 0x00000000; dut->OP = ADD; int mistake = 0; for (int i = -(32 * 32); i < 32 * 32; i++) { dut->A = i % 32; dut->B = i / 32; contextp->timeInc(1); int A = (int) dut->A; int B = (int) dut->B; int D = (int) A + B; dut->eval(); if (D != dut->C) { std::cout << "TEST FAILED ADD\n"; std::bitset<32> x(dut->A); std::bitset<32> y(dut->B); std::bitset<32> z(dut->C); std::bitset<32> a(D); std::cout << "Current: " << x << " + " << y << " = " << z << '\n'; std::cout << "Expected: " << x << " + " << y << " = " << a << '\n'; mistake = 1; } } if(!mistake) { std::cout << "PASSED ADD\n"; } return mistake; } int sub(const std::unique_ptr & dut, const std::unique_ptr & contextp) { // Set Vtop's input signals dut->A = 0x00000000; dut->B = 0x00000000; dut->OP = SUB; int mistake = 0; for (int i = -(32 * 32); i < 32 * 32; i++) { dut->A = i % 32; dut->B = i / 32; contextp->timeInc(1); int A = (int) dut->A; int B = (int) dut->B; int D = (int) A - B; dut->eval(); if (D != dut->C) { std::cout << "TEST FAILED SUB\n"; std::bitset<32> x(dut->A); std::bitset<32> y(dut->B); std::bitset<32> z(dut->C); std::bitset<32> a(D); std::cout << "Current: " << x << " + " << y << " = " << z << '\n'; std::cout << "Expected: " << x << " + " << y << " = " << a << '\n'; mistake = 1; } } if(!mistake) { std::cout << "PASSED SUB\n"; } return mistake; } int slt(const std::unique_ptr & dut, const std::unique_ptr & contextp) { // Set Vtop's input signals dut->A = 0x00000000; dut->B = 0x00000000; dut->OP = SLT; int mistake = 0; for (int i = -(32 * 32); i < 32 * 32; i++) { dut->A = i % 32; dut->B = i / 32; contextp->timeInc(1); int A = (int) dut->A; int B = (int) dut->B; int D = (int) (A < B ? 1 : 0); dut->eval(); if (D != dut->C) { std::cout << "TEST FAILED SLT\n"; std::bitset<32> x(dut->A); std::bitset<32> y(dut->B); std::bitset<32> z(dut->C); std::bitset<32> a(D); std::cout << "Current: " << x << " ? " << y << " = " << z << '\n'; std::cout << "Expected: " << x << " ? " << y << " = " << a << '\n'; mistake = 1; } } if(!mistake) { std::cout << "PASSED SLT\n"; } return mistake; } int sltu(const std::unique_ptr & dut, const std::unique_ptr & contextp) { // Set Vtop's input signals dut->A = 0x00000000; dut->B = 0x00000000; dut->OP = SLTU; int mistake = 0; for (int i = -(32 * 32); i < 32 * 32; i++) { dut->A = i % 32; dut->B = i / 32; contextp->timeInc(1); unsigned int A = (unsigned int) dut->A; unsigned int B = (unsigned int) dut->B; unsigned int D = (unsigned int) (A < B ? 1 : 0); dut->eval(); if (D != dut->C) { std::cout << "TEST FAILED SLTU\n"; std::bitset<32> x(dut->A); std::bitset<32> y(dut->B); std::bitset<32> z(dut->C); std::bitset<32> a(D); std::cout << "Current: " << x << " ?u " << y << " = " << z << '\n'; std::cout << "Expected: " << x << " ?u " << y << " = " << a << '\n'; mistake = 1; } } if(!mistake) { std::cout << "PASSED SLTU\n"; } return mistake; } int main(int argc, char** argv, char** env) { // This is a more complicated example, please also see the simpler examples/make_hello_c. // Prevent unused variable warnings if (false && argc && argv && env) {} // Create logs/ directory in case we have traces to put under it Verilated::mkdir("logs"); // Construct a VerilatedContext to hold simulation time, etc. // Multiple modules (made later below with Vtop) may share the same // context to share time, or modules may have different contexts if // they should be independent from each other. // Using unique_ptr is similar to // "VerilatedContext* contextp = new VerilatedContext" then deleting at end. const std::unique_ptr contextp{new VerilatedContext}; // Do not instead make Vtop as a file-scope static variable, as the // "C++ static initialization order fiasco" may cause a crash // Set debug level, 0 is off, 9 is highest presently used // May be overridden by commandArgs argument parsing contextp->debug(0); // Randomization reset policy // May be overridden by commandArgs argument parsing contextp->randReset(2); // Verilator must compute traced signals contextp->traceEverOn(true); // Pass arguments so Verilated code can see them, e.g. $value$plusargs // This needs to be called before you create any model contextp->commandArgs(argc, argv); // Construct the Verilated model, from Vtop.h generated from Verilating "top.v". // Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end. // "TOP" will be the hierarchical name of the module. const std::unique_ptr dut{new Valu{contextp.get(), "ALU"}}; int test; if (shift_right_a(dut, contextp)) { return 0; } if (shift_right_l(dut, contextp)) { return 0; } if (shift_left(dut, contextp)) { return 0; } if (add(dut, contextp)) { return 0; } if (sub(dut, contextp)) { return 0; } if (slt(dut,contextp)) { return 0; } if (sltu(dut,contextp)) { return 0; } dut->eval(); // Final model cleanup dut->final(); // Return good completion status // Don't use exit() or destructor won't get called return 0; }