Wrote a more complete testbench for verilator, switched from lx2 to fst and fixed cpu clock frequency calculation

This commit is contained in:
(Tim) Efthimis Kritikos 2023-03-05 00:10:55 +00:00
parent 5705b8e8a5
commit 99cbc49e95
8 changed files with 112 additions and 73 deletions

3
.gitignore vendored
View File

@ -1,11 +1,10 @@
*.vvp
*.vpi
*.lx2
*.fst
*.o
*.bf.asm
*.swp
*.memdump
*.lxt # Not sure when those crop up
boot_code/brainfuck_interpreted.bin
boot_code/brainfuck_interpreted.txt
boot_code/brainfuck_mandelbrot.bin

View File

@ -2,7 +2,7 @@ SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm
BINARIES=$(subst .asm,.txt,${SOURCE})
BUILD_FILES=${BINARIES}
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE})
BUILD_FILES+=$(subst .asm,.lx2,${SOURCE})
BUILD_FILES+=$(subst .asm,.fst,${SOURCE})
BUILD_FILES+=$(subst .asm,.bin,${SOURCE})
all: ${BINARIES}
@ -19,4 +19,4 @@ include ../common.mk
clean:
$(call QUIET_CLEAN,boot_code)
${Q}rm -f $(BUILD_FILES) *lxt *.bf.asm
${Q}rm -f $(BUILD_FILES) *.bf.asm

View File

@ -5,10 +5,11 @@ QUIET=1
# 2=normal make output
SIM=VERILATOR
#SIM=ICARUS
# SIM: VERILATOR: use Verilator
# ICARUS: use Icarus Verilog
NUMACTL=#numactl -m 0 -C 0,1 --
ifeq "${QUIET}" "1"
QUIET_AS = @echo ' AS '$@;
@ -46,9 +47,9 @@ endif
# Running simulation
ifeq "${SIM}" "ICARUS"
%.lx2 %.memdump: %.txt ${SYSTEM_VVP} ${MICROCODE}
%.fst %.memdump: %.txt ${SYSTEM_VVP} ${MICROCODE}
${QUIET_VVP}
${Q}vvp "${SYSTEM_VVP}" -lxt2 +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.lx2,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
${Q}vvp "${SYSTEM_VVP}" -fst +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.fst,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
${Q}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)"
${Q}rm "$(subst .txt,.memdumptxt,$<)"
@ -56,20 +57,20 @@ ifeq "${SIM}" "ICARUS"
${QUIET_VVP}
${Q}vvp -i "${SYSTEM_VVP}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
else ifeq "${SIM}" "VERILATOR"
%.lx2 %.memdump: %.txt ${VERILATOR_BIN} ${MICROCODE}
%.fst %.memdump: %.txt ${VERILATOR_BIN} ${MICROCODE}
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
${Q}"${VERILATOR_BIN}" +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.lx2,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
${Q}"${VERILATOR_BIN}" +BOOT_CODE="$<" +WAVEFORM="$(subst .txt,.fst,$<)" +MEMDUMP="$(subst .txt,.memdumptxt,$<)" +MICROCODE="${MICROCODE}"
${Q}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)"
${Q}rm "$(subst .txt,.memdumptxt,$<)"
%.run: %.txt ${VERILATOR_BIN} ${MICROCODE}
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
${Q}numactl -m 0 -C 17,18 -- "${VERILATOR_BIN}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
${Q} ${NUMACTL} "${VERILATOR_BIN}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
endif
%.disas: %.bin
objdump -D -b binary -m i8086 $^ | less
# Tools
%.wave : %.lx2
%.wave : %.fst
gtkwave "$<" "${GTKWSAVE}"

View File

