Compare commits

...

2 Commits

12 changed files with 449 additions and 25 deletions

9
.gitignore vendored
View File

@ -5,12 +5,9 @@
*.bf.asm *.bf.asm
*.swp *.swp
*.memdump *.memdump
boot_code/brainfuck_interpreted.bin *.json
boot_code/brainfuck_interpreted.txt boot_code/*.bin
boot_code/brainfuck_mandelbrot.bin boot_code/*.txt
boot_code/brainfuck_mandelbrot.txt
boot_code/brainfuck_compiled.bin
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/

View File

@ -21,7 +21,7 @@ VERILATOR_BIN=system/obj_dir/Vsystem
BOOT_CODE=boot_code/brainfuck_mandelbrot.txt BOOT_CODE=boot_code/brainfuck_mandelbrot.txt
GTKWSAVE=./gtkwave_savefile.gtkw GTKWSAVE=./gtkwave_savefile.gtkw
MICROCODE=system/ucode.txt MICROCODE=system/ucode.txt
BOOTABLES=boot_code/brainfuck_compiled.txt boot_code/brainfuck_interpreted.txt ${BOOT_CODE} BOOTABLES=boot_code/brainfuck_compiled.txt boot_code/brainfuck_interpreted.txt ${BOOT_CODE} boot_code/fibonacci.txt boot_code/gnome_sort.txt
NO_ASM=1 NO_ASM=1
include common.mk include common.mk

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 fibonacci.asm gnome_sort.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}
@ -11,6 +12,9 @@ brainfuck_interpreted.bin: brainfuck_interpreter_v0.asm hello_9086.bf.asm dos_la
brainfuck_compiled.bin: brainfuck_compiler_v1.asm hello_9086.bf.asm dos_layer.asm brainfuck_compiled.bin: brainfuck_compiler_v1.asm hello_9086.bf.asm dos_layer.asm
brainfuck_mandelbrot.bin: brainfuck_compiler_v1.asm mandelbrot.bf.asm dos_layer.asm brainfuck_mandelbrot.bin: brainfuck_compiler_v1.asm mandelbrot.bf.asm dos_layer.asm
fibonacci.bin: helpers.asm
gnome_sort.bin: helpers.asm
%.bf.asm:%.bf %.bf.asm:%.bf
${Q}sed "s/[a-zA-Z\* ]//g;/^$$/d;s/^/.ASCII '/;s/\$$/'/" "$^" > $@ ${Q}sed "s/[a-zA-Z\* ]//g;/^$$/d;s/^/.ASCII '/;s/\$$/'/" "$^" > $@

38
boot_code/fibonacci.asm Normal file
View File

@ -0,0 +1,38 @@
INCLUDE dos_layer.asm
org 0x100
mov sp,#STACK
MOV AX,#0x1
MOV BX,#0x1
CALL PRINT_16_HEX
push bx
MAIN_LOOP:
pop bx
CALL PRINT_16_HEX
push AX
ADD AX,BX
JNC MAIN_LOOP
pop bx
MOV AH,#0x02
MOV DL,#0x0a
INT #0x21
hlt
.BLKB 200
STACK:
INCLUDE helpers.asm
.ORG 0xFFF0
MOV AX,#0x0100
JMP AX

54
boot_code/gnome_sort.asm Normal file
View File

@ -0,0 +1,54 @@
INCLUDE dos_layer.asm
.org 0x100
mov sp,#STACK
MOV SI,#DATA
GNOME_SORT:
CMP SI,#DATA+31
JZ GNOMED
MOV AX,[SI]
INC SI
CMP AH,AL
JAE GNOME_SORT
SWAP:
MOV BL,AL
MOV AL,AH
MOV AH,BL
DEC SI
MOV [SI],AX
CMP SI,#DATA
JZ GNOME_SORT
DEC SI
JMP GNOME_SORT
GNOMED:
MOV SI,#DATA
PRINT_LOOP:
MOV AL,[SI]
call PRINT_0_8_HEX
INC SI
CMP SI,#DATA+32
JNZ PRINT_LOOP
MOV AH,#0x02
MOV DL,#0x0a
INT #0x21
hlt
DATA: DB 0x51, 0x17, 0x37, 0x5d, 0x06, 0x3f, 0x51, 0x8b
DB 0xa5, 0x33, 0x54, 0xdf, 0xae, 0xee, 0x3a, 0x18
DB 0xe9, 0xdb, 0x1f, 0x21, 0x44, 0x4f, 0x99, 0x09
DB 0x2a, 0x23, 0x82, 0x4f, 0x52, 0xf1, 0xdc, 0x0b
.BLKB 200
STACK:
INCLUDE helpers.asm
.ORG 0xFFF0
MOV AX,#0x0100
JMP AX

93
boot_code/helpers.asm Normal file
View File

@ -0,0 +1,93 @@
;Input AX
PRINT_16_HEX:
PUSH DX
TEST AH,#0xF0
jz NOT_FIRST_NIBBLE
MOV DL,AH
CALL PRINT_HIGH
JMP SKIP1
NOT_FIRST_NIBBLE:
TEST AH,#0x0F
jz NOT_SECOND_NIBBLE
SKIP1:
MOV DL,AH
CALL PRINT_LOW
JMP SKIP2
NOT_SECOND_NIBBLE:
TEST AL,#0xF0
jz NOT_THIRD_NIBBLE
SKIP2:
MOV DL,AL
CALL PRINT_HIGH
NOT_THIRD_NIBBLE:
MOV DL,AL
CALL PRINT_LOW
PUSH AX
MOV AH,#0x02
MOV DL,#0x20
INT #0x21
POP AX
POP DX
RET
PRINT_HIGH:
AND DL,#0xF0
TEST DL,#0x80
jz NOT1
OR DL,#0x08
NOT1:
TEST DL,#0x40
jz NOT2
OR DL,#0x04
NOT2:
TEST DL,#0x20
jz NOT3
OR DL,#0x02
NOT3:
TEST DL,#0x10
jz DONE
OR DL,#0x01
DONE:
PRINT_LOW:
PUSH AX
AND DL,#0x0F
CMP DL,#0x0A
JNS LETTERS
ADD DL,#0x30
MOV AH,#0x02
INT #0x21
POP AX
RET
LETTERS:
ADD DL,#0x37
MOV AH,#0x02
INT #0x21
POP AX
RET
PRINT_0_8_HEX:
MOV DL,AL
PUSH AX
CALL PRINT_HIGH
POP AX
MOV DL,AL
CALL PRINT_LOW
PUSH AX
MOV AH,#0x02
MOV DL,#0x20
INT #0x21
POP AX
RET

View File

@ -57,6 +57,10 @@ 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 +68,10 @@ 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

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

View File

@ -184,19 +184,22 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
in_alu1_sel1=2'b00; in_alu1_sel1=2'b00;
OUT_MOD=3'b100; OUT_MOD=3'b100;
MEM_OR_IO=0; MEM_OR_IO=0;
ALU_1OP=`ALU_OP_SUB; ALU_1OP=`ALU_OP_SUB_REVERSE;
memio_address_select=0; memio_address_select=0;
if(IN_MOD==3'b011)begin if(IN_MOD==3'b011)begin
/*compare register with param*/ /*compare register with param*/
in_alu1_sel2=2'b01; in_alu1_sel2=2'b01;
reg_read_port2_addr={Wbit,RM}; reg_read_port2_addr={Wbit,RM};
next_state=`PROC_DE_LOAD_8_PARAM;
end else begin end else begin
/*compare register indirect access /*compare register indirect access
* with param */ * with param */
in_alu1_sel2=2'b00; in_alu1_sel2=2'b00;
next_state=`PROC_DE_LOAD_16_PARAM; /*will then call MEMIO_READ*/ /*will call MEMIO_READ after EXEC_DE_LOAD..*/
end end
if (Wbit)
next_state=`PROC_DE_LOAD_16_PARAM;
else
next_state=`PROC_DE_LOAD_8_PARAM;
`normal_instruction; `normal_instruction;
end end
11'b1011_0???_??? : begin 11'b1011_0???_??? : begin
@ -364,7 +367,7 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
in_alu1_sel2=2'b01; in_alu1_sel2=2'b01;
reg_read_port2_addr={Wbit,3'b000}; reg_read_port2_addr={Wbit,3'b000};
OUT_MOD=3'b100; OUT_MOD=3'b100;
ALU_1OP=`ALU_OP_SUB; ALU_1OP=`ALU_OP_SUB_REVERSE;
MEM_OR_IO=0; MEM_OR_IO=0;
if(Wbit==1) if(Wbit==1)
next_state=`PROC_DE_LOAD_16_PARAM; next_state=`PROC_DE_LOAD_16_PARAM;
@ -423,6 +426,13 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
else else
next_state=`PROC_EX_STATE_ENTRY; next_state=`PROC_EX_STATE_ENTRY;
end end
3'b001: begin
/* Jump on (not) Carry */
if(FLAGS[0:0]==CIR[8:8])
next_state=`PROC_IF_STATE_ENTRY;
else
next_state=`PROC_EX_STATE_ENTRY;
end
default:begin default:begin
`invalid_instruction; /*We don't support that condition*/ `invalid_instruction; /*We don't support that condition*/
end end
@ -526,6 +536,29 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
`normal_instruction; `normal_instruction;
memio_address_select=0; memio_address_select=0;
end end
11'b1010_100?_???:begin
/* TEST - Bitwise AND of immediate and accumulator affecting only flags */
/* 1 0 1 0 1 0 0 W | DATA | DATA if W | */
opcode_size=0;
Wbit=CIR[8:8];
IN_MOD=3'b011;
RM=3'b000;
MEM_OR_IO=0;
if(Wbit==1)begin
instruction_size=3;
next_state=`PROC_DE_LOAD_16_PARAM;
end else begin
instruction_size=2;
next_state=`PROC_DE_LOAD_8_PARAM;
end
in_alu1_sel1=2'b00; /* PARAM1 */
ALU_1OP=`ALU_OP_AND;
in_alu1_sel2=2'b01;
reg_read_port2_addr={Wbit,RM};
OUT_MOD=3'b100;/*NULL*/
`normal_instruction;
memio_address_select=0;
end
11'b0101_1???_???:begin 11'b0101_1???_???:begin
/* POP - REG=[SP]; SP+=2 */ /* POP - REG=[SP]; SP+=2 */
/* | 0 1 0 1 1 REG | */ /* | 0 1 0 1 1 REG | */
@ -629,6 +662,90 @@ always @( CIR or SIMPLE_MICRO or seq_addr_input ) begin
seq_addr_entry<=`UCODE_RET_ENTRY; seq_addr_entry<=`UCODE_RET_ENTRY;
memio_address_select=0; memio_address_select=0;
end end
11'b1000_000?_100,11'b1000_000?_001:begin
/* OR - Bitwise OR immediate and register/mem */
/* 1 0 0 0 0 0 0 W | MOD 0 0 1 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
/* AND - Bitwise AND immediate and register/mem */
/* 1 0 0 0 0 0 0 W | MOD 1 0 0 R/M | < DISP-LO > | < DISP-HI > | DATA | DATA if W */
opcode_size=1;
Wbit=CIR[8:8];
IN_MOD={1'b0,CIR[7:6]};
RM={CIR[2:0]};
MEM_OR_IO=0;
if(Wbit==1)begin
instruction_size=4;
next_state=`PROC_DE_LOAD_16_PARAM;
end else begin
instruction_size=3;
next_state=`PROC_DE_LOAD_8_PARAM;
end
in_alu1_sel1=2'b00; /* PARAM1 */
case(CIR[5:3])
3'b100: ALU_1OP=`ALU_OP_AND;
3'b001: ALU_1OP=`ALU_OP_OR;
default:begin end
endcase
case(IN_MOD)
3'b011:begin
in_alu1_sel2=2'b01;
reg_read_port2_addr={Wbit,RM};
reg_write_addr={Wbit,RM};
`normal_instruction;
end
default:begin
`invalid_instruction;
end
endcase
OUT_MOD=IN_MOD;
memio_address_select=0;
end
11'b0000_00??_???,11'b0010_10??_???,11'b0011_10??_???:begin
/* CMP - Compare Register/memory and register */
/* 0 0 1 1 1 0 D W | MOD REG R/M | < DISP LO > | < DISP HI > | */
/* SUB - Reg/memory with register to either */
/* 0 0 1 0 1 0 D W | MOD REG R/M | < DISP LO > | < DISP HI > | */
/* ADD - Reg/memory with register to either */
/* 0 0 0 0 0 0 D W | MOD REG R/M | < DISP LO > | < DISP HI > | */
instruction_size=2;
opcode_size=1;
Wbit=CIR[8:8];
Sbit=0;
IN_MOD=3'b011;
RM=CIR[2:0];
in_alu1_sel1=2'b01;//constantly register
reg_read_port1_addr={Wbit,CIR[5:3]};
if(IN_MOD==3'b011)begin
in_alu1_sel2=2'b01;
reg_read_port2_addr={Wbit,RM};
reg_write_addr={Wbit,RM};
next_state=`PROC_EX_STATE_ENTRY;
end else begin
in_alu1_sel2=2'b00;
if(Wbit)
next_state=`PROC_DE_LOAD_16_PARAM;
else
next_state=`PROC_DE_LOAD_8_PARAM;
end
MEM_OR_IO=0;
memio_address_select=0;
case (CIR[13:10])
4'b0000: ALU_1OP=`ALU_OP_ADD;
4'b1010: ALU_1OP=`ALU_OP_SUB;
4'b1110: ALU_1OP=`ALU_OP_SUB_REVERSE;
default: begin end
endcase
case (CIR[13:10])
4'b0000: OUT_MOD={1'b0,CIR[7:6]};
4'b1010: OUT_MOD={1'b0,CIR[7:6]};
4'b1110: OUT_MOD=3'b100; /* NULL */
default: begin end
endcase
if(CIR[9:9]==1'b0) begin
`normal_instruction;
end else begin
`invalid_instruction
end
end
default:begin default:begin
`invalid_instruction `invalid_instruction
end end

View File

@ -29,7 +29,17 @@
//read: active low //read: active low
//reset: 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*/ /*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; reg [15:0] data_bus_output_register;
@ -198,6 +208,12 @@ always @(posedge clock) begin
reg_write_we <= 1; reg_write_we <= 1;
instruction_size_init <= 1; instruction_size_init <= 1;
state <= `PROC_IF_STATE_ENTRY; state <= `PROC_IF_STATE_ENTRY;
`ifdef CALCULATE_IPC
new_instruction <= 0;
`endif
`ifdef OUTPUT_JSON_STATISTICS
jump_debug <= 0;
`endif
end end
`PROC_HALT_STATE:begin `PROC_HALT_STATE:begin
end end
@ -210,6 +226,9 @@ always @(posedge clock) begin
reg_write_we <= 1; reg_write_we <= 1;
state <= `PROC_IF_WRITE_CIR; state <= `PROC_IF_WRITE_CIR;
reg_write_in_sel <= 2'b00; reg_write_in_sel <= 2'b00;
`ifdef OUTPUT_JSON_STATISTICS
jump_debug <= 0;
`endif
end end
`PROC_IF_WRITE_CIR:begin `PROC_IF_WRITE_CIR:begin
`ifdef DEBUG_PC_ADDRESS `ifdef DEBUG_PC_ADDRESS
@ -224,6 +243,9 @@ always @(posedge clock) begin
$display("Fetched instruction at %0x",ProgCount - 0); $display("Fetched instruction at %0x",ProgCount - 0);
end end
`endif `endif
`ifdef CALCULATE_IPC
new_instruction <= !new_instruction;
`endif
/*I built the entire decode stage with CIR /*I built the entire decode stage with CIR
* being big endian so just convert it here*/ * being big endian so just convert it here*/
@ -523,6 +545,9 @@ always @(posedge clock) begin
state <= `PROC_NEXT_MICROCODE; state <= `PROC_NEXT_MICROCODE;
end end
3'b101:begin /* Program Counter*/ 3'b101:begin /* Program Counter*/
`ifdef OUTPUT_JSON_STATISTICS
jump_debug <= 1;
`endif
ProgCount <= ALU_1O[15:0]; ProgCount <= ALU_1O[15:0];
instruction_size_init <= 1; instruction_size_init <= 1;
if (ucode_seq_addr==`UCODE_NO_INSTRUCTION) if (ucode_seq_addr==`UCODE_NO_INSTRUCTION)
@ -609,6 +634,9 @@ always @(posedge clock) begin
state <= `PROC_NEXT_MICROCODE; state <= `PROC_NEXT_MICROCODE;
end end
`PROC_NEXT_MICROCODE:begin `PROC_NEXT_MICROCODE:begin
`ifdef OUTPUT_JSON_STATISTICS
jump_debug <= 0;
`endif
read <= 0; read <= 0;
write <= 1; // maybe we are coming from MEMIO_WRITE write <= 1; // maybe we are coming from MEMIO_WRITE
BHE <= 0; BHE <= 0;

View File

@ -18,31 +18,78 @@
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 `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); 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); 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; 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 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 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 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
`ifdef CALCULATE_IPC
reg [128:0] instruction_count;
always @(new_instruction) begin
instruction_count<=instruction_count+1;
end
`endif
reg [1:0] finish; 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
@ -53,7 +100,17 @@ 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;
$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'd2: finish <= 3;
2'd3: $finish; 2'd3: $finish;
endcase endcase
@ -67,13 +124,17 @@ always @(posedge ERROR) begin
finish<=2'd1; finish<=2'd1;
end end
integer cycles=0; reg [128:0] cycles=0;
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 CALCULATE_IPC
instruction_count <= 0;
`endif
end
end end

View File

@ -46,13 +46,28 @@ 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;
reset<=1;
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