Added code to record statistics and a tool to plot them

This commit is contained in:
(Tim) Efthimis Kritikos 2023-05-14 16:06:33 +01:00
parent df342467c7
commit 07d2a80b2e
11 changed files with 308 additions and 24 deletions

2
.gitignore vendored
View File

@ -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

View File

@ -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}

View 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

View File

@ -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}"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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