Added Automated Testing For Test #3

- Enabled automated testing for test case 3

Co-authored-by: Kevin Dai <kevindai02@outlook.com>
diff --git a/verilog/dv/caravel/hs32_soc/test3/Makefile b/verilog/dv/caravel/hs32_soc/test3/Makefile
index 8265b9d..19efa0d 100644
--- a/verilog/dv/caravel/hs32_soc/test3/Makefile
+++ b/verilog/dv/caravel/hs32_soc/test3/Makefile
@@ -1,7 +1,7 @@
-FIRMWARE_PATH = ../..
+FIRMWARE_PATH = ../../
 RTL_PATH = ../../../../rtl
-IP_PATH = ../../../../ip
-BEHAVIOURAL_MODELS = ../../ 
+BEHAVIOURAL_MODELS = ../../
+VERILOG_PATH = ../../../../
 
 GCC_PATH?=/opt/riscv32i/bin
 GCC_PREFIX?=riscv32-unknown-elf
@@ -9,6 +9,8 @@
 
 .SUFFIXES:
 
+SIM?=RTL
+
 PATTERN = test3
 
 all:  ${PATTERN:=.vcd}
@@ -16,18 +18,24 @@
 hex:  ${PATTERN:=.hex}
 
 %.vvp: %_tb.v %.hex
+ifeq ($(SIM),RTL)
 	iverilog -DSIM -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
-	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) -I $(RTL_PATH)/hs32cpu \
-	-o $@ $<
+	-I $(PDK_PATH) -I $(RTL_PATH) \
+	-I $(RTL_PATH)/hs32cpu $< -o $@
+else
+	iverilog -DSIM -DFUNCTIONAL -DGL_SIM -I $(BEHAVIOURAL_MODELS) \
+	-I $(PDK_PATH) -I $(RTL_PATH) \
+	-I $(RTL_PATH)/hs32cpu -I $(VERILOG_PATH) $< -o $@
+endif
 
 %.vcd: %.vvp
