// For std::unique_ptr
#include <memory>
#include<iostream>
#include<bitset>
// Include common routines
#include <verilated.h>
// Include model header, generated from Verilating "top.v"
#include "Valu.h"
#include "tbalu.h"
int shift_right_a(const std::unique_ptr<Valu> & dut, const std::unique_ptr<VerilatedContext> & contextp);
int shift_right_l(const std::unique_ptr<Valu> & dut, const std::unique_ptr<VerilatedContext> & contextp);
int shift_left(const std::unique_ptr<Valu> & dut, const std::unique_ptr<VerilatedContext> & contextp);
int add(const std::unique_ptr<Valu> & dut, const std::unique_ptr<VerilatedContext> & contextp);
int sub(const std::unique_ptr<Valu> & dut, const std::unique_ptr<VerilatedContext> & contextp);
int slt(const std::unique_ptr<Valu> & dut, const std::unique_ptr<VerilatedContext> & contextp);
int sltu(const std::unique_ptr<Valu> & dut, const std::unique_ptr<VerilatedContext> & contextp);
int shift_right_a(const std::unique_ptr<Valu> & dut, const std::unique_ptr<VerilatedContext> & 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<Valu> & dut, const std::unique_ptr<VerilatedContext> & 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<Valu> & dut, const std::unique_ptr<VerilatedContext> & 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<Valu> & dut, const std::unique_ptr<VerilatedContext> & 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<Valu> & dut, const std::unique_ptr<VerilatedContext> & 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<Valu> & dut, const std::unique_ptr<VerilatedContext> & 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<Valu> & dut, const std::unique_ptr<VerilatedContext> & 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<VerilatedContext> 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<Valu> 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;
}