Added code to record statistics and a tool to plot them
This commit is contained in:
parent
df342467c7
commit
07d2a80b2e
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,6 +5,7 @@
|
|||||||
*.bf.asm
|
*.bf.asm
|
||||||
*.swp
|
*.swp
|
||||||
*.memdump
|
*.memdump
|
||||||
|
*.json
|
||||||
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
|
||||||
@ -14,3 +15,4 @@ boot_code/brainfuck_compiled.txt
|
|||||||
system/boot_code.bin
|
system/boot_code.bin
|
||||||
system/boot_code.txt
|
system/boot_code.txt
|
||||||
system/obj_dir/
|
system/obj_dir/
|
||||||
|
tools/*svg
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm
|
SOURCE=brainfuck_interpreted.asm brainfuck_compiled.asm brainfuck_mandelbrot.asm pipeline_ideal.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,.fst,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.fst,${SOURCE})
|
||||||
BUILD_FILES+=$(subst .asm,.bin,${SOURCE})
|
BUILD_FILES+=$(subst .asm,.bin,${SOURCE})
|
||||||
|
BUILD_FILES+=$(subst .asm,.json,${SOURCE})
|
||||||
|
|
||||||
all: ${BINARIES}
|
all: ${BINARIES}
|
||||||
|
|
||||||
|
106
boot_code/pipeline_ideal.asm
Normal file
106
boot_code/pipeline_ideal.asm
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
org 0x100
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
hlt
|
||||||
|
|
||||||
|
.ORG 0xFFF0
|
||||||
|
MOV AX,#0x0100
|
||||||
|
JMP AX
|
@ -32,7 +32,6 @@ run: $(subst .txt,.run,${BOOT_CODE})
|
|||||||
wave: $(subst .txt,.wave,${BOOT_CODE})
|
wave: $(subst .txt,.wave,${BOOT_CODE})
|
||||||
disas: $(subst .txt,.disas,${BOOT_CODE})
|
disas: $(subst .txt,.disas,${BOOT_CODE})
|
||||||
|
|
||||||
|
|
||||||
# Assembling code
|
# Assembling code
|
||||||
%.txt:%.bin
|
%.txt:%.bin
|
||||||
${Q}dd if=/dev/zero bs=1 count=65536 of="$(subst .bin,.stage,$<)" status=none
|
${Q}dd if=/dev/zero bs=1 count=65536 of="$(subst .bin,.stage,$<)" status=none
|
||||||
@ -57,6 +56,9 @@ ifeq "${SIM}" "ICARUS"
|
|||||||
%.run: %.txt ${SYSTEM_VVP} ${MICROCODE}
|
%.run: %.txt ${SYSTEM_VVP} ${MICROCODE}
|
||||||
${QUIET_VVP}
|
${QUIET_VVP}
|
||||||
${Q}vvp -i "${SYSTEM_VVP}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
${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"
|
else ifeq "${SIM}" "VERILATOR"
|
||||||
%.fst %.memdump: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
%.fst %.memdump: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
||||||
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
||||||
@ -64,6 +66,9 @@ else ifeq "${SIM}" "VERILATOR"
|
|||||||
${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,$<)"
|
||||||
|
|
||||||
|
%.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}
|
%.run: %.txt ${VERILATOR_BIN} ${MICROCODE}
|
||||||
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
$(call QUIET_VERILATOR_RUN,$(word 2,$^),$<)
|
||||||
${Q} ${NUMACTL} "${VERILATOR_BIN}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
${Q} ${NUMACTL} "${VERILATOR_BIN}" +BOOT_CODE="$<" +MICROCODE="${MICROCODE}"
|
||||||
|
@ -46,16 +46,16 @@ VERILATOR_OPTS += -x-assign fast --x-initial fast
|
|||||||
# COMPILING
|
# COMPILING
|
||||||
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
|
${SYSTEM_VVP} : ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES} ${EVENT_SIM_TESTBENCH}
|
||||||
${QUIET_IVERILOG}
|
${QUIET_IVERILOG}
|
||||||
${Q}iverilog -g2012 -o "$@" ${TOP_LEVEL_SOURCE} ${SOURCES} ${EVENT_SIM_TESTBENCH}
|
${Q}iverilog -g2012 -D CALCULATE_IPC -D OTUPUT_JSON_STATISTICS -o "$@" ${TOP_LEVEL_SOURCE} ${SOURCES} ${EVENT_SIM_TESTBENCH}
|
||||||
|
|
||||||
${VERILATOR_BIN}: ${VERILATOR_BIN}.mk
|
${VERILATOR_BIN}: ${VERILATOR_BIN}.mk
|
||||||
${Q}make ${MAKEOPTS} OPT_FAST="-O2 -march=native -mtune=native" -C obj_dir -f ../verilator_makefile Vsystem
|
${Q}make ${MAKEOPTS} OPT_FAST="-O2 -march=native -mtune=native" -C obj_dir -f ../verilator_makefile Vsystem
|
||||||
|
|
||||||
${VERILATOR_BIN}.mk: ${VERILATOR_TESTBENCH} ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
|
${VERILATOR_BIN}.mk: ${VERILATOR_TESTBENCH} ${TOP_LEVEL_SOURCE} ${SOURCES} ${INCLUDES}
|
||||||
${QUIET_VERILATOR}
|
${QUIET_VERILATOR}
|
||||||
${Q}verilator ${VERILATOR_OPTS} $^
|
${Q}verilator -DCALCULATE_IPC -DOTUPUT_JSON_STATISTICS ${VERILATOR_OPTS} $^
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(call QUIET_CLEAN,system)
|
$(call QUIET_CLEAN,system)
|
||||||
${Q}rm -rf ${SYSTEM_VVP} *.fst 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 *json
|
||||||
|
16
system/biu.v
16
system/biu.v
@ -43,8 +43,16 @@ module BIU (
|
|||||||
/* Internal */ output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION, input jump_req,
|
/* Internal */ output reg [31:0] INSTRUCTION, output reg VALID_INSTRUCTION, output reg [15:0] INSTRUCTION_LOCATION, input jump_req,
|
||||||
/* */ input[15:0] ADDRESS_INPUT, inout [15:0] DATA, input write_request, input read_request, input Wbit, output reg VALID_DATA, input MEM_OR_IO,
|
/* */ input[15:0] ADDRESS_INPUT, inout [15:0] DATA, input write_request, input read_request, input Wbit, output reg VALID_DATA, input MEM_OR_IO,
|
||||||
/* */ input [`PROC_STATE_BITS-1:0] proc_state, input SIMPLE_MICRO
|
/* */ input [`PROC_STATE_BITS-1:0] proc_state, input SIMPLE_MICRO
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
/* Statistics */ ,output wire [`L1_CACHE_SIZE-1:0] FIFO_SIZE_STAT, output wire VALID_INSTRUCTION_STAT
|
||||||
|
`endif
|
||||||
);
|
);
|
||||||
|
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
assign FIFO_SIZE_STAT = FIFO_SIZE;
|
||||||
|
assign VALID_INSTRUCTION_STAT = ((Isit1==1) && (FIFO_SIZE!=0) && `EARLY_VALID_INSTRUCTION_) || ((fifoIsize==2) && (FIFO_SIZE > 1) && `EARLY_VALID_INSTRUCTION_) || ((fifoIsize==3) && (FIFO_SIZE > 2) && `EARLY_VALID_INSTRUCTION_) || (FIFO_SIZE>3);
|
||||||
|
`endif
|
||||||
|
|
||||||
reg [15:0] data_bus_output_register;
|
reg [15:0] data_bus_output_register;
|
||||||
assign external_data_bus=read?data_bus_output_register:16'hz;
|
assign external_data_bus=read?data_bus_output_register:16'hz;
|
||||||
|
|
||||||
@ -153,11 +161,11 @@ always @(posedge clock) begin
|
|||||||
end else if(INSTRUCTION_ADDRESS[0:0]==0)begin
|
end else if(INSTRUCTION_ADDRESS[0:0]==0)begin
|
||||||
INPUT_FIFO[FIFO_end] <= external_data_bus[7:0];
|
INPUT_FIFO[FIFO_end] <= external_data_bus[7:0];
|
||||||
FIFO_end <= FIFO_end+4'd1;
|
FIFO_end <= FIFO_end+4'd1;
|
||||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+1;
|
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
||||||
end else begin
|
end else begin
|
||||||
INPUT_FIFO[FIFO_end] <= external_data_bus[15:8];
|
INPUT_FIFO[FIFO_end] <= external_data_bus[15:8];
|
||||||
FIFO_end <= FIFO_end+4'd1;
|
FIFO_end <= FIFO_end+4'd1;
|
||||||
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+1;
|
INSTRUCTION_ADDRESS <= INSTRUCTION_ADDRESS+20'd1;
|
||||||
end
|
end
|
||||||
biu_state <= `BIU_NEXT_ACTION;
|
biu_state <= `BIU_NEXT_ACTION;
|
||||||
read<=1;
|
read<=1;
|
||||||
@ -176,7 +184,7 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
`BIU_PUT_UNALIGNED_PREP_NEXT2:begin
|
`BIU_PUT_UNALIGNED_PREP_NEXT2:begin
|
||||||
write <= 1;
|
write <= 1;
|
||||||
DATA_ADDRESS <= DATA_ADDRESS+1;
|
DATA_ADDRESS <= DATA_ADDRESS+20'd1;
|
||||||
BHE <= 1;
|
BHE <= 1;
|
||||||
biu_state <= `BIU_WRITE_EXIT;
|
biu_state <= `BIU_WRITE_EXIT;
|
||||||
end
|
end
|
||||||
@ -245,7 +253,7 @@ always @(posedge clock) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
`BIU_GET_SECOND_BYTE:begin
|
`BIU_GET_SECOND_BYTE:begin
|
||||||
DATA_ADDRESS <= DATA_ADDRESS+1;
|
DATA_ADDRESS <= DATA_ADDRESS+20'd1;
|
||||||
biu_state <= `BIU_GET_SECOND_BYTE1;
|
biu_state <= `BIU_GET_SECOND_BYTE1;
|
||||||
read <=0;
|
read <=0;
|
||||||
end
|
end
|
||||||
|
@ -22,6 +22,11 @@
|
|||||||
//`define DEBUG_PC_ADDRESS
|
//`define DEBUG_PC_ADDRESS
|
||||||
//`define DEBUG_DATA_READ_WRITES
|
//`define DEBUG_DATA_READ_WRITES
|
||||||
|
|
||||||
|
/** OUTPUT **/
|
||||||
|
/* These are usually set at build time*/
|
||||||
|
//`define CALCULATE_IPC
|
||||||
|
//`define OTUPUT_JSON_STATISTICS
|
||||||
|
|
||||||
/** Optimisations **/
|
/** Optimisations **/
|
||||||
|
|
||||||
/* Enables the ability to check if an instruction in the input
|
/* Enables the ability to check if an instruction in the input
|
||||||
@ -44,3 +49,7 @@
|
|||||||
`else
|
`else
|
||||||
`define EARLY_VALID_INSTRUCTION_ 0
|
`define EARLY_VALID_INSTRUCTION_ 0
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
`define CALCULATE_IPC
|
||||||
|
`endif
|
||||||
|
@ -36,7 +36,16 @@
|
|||||||
//read: active low
|
//read: active low
|
||||||
//reset: active low
|
//reset: active low
|
||||||
|
|
||||||
module processor ( input clock, input reset, output [19:0] external_address_bus, inout [15:0] external_data_bus,output read, output write,output BHE,output IOMEM, output wire HALT,output [`ERROR_BITS-1:0] ERROR);
|
module processor (
|
||||||
|
/* MISC */ input clock, input reset, output wire HALT,output [`ERROR_BITS-1:0] ERROR
|
||||||
|
/* MEMORY / IO */ ,output [19:0] external_address_bus, inout [15:0] external_data_bus,output read, output write,output BHE,output IOMEM
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
|
/* STATISTICS */ ,output reg new_instruction
|
||||||
|
`endif
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
/* */ ,output wire [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT, output wire VALID_INSTRUCTION_STAT
|
||||||
|
`endif
|
||||||
|
);
|
||||||
|
|
||||||
/* If there is an error either from the decoder or execution unit set it to ERROR */
|
/* If there is an error either from the decoder or execution unit set it to ERROR */
|
||||||
assign ERROR=(DE_ERROR!=`ERR_NO_ERROR)?DE_ERROR:(EXEC_ERROR!=`ERR_NO_ERROR)?EXEC_ERROR:`ERR_NO_ERROR;
|
assign ERROR=(DE_ERROR!=`ERR_NO_ERROR)?DE_ERROR:(EXEC_ERROR!=`ERR_NO_ERROR)?EXEC_ERROR:`ERR_NO_ERROR;
|
||||||
@ -99,6 +108,9 @@ BIU BIU(
|
|||||||
/* Internal */ ,INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION,biu_jump_req
|
/* Internal */ ,INSTRUCTION,VALID_INSTRUCTION,INSTRUCTION_LOCATION,biu_jump_req
|
||||||
/* */ ,BIU_ADDRESS_INPUT,BIU_DATA,biu_write_request,biu_read_request,Wbit,BIU_VALID_DATA,MEM_OR_IO
|
/* */ ,BIU_ADDRESS_INPUT,BIU_DATA,biu_write_request,biu_read_request,Wbit,BIU_VALID_DATA,MEM_OR_IO
|
||||||
/* */ ,state,SIMPLE_MICRO
|
/* */ ,state,SIMPLE_MICRO
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
/* Statistics */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT
|
||||||
|
`endif
|
||||||
);
|
);
|
||||||
|
|
||||||
assign BIU_DATA= biu_data_direction ? 16'hz : (memio_address_select ? reg_read_port1_data : ALU_O);
|
assign BIU_DATA= biu_data_direction ? 16'hz : (memio_address_select ? reg_read_port1_data : ALU_O);
|
||||||
@ -176,6 +188,9 @@ register_file register_file(
|
|||||||
|
|
||||||
always @(negedge reset) begin
|
always @(negedge reset) begin
|
||||||
state <= `PROC_HALT; //TODO: race condition ??
|
state <= `PROC_HALT; //TODO: race condition ??
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
|
new_instruction<=0;
|
||||||
|
`endif
|
||||||
end
|
end
|
||||||
always @(posedge reset) begin
|
always @(posedge reset) begin
|
||||||
state <= `PROC_RESET;
|
state <= `PROC_RESET;
|
||||||
@ -211,6 +226,9 @@ always @(posedge clock) begin
|
|||||||
`ifdef DEBUG_PC_ADDRESS
|
`ifdef DEBUG_PC_ADDRESS
|
||||||
$display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,INSTRUCTION);
|
$display("Running command at %04x (%08x)",INSTRUCTION_LOCATION,INSTRUCTION);
|
||||||
`endif
|
`endif
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
|
new_instruction <= !new_instruction;
|
||||||
|
`endif
|
||||||
ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end};
|
ProgCount <= INSTRUCTION_LOCATION+{12'b0,instr_end};
|
||||||
INSTRUCTION_BUFFER<=INSTRUCTION[23:0];
|
INSTRUCTION_BUFFER<=INSTRUCTION[23:0];
|
||||||
end
|
end
|
||||||
|
@ -19,19 +19,51 @@
|
|||||||
|
|
||||||
`timescale 1ns/1ps
|
`timescale 1ns/1ps
|
||||||
`include "error_header.v"
|
`include "error_header.v"
|
||||||
|
`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_BITS-1:0] 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_BITS-1:0] ERROR);
|
||||||
processor p(clock,reset,address_bus,data_bus,rd,wr,BHE,IOMEM,HALT,ERROR);
|
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
|
wire new_instruction;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
wire unsigned [`L1_CACHE_SIZE-1:0] L1_SIZE_STAT;
|
||||||
|
wire VALID_INSTRUCTION_STAT;
|
||||||
|
`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 OTUPUT_JSON_STATISTICS
|
||||||
|
/* */ ,L1_SIZE_STAT, VALID_INSTRUCTION_STAT
|
||||||
|
`endif
|
||||||
|
);
|
||||||
|
|
||||||
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
|
doublemem sysmem(address_bus,data_bus,rd,wr,BHE,IOMEM);
|
||||||
|
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
string stats_name;
|
||||||
|
integer json_file_descriptor;
|
||||||
|
`endif
|
||||||
string waveform_name;
|
string waveform_name;
|
||||||
initial begin
|
initial begin
|
||||||
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
|
if($value$plusargs("WAVEFORM=%s",waveform_name))begin
|
||||||
$dumpfile(waveform_name);
|
$dumpfile(waveform_name);
|
||||||
$dumpvars(0,p);
|
$dumpvars(0,p);
|
||||||
end
|
end
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
if($value$plusargs("STATS=%s",stats_name))begin
|
||||||
|
json_file_descriptor=$fopen(stats_name,"w");
|
||||||
|
$fdisplay(json_file_descriptor,"{\n\"L1_size\":%0d,\n\"Cycles\":[",$rtoi($pow(2,`L1_CACHE_SIZE)));
|
||||||
|
first_json_cycle = 1;
|
||||||
|
end else
|
||||||
|
json_file_descriptor=0;
|
||||||
|
`endif
|
||||||
end
|
end
|
||||||
|
|
||||||
//integer killswitch=0;
|
//integer killswitch=0;
|
||||||
@ -45,16 +77,32 @@ end
|
|||||||
// end
|
// end
|
||||||
//end
|
//end
|
||||||
|
|
||||||
|
`ifdef OTUPUT_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,\"L1\":%0d,\"VDI\":%0d}",first_json_cycle?"":",",cycles,L1_SIZE_STAT,VALID_INSTRUCTION_STAT);
|
||||||
|
first_json_cycle <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
always @(negedge wr) begin
|
always @(negedge wr) begin
|
||||||
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
|
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )
|
||||||
$write("%s" ,data_bus[15:8]);
|
$write("%s" ,data_bus[15:8]);
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [1:0] finish;
|
|
||||||
|
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
|
integer instruction_count;
|
||||||
|
always @(new_instruction) begin
|
||||||
|
instruction_count<=instruction_count+1;
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
|
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-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
|
||||||
@ -65,7 +113,20 @@ always @(posedge clock) begin
|
|||||||
/* Allow some clock cycles for the waveform*/
|
/* Allow some clock cycles for the waveform*/
|
||||||
case(finish)
|
case(finish)
|
||||||
2'd0: begin end
|
2'd0: begin end
|
||||||
2'd1: finish <= 2;
|
2'd1: begin
|
||||||
|
finish <= 2;
|
||||||
|
/* instruction_count gets updated at the sme time as HALT is pulled so wait a clock cycle to get an accurate reading*/
|
||||||
|
$display("\x1b[7mProcessor halted.\nCycles run for : %0d\x1b[m",cycles);
|
||||||
|
`ifdef CALCULATE_IPC
|
||||||
|
/* verilator lint_off REALCVT */
|
||||||
|
$display("\x1b[7mInstr. per cycle : %f\x1b[m", $itor(instruction_count) / $itor(cycles) );
|
||||||
|
/* verilator lint_on REALCVT */
|
||||||
|
`endif
|
||||||
|
`ifdef OTUPUT_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'd2: finish <= 3;
|
||||||
2'd3: $finish;
|
2'd3: $finish;
|
||||||
endcase
|
endcase
|
||||||
@ -84,7 +145,7 @@ always @( ERROR ) begin
|
|||||||
$display("Unimplemented addressing mode");
|
$display("Unimplemented addressing mode");
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
$display("Cycles run for: %d",cycles-1);
|
$display("Cycles run for: %0d",cycles-1);
|
||||||
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
if($value$plusargs("MEMDUMP=%s",memdump_name))begin
|
||||||
$writememh(memdump_name, system.sysmem.memory,0,32767);
|
$writememh(memdump_name, system.sysmem.memory,0,32767);
|
||||||
end
|
end
|
||||||
@ -92,13 +153,17 @@ always @( ERROR ) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
integer cycles=0;
|
integer cycles;
|
||||||
|
|
||||||
always @(posedge clock)begin
|
always @(negedge clock)begin
|
||||||
if(reset==1)
|
if(reset==1)
|
||||||
cycles<=cycles+1;
|
cycles<=cycles+1;
|
||||||
else
|
else begin
|
||||||
cycles<=0;
|
cycles<=0;
|
||||||
|
`ifdef OTUPUT_JSON_STATISTICS
|
||||||
|
instruction_count <= 0;
|
||||||
|
`endif
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,13 +46,27 @@ clock_gen #(.FREQ(1000)) u1(clk_enable, clock);
|
|||||||
string memdump_name;
|
string memdump_name;
|
||||||
initial begin
|
initial begin
|
||||||
clk_enable = 1;
|
clk_enable = 1;
|
||||||
|
do_reset = 0;
|
||||||
|
end
|
||||||
|
|
||||||
reset = 1;
|
reg [1:0]do_reset;
|
||||||
#(`CPU_SPEED*2)
|
|
||||||
reset = 0;
|
always @(posedge clock) begin
|
||||||
#($random%1000)
|
case(do_reset)
|
||||||
#(`CPU_SPEED)
|
2'd0:begin
|
||||||
reset = 1;
|
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
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
56
tools/plot.sh
Executable file
56
tools/plot.sh
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -euf
|
||||||
|
|
||||||
|
print_help(){
|
||||||
|
echo "$0 <json data file> <function> <output filename>"
|
||||||
|
echo " Possible functions:"
|
||||||
|
echo " cache_time : graph of cache utilisation in bytes over time in clock cycles"
|
||||||
|
echo " cache_util_freq : graph of the likelyhood of the cache for each utilisation"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$#" != 3 ] || ! [ -e "$1" ]
|
||||||
|
then
|
||||||
|
print_help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CSV_FILE=$(mktemp)
|
||||||
|
IN=$1
|
||||||
|
OUT=$3
|
||||||
|
|
||||||
|
jq -r '.Cycles[]| [.C,.L1,.VDI]|@csv' -- "$IN" > "$CSV_FILE"
|
||||||
|
|
||||||
|
BASE_GNUPLOT_OPTIONS="set datafile separator ',';set term svg;set output \"${OUT}\";"
|
||||||
|
|
||||||
|
case "$2" in
|
||||||
|
"cache_time")
|
||||||
|
CACHE_SIZE=$(jq -r .L1_size -- "$IN")
|
||||||
|
gnuplot -e "${BASE_GNUPLOT_OPTIONS}\
|
||||||
|
set xlabel \"Clock cycles\";\
|
||||||
|
set ylabel \"Cache utilisation (bytes)\";\
|
||||||
|
set offsets 0, 0, 3, 1;\
|
||||||
|
set ytics 0,1,$((CACHE_SIZE-1));\
|
||||||
|
unset colorbox;\
|
||||||
|
set ytics add (\"Valid\" -1);\
|
||||||
|
set palette model RGB defined ( 0 'red', 1 'green' );\
|
||||||
|
plot '${CSV_FILE}' using 1:2 with lines notitle ,\
|
||||||
|
'${CSV_FILE}' using 1:(-0.75):(0):(-0.5):3 with vectors nohead palette notitle"
|
||||||
|
|
||||||
|
;;
|
||||||
|
"cache_util_freq")
|
||||||
|
CACHE_SIZE=$(jq -r .L1_size -- "$IN")
|
||||||
|
gnuplot -e "${BASE_GNUPLOT_OPTIONS}\
|
||||||
|
set xlabel \"Utilisation (bytes)\";\
|
||||||
|
set ylabel \"Occurrences\";\
|
||||||
|
set boxwidth 0.5;\
|
||||||
|
set style fill solid 0.4;\
|
||||||
|
set xtics 0,1,$((CACHE_SIZE-1));\
|
||||||
|
set offsets 1, 2, 0, 0;\
|
||||||
|
plot '${CSV_FILE}' using 2:(1) smooth frequency with boxes notitle"
|
||||||
|
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print_help;
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
Loading…
Reference in New Issue
Block a user