Fixed clock cycle counter overflow, reset circuitry for icarus verilog and implemented statistics recording

This commit is contained in:
(Tim) Efthimis Kritikos 2023-05-23 10:28:58 +01:00
parent 88a47cc4a9
commit 98e73af5da
6 changed files with 137 additions and 19 deletions

9
.gitignore vendored
View File

@ -5,12 +5,9 @@
*.bf.asm
*.swp
*.memdump
boot_code/brainfuck_interpreted.bin
boot_code/brainfuck_interpreted.txt
boot_code/brainfuck_mandelbrot.bin
boot_code/brainfuck_mandelbrot.txt
boot_code/brainfuck_compiled.bin
boot_code/brainfuck_compiled.txt
*.json
boot_code/*.bin
boot_code/*.txt
system/boot_code.bin
system/boot_code.txt
system/obj_dir/

View File

@ -57,6 +57,10 @@ ifeq "${SIM}" "ICARUS"
%.run: %.txt ${SYSTEM_VVP} ${MICROCODE}
${QUIET_VVP}
${Q}vvp -i "${SYSTEM_VVP}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
%.json: %.txt ${SYSTEM_VVP} ${MICROCODE}
${QUIET_VVP}
${Q}vvp -i "${SYSTEM_VVP}" +STATS="$@" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
else ifeq "${SIM}" "VERILATOR"
%.fst %.memdump: %.txt ${VERILATOR_BIN} ${MICROCODE}
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
@ -64,6 +68,10 @@ else ifeq "${SIM}" "VERILATOR"
${Q}grep -v '^//' "$(subst .txt,.memdumptxt,$<)" | xxd -ps -c 2 -r > "$(subst .txt,.memdump,$<)"
${Q}rm "$(subst .txt,.memdumptxt,$<)"
%.json: %.txt ${VERILATOR_BIN} ${MICROCODE}
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
${Q} ${NUMACTL} "${VERILATOR_BIN}" +STATS=$@ +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
%.run: %.txt ${VERILATOR_BIN} ${MICROCODE}
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
${Q} ${NUMACTL} "${VERILATOR_BIN}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"

View File

@ -21,3 +21,12 @@
//`define DEBUG_REG_WRITES
//`define DEBUG_PC_ADDRESS
//`define DEBUG_MEMORY_WRITES
`define CALCULATE_IPC
`define OUTPUT_JSON_STATISTICS
/********** Internal **********/
`ifdef OUTPUT_JSON_STATISTICS
`define CALCULATE_IPC
`endif

View File

@ -29,7 +29,17 @@
//read: active low
//reset: active low
module processor ( input clock, input reset, output reg [19:0] external_address_bus, inout [15:0] external_data_bus,output reg read, output reg write,output reg BHE,output reg IOMEM, output reg HALT,output reg ERROR);
module processor (
/* MISC */ input clock, input reset, output reg HALT,output reg ERROR
/* MEMORY / IO */ ,output reg [19:0] external_address_bus, inout [15:0] external_data_bus,output reg read, output reg write,output reg BHE,output reg IOMEM
`ifdef CALCULATE_IPC
/* STATISTICS */ ,output reg new_instruction
`endif
`ifdef OUTPUT_JSON_STATISTICS
/* */ , output reg jump_debug
`endif
);
/*if we don't read, output the register to have the bus stable by the write falling edge*/
reg [15:0] data_bus_output_register;
@ -198,6 +208,12 @@ always @(posedge clock) begin
reg_write_we <= 1;
instruction_size_init <= 1;
state <= `PROC_IF_STATE_ENTRY;
`ifdef CALCULATE_IPC
new_instruction <= 0;
`endif
`ifdef OUTPUT_JSON_STATISTICS
jump_debug <= 0;
`endif
end
`PROC_HALT_STATE:begin
end
@ -210,6 +226,9 @@ always @(posedge clock) begin
reg_write_we <= 1;
state <= `PROC_IF_WRITE_CIR;
reg_write_in_sel <= 2'b00;
`ifdef OUTPUT_JSON_STATISTICS
jump_debug <= 0;
`endif
end
`PROC_IF_WRITE_CIR:begin
`ifdef DEBUG_PC_ADDRESS
@ -224,6 +243,9 @@ always @(posedge clock) begin
$display("Fetched instruction at %0x",ProgCount - 0);
end
`endif
`ifdef CALCULATE_IPC
new_instruction <= !new_instruction;
`endif
/*I built the entire decode stage with CIR
* being big endian so just convert it here*/
@ -523,6 +545,9 @@ always @(posedge clock) begin
state <= `PROC_NEXT_MICROCODE;
end
3'b101:begin /* Program Counter*/
`ifdef OUTPUT_JSON_STATISTICS
jump_debug <= 1;
`endif
ProgCount <= ALU_1O[15:0];
instruction_size_init <= 1;
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
@ -609,6 +634,9 @@ always @(posedge clock) begin
state <= `PROC_NEXT_MICROCODE;
end
`PROC_NEXT_MICROCODE:begin
`ifdef OUTPUT_JSON_STATISTICS
jump_debug <= 0;
`endif
read <= 0;
write <= 1; // maybe we are coming from MEMIO_WRITE
BHE <= 0;