@ -1,37 +1,42 @@
[*]
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
[*] Tue Feb 21 04:41:50 2023
[*] GTKWave Analyzer v3.3.111 (w)1999-2020 BSI
[*] Sat Mar 4 23:56:38 2023
[*]
[dumpfile] "/home/user/UNI_DATA/COMS30046_2022_TB-2/projects/9086/boot_code/brainfuck_compiled.lx2"
[dumpfile_mtime] "Tue Feb 21 04:40:18 2023"
[dumpfile_size] 21374
[savefile] "/home/user/UNI_DATA/COMS30046_2022_TB-2/projects/9086/gtkwave_savefile.gtkw"
[timestart] 513190000
[size] 1342 1059
[dumpfile] "/home/user/9086/boot_code/brainfuck_compiled.fst"
[dumpfile_mtime] "Sat Mar 4 23:55:57 2023"
[dumpfile_size] 464968
[savefile] "/home/user/9086/gtkwave_savefile.gtkw"
[timestart] 500000000
[size] 1332 1017
[pos] -1 -1
*-23.795050 802940000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] tb.
[treeopen] tb.p.
*-37.895050 40500000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] TOP.
[treeopen] TOP.system.
[sst_width] 221
[signals_width] 293
[sst_expanded] 1
[sst_vpaned_height] 312
@28
tb.p.clock[0]
tb.p.reset[0]
tb.p.state[5:0]
@23
tb.p.ucode_seq_addr[4:0]
TOP.system.clock
TOP.system.reset
TOP.system.p.state[5:0]
@22
tb.p.external_address_bus[19:0]
tb.p.external_data_bus[15:0]
tb.p.CIR[15:0]
tb.p.PARAM1[15:0]
tb.p.PARAM2[15:0]
TOP.system.p.ucode_seq_addr[3:0]
TOP.system.address_bus[19:0]
TOP.system.data_bus[15:0]
TOP.system.p.CIR[15:0]
TOP.system.p.PARAM1[15:0]
TOP.system.p.PARAM2[15:0]
@28
tb.p.read[0]
tb.p.write[0]
tb.p.ERROR[0]
tb.p.SIMPLE_MICRO[0]
TOP.system.p.read
TOP.system.p.write
@22
TOP.system.p.ALU_1A[15:0]
TOP.system.p.ALU_1B[15:0]
TOP.system.p.ALU_1O[15:0]
@28
TOP.system.p.ERROR
@29
TOP.system.p.HALT
[pattern_trace] 1
[pattern_trace] 0

View File

