summaryrefslogblamecommitdiff
path: root/verilog/tbalu.cpp
blob: 4351766e7ce7df69accbf9d20ebe5ba0a0f24e46 (plain) (tree)





















































































































































































































































































































































                                                                                                          
// 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;
}