Wrote a more complete testbench for verilator, switched from lx2 to fst and fixed cpu clock frequency calculation
This commit is contained in:
parent
5705b8e8a5
commit
99cbc49e95
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,11 +1,10 @@
|
|||||||
*.vvp
|
*.vvp
|
||||||
*.vpi
|
*.vpi
|
||||||
*.lx2
|
*.fst
|
||||||
*.o
|
*.o
|
||||||
*.bf.asm
|
*.bf.asm
|
||||||
*.swp
|
*.swp
|
||||||
*.memdump
|
*.memdump
|
||||||
*.lxt # Not sure when those crop up
|
|
||||||
boot_code/brainfuck_interpreted.bin
|
boot_code/brainfuck_interpreted.bin
|
||||||
boot_code/brainfuck_interpreted.txt
|
boot_code/brainfuck_interpreted.txt
|
||||||
boot_code/brainfuck_mandelbrot.bin
|
boot_code/brainfuck_mandelbrot.bin
|
||||||
|
@ -2,7 +2,7 @@ SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm
|
|||||||
BINARIES=$(subst .asm,.txt,${SOURCE})
|
BINARIES=$(subst .asm,.txt,${SOURCE})
|
||||||
BUILD_FILES=${BINARIES}
|
BUILD_FILES=${BINARIES}
|
||||||
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.memdump,${SOURCE})
|
||||||
BUILD_FILES+=$(subst .asm,.lx2,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.fst,${SOURCE})
|
||||||
BUILD_FILES+=$(subst .asm,.bin,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.bin,${SOURCE})
|
||||||
|
|
||||||
all: ${BINARIES}
|
all: ${BINARIES}
|
||||||
@ -19,4 +19,4 @@ include ../common.mk
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(call QUIET_CLEAN,boot_code)
|
$(call QUIET_CLEAN,boot_code)
|
||||||
${Q}rm -f $(BUILD_FILES) *lxt *.bf.asm
|
${Q}rm -f $(BUILD_FILES) *.bf.asm
|
||||||
|
15
common.mk
15
common.mk
@ -5,10 +5,11 @@ QUIET=1
|
|||||||
# 2=normal make output
|
# 2=normal make output
|
||||||
|
|
||||||
SIM=VERILATOR
|
SIM=VERILATOR
|
||||||
#SIM=ICARUS
|
|
||||||
# SIM: VERILATOR: use Verilator
|
# SIM: VERILATOR: use Verilator
|
||||||
# ICARUS: use Icarus Verilog
|
# ICARUS: use Icarus Verilog
|
||||||
|
|
||||||
|
NUMACTL=#numactl -m 0 -C 0,1 --
|
||||||
|
|
||||||
|
|
||||||
ifeq "${QUIET}" "1"
|
ifeq "${QUIET}" "1"
|
||||||
QUIET_AS = @echo ' AS '$@;
|
QUIET_AS = @echo ' AS '$@;
|
||||||
@ -46,9 +47,9 @@ endif
|
|||||||
|
|
||||||
# Running simulation
|
# Running simulation
|
||||||
ifeq "${SIM}" "ICARUS"
|
ifeq "${SIM}" "ICARUS"
|
||||||
%.lx2 %.memdump: %.txt ${SYSTEM_VVP} ${MICROCODE}
|
%.fst %.memdump: %.txt ${SYSTEM_VVP} ${MICROCODE}
|
||||||
${QUIET_VVP}
|
${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}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)"
|
||||||
${Q}rm "$(subst .txt,.memdumptxt,$<)"
|
${Q}rm "$(subst .txt,.memdumptxt,$<)"
|
||||||
|
|
||||||
@ -56,20 +57,20 @@ ifeq "${SIM}" "ICARUS"
|
|||||||
${QUIET_VVP}
|
${QUIET_VVP}
|
||||||
${Q}vvp -i "${SYSTEM_VVP}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
${Q}vvp -i "${SYSTEM_VVP}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||||
else ifeq "${SIM}" "VERILATOR"
|
else ifeq "${SIM}" "VERILATOR"
|
||||||
%.lx2 %.memdump: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
%.fst %.memdump: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
||||||
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
$(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}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)"
|
||||||
${Q}rm "$(subst .txt,.memdumptxt,$<)"
|
${Q}rm "$(subst .txt,.memdumptxt,$<)"
|
||||||
|
|
||||||
%.run: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
%.run: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
||||||
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
$(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
|
endif
|
||||||
|
|
||||||
%.disas: %.bin
|
%.disas: %.bin
|
||||||
objdump -D -b binary -m i8086 $^ | less
|
objdump -D -b binary -m i8086 $^ | less
|
||||||
|
|
||||||
# Tools
|
# Tools
|
||||||
%.wave : %.lx2
|
%.wave : %.fst
|
||||||
gtkwave "$<" "${GTKWSAVE}"
|
gtkwave "$<" "${GTKWSAVE}"
|
||||||
|
@ -1,37 +1,42 @@
|
|||||||
[*]
|
[*]
|
||||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
[*] GTKWave Analyzer v3.3.111 (w)1999-2020 BSI
|
||||||
[*] Tue Feb 21 04:41:50 2023
|
[*] Sat Mar 4 23:56:38 2023
|
||||||
[*]
|
[*]
|
||||||
[dumpfile] "/home/user/UNI_DATA/COMS30046_2022_TB-2/projects/9086/boot_code/brainfuck_compiled.lx2"
|
[dumpfile] "/home/user/9086/boot_code/brainfuck_compiled.fst"
|
||||||
[dumpfile_mtime] "Tue Feb 21 04:40:18 2023"
|
[dumpfile_mtime] "Sat Mar 4 23:55:57 2023"
|
||||||
[dumpfile_size] 21374
|
[dumpfile_size] 464968
|
||||||
[savefile] "/home/user/UNI_DATA/COMS30046_2022_TB-2/projects/9086/gtkwave_savefile.gtkw"
|
[savefile] "/home/user/9086/gtkwave_savefile.gtkw"
|
||||||
[timestart] 513190000
|
[timestart] 500000000
|
||||||
[size] 1342 1059
|
[size] 1332 1017
|
||||||
[pos] -1 -1
|
[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
|
*-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] tb.
|
[treeopen] TOP.
|
||||||
[treeopen] tb.p.
|
[treeopen] TOP.system.
|
||||||
[sst_width] 221
|
[sst_width] 221
|
||||||
[signals_width] 293
|
[signals_width] 293
|
||||||
[sst_expanded] 1
|
[sst_expanded] 1
|
||||||
[sst_vpaned_height] 312
|
[sst_vpaned_height] 312
|
||||||
@28
|
@28
|
||||||
tb.p.clock[0]
|
TOP.system.clock
|
||||||
tb.p.reset[0]
|
TOP.system.reset
|
||||||
tb.p.state[5:0]
|
TOP.system.p.state[5:0]
|
||||||
@23
|
|
||||||
tb.p.ucode_seq_addr[4:0]
|
|
||||||
@22
|
@22
|
||||||
tb.p.external_address_bus[19:0]
|
TOP.system.p.ucode_seq_addr[3:0]
|
||||||
tb.p.external_data_bus[15:0]
|
TOP.system.address_bus[19:0]
|
||||||
tb.p.CIR[15:0]
|
TOP.system.data_bus[15:0]
|
||||||
tb.p.PARAM1[15:0]
|
TOP.system.p.CIR[15:0]
|
||||||
tb.p.PARAM2[15:0]
|
TOP.system.p.PARAM1[15:0]
|
||||||
|
TOP.system.p.PARAM2[15:0]
|
||||||
@28
|
@28
|
||||||
tb.p.read[0]
|
TOP.system.p.read
|
||||||
tb.p.write[0]
|
TOP.system.p.write
|
||||||
tb.p.ERROR[0]
|
@22
|
||||||
tb.p.SIMPLE_MICRO[0]
|
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] 1
|
||||||
[pattern_trace] 0
|
[pattern_trace] 0
|
||||||
|
@ -36,9 +36,9 @@ ${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH
|
|||||||
|
|
||||||
${VERILATOR_BIN}: ${VERILATOR_TESTBENCH} ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
|
${VERILATOR_BIN}: ${VERILATOR_TESTBENCH} ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
|
||||||
${QUIET_VERILATOR}
|
${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
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(call QUIET_CLEAN,system)
|
$(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
|
||||||
|
@ -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);
|
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);
|
processor p(clock,reset,address_bus,data_bus,rd,wr,BHE,IOMEM,HALT,ERROR);
|
||||||
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
|
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;
|
string memdump_name;
|
||||||
always @(posedge HALT) begin
|
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
|
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||||
$writememh(memdump_name, sysmem.memory,0,32767);
|
$writememh(memdump_name, sysmem.memory,0,32767);
|
||||||
end
|
end
|
||||||
// #(`CPU_SPEED) //Just for the waveform
|
finish<=2'd1;
|
||||||
$finish;
|
|
||||||
end
|
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
|
endmodule
|
||||||
|
@ -3,11 +3,19 @@
|
|||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
|
|
||||||
Vsystem *system_state;
|
Vsystem *system_state;
|
||||||
|
VerilatedContext* contextp;
|
||||||
|
|
||||||
|
/*In hz */
|
||||||
|
#define CPU_SPEED 1000
|
||||||
|
|
||||||
|
#define timeinc CPU_SPEED*1000000/2
|
||||||
|
|
||||||
void tick() {
|
void tick() {
|
||||||
system_state->clock = 1;
|
system_state->clock = 1;
|
||||||
|
contextp->timeInc(timeinc);
|
||||||
system_state->eval();
|
system_state->eval();
|
||||||
system_state->clock = 0;
|
system_state->clock = 0;
|
||||||
|
contextp->timeInc(timeinc);
|
||||||
system_state->eval();
|
system_state->eval();
|
||||||
//printf("tick() %04x\n",system_state->address_bus);
|
//printf("tick() %04x\n",system_state->address_bus);
|
||||||
//trace->dump(timestamp);
|
//trace->dump(timestamp);
|
||||||
@ -15,17 +23,31 @@ void tick() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
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);
|
contextp->commandArgs(argc, argv);
|
||||||
system_state = new Vsystem{contextp};
|
system_state = new Vsystem{contextp};
|
||||||
|
|
||||||
system_state->reset=1;
|
system_state->reset=1;
|
||||||
tick();
|
tick();
|
||||||
system_state->reset=0;
|
system_state->reset=0;
|
||||||
tick();
|
tick();
|
||||||
system_state->reset=1;
|
system_state->reset=1;
|
||||||
|
|
||||||
|
// Simulate until $finish
|
||||||
while(!contextp->gotFinish()){
|
while(!contextp->gotFinish()){
|
||||||
tick();
|
tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
system_state->final();
|
||||||
|
|
||||||
delete system_state;
|
delete system_state;
|
||||||
delete contextp;
|
delete contextp;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
`timescale 1ns/1ps
|
/*In hz */
|
||||||
|
`define CPU_SPEED 1000
|
||||||
|
|
||||||
module tb;
|
module tb;
|
||||||
wire clock;
|
wire clock;
|
||||||
@ -40,47 +41,20 @@ system system( .clock(clock),
|
|||||||
.IOMEM(IOMEM)
|
.IOMEM(IOMEM)
|
||||||
);
|
);
|
||||||
|
|
||||||
`define CPU_SPEED 1000
|
|
||||||
|
|
||||||
clock_gen #(.FREQ(1000)) u1(clk_enable, clock);
|
clock_gen #(.FREQ(1000)) u1(clk_enable, clock);
|
||||||
|
|
||||||
integer cycles=0;
|
|
||||||
|
|
||||||
string memdump_name;
|
string memdump_name;
|
||||||
initial begin
|
initial begin
|
||||||
string waveform_name;
|
|
||||||
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
|
|
||||||
$dumpfile(waveform_name);
|
|
||||||
$dumpvars(0,system);
|
|
||||||
end
|
|
||||||
clk_enable = 1;
|
clk_enable = 1;
|
||||||
|
|
||||||
reset = 1;
|
reset = 1;
|
||||||
#(`CPU_SPEED*2)
|
#(`CPU_SPEED*2)
|
||||||
reset = 0;
|
reset = 0;
|
||||||
#($random%1000)
|
#($random%1000)
|
||||||
#(`CPU_SPEED)
|
#(`CPU_SPEED)
|
||||||
reset = 1;
|
reset = 1;
|
||||||
end
|
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
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
@ -91,7 +65,7 @@ parameter FREQ = 1000; // in HZ
|
|||||||
parameter PHASE = 0; // in degrees
|
parameter PHASE = 0; // in degrees
|
||||||
parameter DUTY = 50; // in percentage
|
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_on = DUTY/100.0 * clk_pd;
|
||||||
real clk_off = (100.0 - DUTY)/100.0 * clk_pd;
|
real clk_off = (100.0 - DUTY)/100.0 * clk_pd;
|
||||||
real quarter = clk_pd/4;
|
real quarter = clk_pd/4;
|
||||||
|
Loading…
Reference in New Issue
Block a user