diff --git a/.gitignore b/.gitignore index 73d0dad..e179820 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/common.mk b/common.mk index d3d7f30..08bf361 100644 --- a/common.mk +++ b/common.mk @@ -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}" diff --git a/system/config.v b/system/config.v index eb0c66a..fe6f0ac 100644 --- a/system/config.v +++ b/system/config.v @@ -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 diff --git a/system/processor.v b/system/processor.v index 261bf07..75e5f8a 100644 --- a/system/processor.v +++ b/system/processor.v @@ -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; diff --git a/system/system.v b/system/system.v index 0c651bc..5f2529a 100644 --- a/system/system.v +++ b/system/system.v @@ -18,31 +18,78 @@ along with this program. If not, see . */ `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 diff --git a/system/testbench.v b/system/testbench.v index 006567a..5e97d2d 100644 --- a/system/testbench.v +++ b/system/testbench.v @@ -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