View File

@ -18,31 +18,78 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
`timescale 1ns/1ps
`include "config.v"
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);
`ifdef CALCULATE_IPC
wire new_instruction;
`endif
`ifdef OUTPUT_JSON_STATISTICS
wire jump;
`endif
processor p(
/* MISC */ clock,reset,HALT,ERROR
/* MEMORY / IO */ ,address_bus,data_bus,rd,wr,BHE,IOMEM
`ifdef CALCULATE_IPC
/* STATISTICS */ ,new_instruction
`endif
`ifdef OUTPUT_JSON_STATISTICS
/* */ , jump
`endif
);
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
`ifdef OUTPUT_JSON_STATISTICS
string stats_name;
integer json_file_descriptor;
`endif
string waveform_name;
initial begin
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
$dumpfile(waveform_name);
$dumpvars(0,p);
end
`ifdef OUTPUT_JSON_STATISTICS
if($value$plusargs("STATS=%s",stats_name))begin
json_file_descriptor=$fopen(stats_name,"w");
$fdisplay(json_file_descriptor,"{\n\"L1_size\":0,\n\"Cycles\":[");
first_json_cycle = 1;
end else
json_file_descriptor=0;
`endif
end
`ifdef OUTPUT_JSON_STATISTICS
reg first_json_cycle;
always @(negedge clock)begin
if(HALT==0 && json_file_descriptor!=0)begin
$fdisplay(json_file_descriptor,"%s{\"C\":%0d,\"JMP\":%0d}",first_json_cycle?"":",",cycles,jump);
first_json_cycle <= 0;
end
end
`endif
always @(negedge wr) begin
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
$write("%s" ,data_bus[15:8]);
end
`ifdef CALCULATE_IPC
reg [128:0] instruction_count;
always @(new_instruction) begin
instruction_count<=instruction_count+1;
end
`endif
reg [1:0] finish;
string memdump_name;
always @(posedge HALT) begin
$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
@ -53,7 +100,17 @@ always @(posedge clock) begin
/* Allow some clock cycles for the waveform*/
case(finish)
2'd0: begin end
2'd1: finish <= 2;
2'd1: begin
finish <= 2;
$display("\x1b[7mProcessor halted.\nCycles run for : %0d\x1b[m",cycles);
`ifdef CALCULATE_IPC
$display("\x1b[7mInstr. per cycle : %f\x1b[m", $itor(instruction_count) / $itor(cycles) );
`endif
`ifdef OUTPUT_JSON_STATISTICS
if(json_file_descriptor!=0)
$fdisplay(json_file_descriptor,"],\n\"Total Cycles\":%0d,\n\"Instructions run\":%0d\n}",cycles,instruction_count);
`endif
end
2'd2: finish <= 3;
2'd3: $finish;
endcase
@ -67,13 +124,17 @@ always @(posedge ERROR) begin
finish<=2'd1;
end
integer cycles=0;
reg [128:0] cycles=0;
always @(posedge clock)begin
always @(negedge clock)begin
if(reset==1)
cycles<=cycles+1;
else
else begin
cycles<=0;
`ifdef CALCULATE_IPC
instruction_count <= 0;
`endif
end
end

View File

@ -46,13 +46,28 @@ clock_gen #(.FREQ(1000)) u1(clk_enable, clock);
string memdump_name;
initial begin
clk_enable = 1;
do_reset = 0;
reset<=1;
end
reset = 1;
#(`CPU_SPEED*2)
reset = 0;
#($random%1000)
#(`CPU_SPEED)
reset = 1;
reg [1:0]do_reset;
always @(posedge clock) begin
case(do_reset)
2'd0:begin
do_reset<=1;
end
2'd1:begin
do_reset<=2;
reset <= 0;
end
2'd2:begin
do_reset<=3;
reset <= 1;
end
2'd3:begin
end
endcase
end
endmodule