-	vvp $<
+	vvp $< -fst-speed $(OPT)
 
 %.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
 	${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
 
 %.hex: %.elf
-	${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ 
+	${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@
 	# to fix flash base address
 	sed -i 's/@10000000/@00000000/g' $@
 
@@ -37,6 +45,6 @@
 # ---- Clean ----
 
 clean:
-	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log *.idx
+	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log *.idx *.fst
 
 .PHONY: clean hex all
diff --git a/verilog/dv/caravel/hs32_soc/test3/README.md b/verilog/dv/caravel/hs32_soc/test3/README.md
index 40f7a48..ee18d63 100644
--- a/verilog/dv/caravel/hs32_soc/test3/README.md
+++ b/verilog/dv/caravel/hs32_soc/test3/README.md
@@ -16,6 +16,14 @@
 | I-Type | `oooo_oooo` | `dddd_mmmm` | `iiii_iiii` | `iiii_iiii` |
 | R-Type | `oooo_oooo` | `dddd_mmmm` | `nnnn_ssss` | `sDDb_bxxx` |
 
+## Usage
+
+Use `make` to run test.
+
+Results should match the *Expected result* listed below.
+
+Test will display `Passed all cases.` or `failed` message indicating errors.
+
 ## Assembly
 
 ```assembly
diff --git a/verilog/dv/caravel/hs32_soc/test3/test3.c b/verilog/dv/caravel/hs32_soc/test3/test3.c
index 7a17de4..b653400 100644
--- a/verilog/dv/caravel/hs32_soc/test3/test3.c
+++ b/verilog/dv/caravel/hs32_soc/test3/test3.c
@@ -7,7 +7,7 @@
 	reg_la1_ena = 0xFFFFFFFF;    // [63:32]
 	reg_la2_ena = 0xFFFFFFFF;    // [95:64]
 	reg_la3_ena = 0xFFFFFFFF;    // [127:96]
-	
+
 	// Reset and control bus
 	reg_la0_data = 0b01; // [0] is high means reset
 	reg_la0_data = 0b00; // [0] is low means stop reset
diff --git a/verilog/dv/caravel/hs32_soc/test3/test3_tb.v b/verilog/dv/caravel/hs32_soc/test3/test3_tb.v
index 7e94c3a..23f778d 100644
--- a/verilog/dv/caravel/hs32_soc/test3/test3_tb.v
+++ b/verilog/dv/caravel/hs32_soc/test3/test3_tb.v
@@ -1,20 +1,32 @@
-`define DBG1
+`ifdef GL_SIM
+	`define SRAM_LOG_READ
+	`define SRAM_LOG_WRITE
+`endif
 
 `default_nettype none
-
 `timescale 1 ns / 1 ns
 
 `include "caravel.v"
 `include "spiflash.v"
 
 module tb();
+	parameter TEST_ID = 3;
+	parameter FILENAME = "test3.hex";
+
+	function [0:0] implies;
+		input [0:0] p, q;
+		begin
+			implies = (!p) || q;
+		end
+	endfunction
+
 	reg clock;
-  reg RSTB;
+	reg RSTB;
 	reg power1, power2;
 	reg power3, power4;
 
-  wire gpio;
-  wire [37:0] mprj_io;
+	wire gpio;
+	wire [37:0] mprj_io;
 	wire [7:0] mprj_io_0;
 
 	assign mprj_io_0 = mprj_io[7:0];
@@ -29,6 +41,8 @@
 		clock = 0;
 	end
 
+	reg failed = 1;
+
 	initial begin
 		$dumpfile("tb.vcd");
 		$dumpvars(0, tb);
@@ -37,16 +51,23 @@
 			repeat (1000) @(posedge clock);
 			// $display("+1000 cycles");
 		end
-		//$display("%c[1;31m",27);
-		//$display("Test 1: Failed (timed out)!");
-		//$display("%c[0m",27);
+`ifndef GL_SIM
+		if(failed) begin
+			$display("%c[1;31mTest %0d: Failed. %c[0m", 27, TEST_ID, 27);
+			$finish_and_return(1);
+		end else begin
+			$display("%c[1;32mTest %0d: Passed all cases. %c[0m", 27, TEST_ID, 27);
+			$finish_and_return(0);
+		end
+`endif
 		$finish;
 	end
 
 	initial begin
 		RSTB <= 1'b0;
-		#2000;
+		#1000;
 		RSTB <= 1'b1;	    // Release reset
+		#2000;
 	end
 
 	initial begin			// Power-up sequence
@@ -64,6 +85,76 @@
 		power4 <= 1'b1;
 	end
 
+`ifndef GL_SIM
+	// Weak test cases for debugging
+	initial begin
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[0] == 32'hF000);
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_u.regs[1] == 32'h000F);
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[1] == 32'h000F);
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[2] == 32'h00F0);
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[3] == 32'h00F0);
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[4] == 32'h0F00);
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[5] == 32'hF000);
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[6] == 32'hF001);
+		failed = 0;
+		$display("%c[1;32mTest %0d: Passed weak cases. %c[0m", 27, TEST_ID, 27);
+	end
+
+	// Trigger when register write
+	wire trigger = tb.uut.mprj.core1.core.EXEC.regfile_s.we === 1'b1;
+	reg[31:0] step = 0;
+	always @(posedge clock) if(trigger) step <= step + 1;
+	// Strict assertations for each instruction
+	assert a0(clock, implies(trigger && step == 0,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 0 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h000F));
+	assert a1(clock, implies(trigger && step == 1,
+		tb.uut.mprj.core1.core.EXEC.regfile_u.wadr == 1 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_u.din == 32'h000F));
+	assert a2(clock, implies(trigger && step == 2,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 1 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h000F));
+	assert a3(clock, implies(trigger && step == 3,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 0 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h00F0));
+	assert a4(clock, implies(trigger && step == 4,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 2 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h00F0));
+	assert a5(clock, implies(trigger && step == 5,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 3 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h00F0));
+	assert a6(clock, implies(trigger && step == 6,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 0 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h0F00));
+	assert a7(clock, implies(trigger && step == 7,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 3 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h0F00));
+	assert a8(clock, implies(trigger && step == 8,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 4 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h0F00));
+	assert a9(clock, implies(trigger && step == 9,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 0 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'hF000));
+	assert a10(clock, implies(trigger && step == 10,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 5 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'hF000));
+	assert a11(clock, implies(trigger && step == 11,
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == 6 &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'hF000));
+	/*assert a{{ STEP }}(clock, implies(trigger && step == {{ STEP }},
+		tb.uut.mprj.core1.core.EXEC.regfile_s.wadr == {{ REGISTER }} &&
+		tb.uut.mprj.core1.core.EXEC.regfile_s.din == 32'h{{ DATA }}));*/
+	assert a12(clock, step <= 12);
+
+	// If fault, then test failed
+	always @(*) begin
+		if(tb.uut.mprj.core1.core.EXEC.fault) begin
+			$display("%c[1;31mTest %0d: Faulted. %c[0m", 27, TEST_ID, 27);
+			$finish_and_return(1);
+		end
+	end
+`endif
+
 	always @(mprj_io) begin
 		#1 $display("MPRJ-IO state = %b ", mprj_io[7:0]);
 	end
@@ -75,8 +166,8 @@
 
 	wire VDD3V3 = power1;
 	wire VDD1V8 = power2;
-	wire USER_VDD3V3 = power3;
-	wire USER_VDD1V8 = power4;
+	wire USER_VDD3V3 = power1;
+	wire USER_VDD1V8 = power2;
 	wire VSS = 1'b0;
 
 	caravel uut (
@@ -105,7 +196,7 @@
 	);
 
 	spiflash #(
-		.FILENAME("test3.hex")
+		.FILENAME(FILENAME)
 	) spiflash (
 		.csb(flash_csb),
 		.clk(flash_clk),
@@ -115,4 +206,16 @@
 		.io3()			// not used
 	);
 endmodule
+
+module assert(input clk, input test);
+    always @(posedge clk)
+    begin
+        if (test !== 1)
+        begin
+            $display("%c[1;31mAssertation failed in %m %c[0m", 27, 27);
+            $finish_and_return(1);
+        end
+    end
+endmodule
+
 `default_nettype wire