@ -36,9 +36,9 @@ ${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH
${VERILATOR_BIN}: ${VERILATOR_TESTBENCH} ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
${QUIET_VERILATOR}
${Q}verilator --cc --exe --build -j 0 $^ -Wall --Wno-DECLFILENAME -Wno-SYNCASYNCNET -Wno-MULTIDRIVEN 2>&1 --threads 1 --autoflush >/dev/null #TODO: remove the silencing and make the generated Makefiles print quietly as well
${Q}verilator --trace-fst --cc --exe --build -j 0 $^ -Wall --Wno-DECLFILENAME -Wno-SYNCASYNCNET -Wno-MULTIDRIVEN 2>&1 --threads 1 --autoflush >/dev/null #TODO: remove the silencing and make the generated Makefiles print quietly as well
.PHONY: clean
clean:
$(call QUIET_CLEAN,system)
${Q}rm -rf ${SYSTEM_VVP} *.lx2 boot_code.txt boot_code.bin *memdump *memdumptxt obj_dir
${Q}rm -rf ${SYSTEM_VVP} *.fst boot_code.txt boot_code.bin *memdump *memdumptxt obj_dir

View File

@ -1,17 +1,55 @@
`define CPU_SPEED 1000
`timescale 1ns/1ps
module system ( input clock,input reset, output [19:0]address_bus, inout [15:0]data_bus,output BHE, output rd, output wr, output IOMEM, output HALT, output ERROR);
processor p(clock,reset,address_bus,data_bus,rd,wr,BHE,IOMEM,HALT,ERROR);
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
string waveform_name;
initial begin
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
$dumpfile(waveform_name);
$dumpvars(0,p);
end
end
reg [1:0] finish;
string memdump_name;
always @(posedge HALT) begin
// $display("Processor halted.\nCycles run for: %d",cycles);
$display("Processor halted.\nCycles run for: %d",cycles-1);
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
$writememh(memdump_name, sysmem.memory,0,32767);
end
// #(`CPU_SPEED) //Just for the waveform
$finish;
finish<=2'd1;
end
always @(posedge clock) begin
/* Allow some clock cycles for the waveform*/
case(finish)
2'd0: begin end
2'd1: finish <= 2;
2'd2: finish <= 3;
2'd3: $finish;
endcase
end
always @(posedge ERROR) begin
$display("PROCESSOR RUN INTO AN ERROR.\nCycles run for: %d",cycles-1);
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
$writememh(memdump_name, system.sysmem.memory,0,32767);
end
finish<=2'd1;
end
integer cycles=0;
always @(posedge clock)begin
if(reset==1)
cycles<=cycles+1;
else
cycles<=0;
end
endmodule

View File

@ -3,11 +3,19 @@
#include "stdio.h"
Vsystem *system_state;
VerilatedContext* contextp;
/*In hz */
#define CPU_SPEED 1000
#define timeinc CPU_SPEED*1000000/2
void tick() {
system_state->clock = 1;
contextp->timeInc(timeinc);
system_state->eval();
system_state->clock = 0;
contextp->timeInc(timeinc);
system_state->eval();
//printf("tick() %04x\n",system_state->address_bus);
//trace->dump(timestamp);
@ -15,17 +23,31 @@ void tick() {
}
int main(int argc, char** argv) {
VerilatedContext* contextp = new VerilatedContext;
contextp = new VerilatedContext;
// Set debug level, 0 is off, 9 is highest presently used
// May be overridden by commandArgs argument parsing
contextp->debug(0);
// Verilator must compute traced signals
contextp->traceEverOn(true);
contextp->commandArgs(argc, argv);
system_state = new Vsystem{contextp};
system_state->reset=1;
tick();
system_state->reset=0;
tick();
system_state->reset=1;
// Simulate until $finish
while(!contextp->gotFinish()){
tick();
}
system_state->final();
delete system_state;
delete contextp;
return 0;

View File

@ -17,7 +17,8 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
`timescale 1ns/1ps
/*In hz */
`define CPU_SPEED 1000
module tb;
wire clock;
@ -40,47 +41,20 @@ system system( .clock(clock),
.IOMEM(IOMEM)
);
`define CPU_SPEED 1000
clock_gen #(.FREQ(1000)) u1(clk_enable, clock);
integer cycles=0;
string memdump_name;
initial begin
string waveform_name;
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
$dumpfile(waveform_name);
$dumpvars(0,system);
end
clk_enable = 1;
reset = 1;
#(`CPU_SPEED*2)
reset = 0;
#($random%1000)
#(`CPU_SPEED)
#(`CPU_SPEED)
reset = 1;
end
always @(posedge ERROR) begin
clk_enable <= 0;
$display("PROCESSOR RUN INTO AN ERROR.\nCycles run for: %d",cycles);
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
$writememh(memdump_name, system.sysmem.memory,0,32767);
end
#(`CPU_SPEED) //Just for the waveform
$finish;
end
always @(posedge clock)begin
if(reset==1)
cycles=cycles+1;
else
cycles=0;
end
endmodule
@ -91,7 +65,7 @@ parameter FREQ = 1000; // in HZ
parameter PHASE = 0; // in degrees
parameter DUTY = 50; // in percentage
real clk_pd = 1.0/FREQ * 1000000; // convert to ms
real clk_pd = 1.0/FREQ * 1000000000; // convert to ms
real clk_on = DUTY/100.0 * clk_pd;
real clk_off = (100.0 - DUTY)/100.0 * clk_pd;
real quarter = clk_pd/4;