diff --git a/slapper/src/main.rs b/slapper/src/main.rs index f665e45..a20db43 100644 --- a/slapper/src/main.rs +++ b/slapper/src/main.rs @@ -52,8 +52,11 @@ fn main() { format!("{byte:02X}") }).collect(); - let bit_length = from_contents.len() * 8; - let insert_mem = format!("reg [0:{}] mem = {bit_length}'h{mem_value};", bit_length - 1); + let contents_len = from_contents.len() * 8; + let bit_len = (2048 * 8).max(contents_len * 2); + let padding_len = bit_len - contents_len; + + let insert_mem = format!("reg [0:{}] mem = {{{contents_len}'h{mem_value}, {padding_len}'h0}};", bit_len - 1); into_contents = into_contents.replace("$$insert_mem$$", &insert_mem); diff --git a/src/beepo.v b/src/beepo.v index fd831f7..a9620e0 100644 --- a/src/beepo.v +++ b/src/beepo.v @@ -6,8 +6,10 @@ module Beepo #( ) ( input i_clk, input i_button1, + input i_resume, output [6:0] o_segments_drive, - output [3:0] o_displays_neg + output [3:0] o_displays_neg, + output o_breakpoint ); // State values localparam IDLE = 0; // Start fetching instruction @@ -38,8 +40,7 @@ module Beepo #( // Registers reg [63:0] r_pc = PC_START; // program counter - reg [63:0] r_pc_latch = PC_START; // address input to ROM - reg [63:0] r_registers [1:NUM_REGS]; // up to 255 modifiable registers + reg [63:0] r_registers [0:NUM_REGS]; // up to 255 modifiable registers reg [7:0] r_instr; // the current instruction reg [7:0] r_arg_regs [0:3]; // register arguments reg [63:0] r_arg_imm = 0; // immediate argument @@ -52,21 +53,22 @@ module Beepo #( reg [3:0] r_arg_current_type = 8; // the type of the current argument reg [5:0] r_arg_bit = 0; // the current lower bit index being fetched for the current argument - reg r_bus_wre = 0; - reg [7:0] r_bus_in = 0; - reg [4:0] r_bus_bytes = 1; // the number of bytes to transfer on the bus - reg [7:0] r_bus_index = 0; // the index of the byte in transfer - reg [7:0] r_bus_reg = 0; // the register currently used in transfer - reg r_bus_start = 0; // pulsed high when the bus should start a transfer - reg r_bus_trans = 0; // trans rights (the bus is executing a transfer instruction) - wire [63:0] w_bus_addr = r_bus_trans ? r_arg_addr : r_pc_latch; - wire [4:0] w_bus_bytes = r_bus_trans ? r_bus_bytes : 1; - wire [7:0] w_bus_fetch; + reg r_mem_wre = 0; + reg r_mem_busy = 0; + reg r_mem_trans = 0; + reg [7:0] r_mem_in = 0; + reg [7:0] r_mem_index = 0; // the index of the byte in transfer + reg [7:0] r_mem_reg = 0; // the register currently used in transfer + wire [63:0] w_mem_addr = r_mem_trans ? r_arg_addr : r_pc; + wire [7:0] w_mem_fetch; + + reg r_breakpoint = 0; + assign o_breakpoint = r_breakpoint; genvar i; generate - for (i = 1; i < NUM_REGS-1; i = i + 1) begin + for (i = 0; i <= NUM_REGS; i = i + 1) begin initial r_registers[i] <= 0; end endgenerate @@ -74,23 +76,24 @@ module Beepo #( always @(posedge i_clk) r_tick <= r_tick + 1; always @(posedge i_clk) begin - if (w_bus_ready == 0) begin - r_bus_start <= 0; - r_bus_trans <= r_bus_trans & ~w_bus_ready; + if (r_breakpoint == 1) begin + r_breakpoint = ~i_resume; + end else if (r_mem_busy == 1) begin + r_mem_busy = 0; end else case (r_state) IDLE: begin - r_pc_latch <= r_pc; - r_pc <= r_pc + 1; - r_bus_start <= 1; r_state <= FETCHI; - r_bus_wre <= 0; + r_mem_wre <= 0; + r_mem_busy <= 1; end FETCHI: begin - r_instr <= w_bus_fetch; + r_instr <= w_mem_fetch; r_arg_index <= 0; r_arg_bit <= 0; + r_mem_trans <= 0; - case (w_bus_fetch) + + case (w_mem_fetch) `TX: r_arg_types_packed = `TX_ARGS; `NOP: r_arg_types_packed = `NOP_ARGS; `ADD8: r_arg_types_packed = `ADD8_ARGS; @@ -107,14 +110,15 @@ module Beepo #( `LI64: r_arg_types_packed = `LI64_ARGS; `LD: r_arg_types_packed = `LD_ARGS; `ST: r_arg_types_packed = `ST_ARGS; + `EBP: r_arg_types_packed = `EBP_ARGS; default: r_arg_types_packed = {ARG_N, ARG_N, ARG_N, ARG_N}; endcase + r_pc = r_pc + 1; + r_mem_busy = 1; + if (r_arg_types_packed[15:12] != ARG_N) begin r_state <= FETCHA; - r_pc_latch <= r_pc; - r_pc <= r_pc + 1; - r_bus_start <= 1; r_arg_bytes <= ARG_SIZES[r_arg_types_packed[15:12]*4+:4]; r_arg_current_type <= r_arg_types_packed[15:12]; @@ -136,19 +140,18 @@ module Beepo #( if (r_arg_current_type == ARG_N) r_state <= IDLE; else begin case (r_arg_current_type) - ARG_R: r_arg_regs[r_arg_index] <= w_bus_fetch; - ARG_O: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch; - ARG_P: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch; - ARG_B: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch; - ARG_H: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch; - ARG_W: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch; - ARG_D: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch; - ARG_A: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch; + ARG_R: r_arg_regs[r_arg_index] <= w_mem_fetch; + ARG_O: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch; + ARG_P: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch; + ARG_B: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch; + ARG_H: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch; + ARG_W: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch; + ARG_D: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch; + ARG_A: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch; endcase - r_pc_latch <= r_pc; r_pc <= r_pc + 1; - r_bus_start <= 1; + r_mem_busy <= 1; r_arg_bytes = r_arg_bytes - 1; r_arg_bit <= r_arg_bit + 8; @@ -172,82 +175,109 @@ module Beepo #( case (r_instr) `TX: r_state <= DONE; `NOP: ; - `ADD8: set_register(r_arg_regs[0], r_registers[r_arg_regs[1]] + r_registers[r_arg_regs[2]][7:0]); - `ADD16: set_register(r_arg_regs[0], r_registers[r_arg_regs[1]] + r_registers[r_arg_regs[2]][15:0]); - `ADD32: set_register(r_arg_regs[0], r_registers[r_arg_regs[1]] + r_registers[r_arg_regs[2]][31:0]); - `ADD64: set_register(r_arg_regs[0], r_registers[r_arg_regs[1]] + r_registers[r_arg_regs[2]][63:0]); - `ADDI8: set_register(r_arg_regs[0], r_registers[r_arg_regs[1]] + r_arg_imm[7:0]); - `ADDI16: set_register(r_arg_regs[0], r_registers[r_arg_regs[1]] + r_arg_imm[15:0]); - `ADDI32: set_register(r_arg_regs[0], r_registers[r_arg_regs[1]] + r_arg_imm[31:0]); - `ADDI64: set_register(r_arg_regs[0], r_registers[r_arg_regs[1]] + r_arg_imm[63:0]); - `LI8: set_register(r_arg_regs[0], r_arg_imm); - `LI16: set_register(r_arg_regs[0], r_arg_imm); - `LI32: set_register(r_arg_regs[0], r_arg_imm); - `LI64: set_register(r_arg_regs[0], r_arg_imm); + `ADD8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_registers [r_arg_regs[2]][0+:8]); + `ADD16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_registers [r_arg_regs[2]][0+:16]); + `ADD32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_registers [r_arg_regs[2]][0+:32]); + `ADD64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_registers [r_arg_regs[2]][0+:64]); + `ADDI8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_arg_imm [0+:8]); + `ADDI16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_arg_imm [0+:16]); + `ADDI32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_arg_imm [0+:32]); + `ADDI64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_arg_imm [0+:64]); + `LI8: set_reg_byte (r_arg_regs[0], r_arg_imm); + `LI16: set_reg_hword (r_arg_regs[0], r_arg_imm); + `LI32: set_reg_word (r_arg_regs[0], r_arg_imm); + `LI64: set_reg_dword (r_arg_regs[0], r_arg_imm); `LD: begin if (r_arg_imm > 0) begin r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]]; - r_bus_index <= 0; - r_bus_reg <= r_arg_regs[0]; + r_mem_index <= 0; + r_mem_reg <= r_arg_regs[0]; + r_mem_busy <= 1; r_state <= MEMR; - r_bus_start <= 1; - r_bus_trans <= 1; - r_bus_bytes <= 1; + r_mem_trans <= 1; end end `ST: begin if (r_arg_imm > 0) begin r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]]; - r_bus_index <= 0; - r_bus_reg <= r_arg_regs[0]; - r_bus_wre <= 1; - r_bus_in <= r_registers[r_arg_regs[0]][0+:8]; + r_mem_index <= 1; + r_mem_reg <= r_arg_regs[0]; + r_mem_wre <= 1; + r_mem_in <= r_registers[r_arg_regs[0]][0+:8]; + r_mem_busy <= 1; r_state <= MEMR; - r_bus_start <= 1; - r_bus_trans <= 1; - r_bus_bytes <= 1; + r_mem_trans <= 1; + end end + `EBP: r_breakpoint = 1; endcase end MEMR: begin case (r_instr) - `LD: set_register(r_arg_regs[0], w_bus_fetch); - `ST: r_bus_in <= r_registers[r_arg_regs[0]][r_bus_index]; + `LD: set_reg_part(r_mem_reg, w_mem_fetch, r_mem_index*8); + `ST: r_mem_in <= r_registers[r_mem_reg][r_mem_index*8+:8]; endcase + r_mem_busy <= 1; + if (r_arg_imm == 1) begin // reached the end of the transfer - r_bus_wre <= 0; + r_mem_wre <= 0; + r_mem_trans <= 0; r_state <= FETCHI; end else begin - if (r_bus_index == 6) begin + r_mem_index = r_mem_index + 1; + + if (r_mem_index == 8) begin // reached the end of this register - r_bus_reg <= r_bus_reg + 1; + r_mem_reg <= r_mem_reg + 1; + r_mem_index <= 0; end r_arg_addr <= r_arg_addr + 1; r_arg_imm <= r_arg_imm - 1; - r_bus_start <= 1; - r_bus_trans <= 1; end end endcase end - task automatic set_register( - input [7:0] being_set, - input [63:0] setting_to - ); - if (being_set != 0) r_registers[being_set] = setting_to; - endtask + always @(r_registers[0]) r_registers[0] <= 0; task automatic set_reg_byte( input [7:0] being_set, - input [2:0] byte_idx, input [7:0] setting_to ); - if (being_set != 0) r_registers[being_set][byte_idx*8+:8] = setting_to; + r_registers[being_set][0+:8] = setting_to; + endtask + + task automatic set_reg_hword( + input [7:0] being_set, + input [15:0] setting_to + ); + r_registers[being_set][0+:16] = setting_to; + endtask + + task automatic set_reg_word( + input [7:0] being_set, + input [31:0] setting_to + ); + r_registers[being_set][0+:32] = setting_to; + endtask + + task automatic set_reg_dword( + input [7:0] being_set, + input [63:0] setting_to + ); + r_registers[being_set][0+:64] = setting_to; + endtask + + task automatic set_reg_part( + input [7:0] being_set, + input [7:0] setting_to, + input [5:0] start_bit + ); + if (start_bit <= 56) r_registers[being_set][start_bit+:8] = setting_to; endtask Multi7 display ( @@ -257,14 +287,14 @@ module Beepo #( .o_displays_neg(o_displays_neg) ); - Bus bus ( - .i_clk(i_clk), - .i_addr(w_bus_addr), - .i_in(r_bus_in), - .i_flags(r_bus_wre), - .i_size(r_bus_bytes), - .i_start(r_bus_start), - .o_ready(w_bus_ready), - .o_out(w_bus_fetch) + spMem mem ( + .clk(i_clk), + .ad(w_mem_addr), + .din(r_mem_in), + .dout(w_mem_fetch), + .oce(0), + .ce(1), + .reset(0), + .wre(r_mem_wre) ); endmodule \ No newline at end of file diff --git a/src/instructions.v b/src/instructions.v index 65852ef..fd75bec 100644 --- a/src/instructions.v +++ b/src/instructions.v @@ -58,4 +58,8 @@ `define ST_ARGS {ARG_R, ARG_R, ARG_A, ARG_H} // Conditional jump -`define JEQ 'h56 \ No newline at end of file +`define JEQ 'h56 + +// Environment traps +`define EBP 'h5D +`define EBP_ARGS {ARG_N, ARG_N, ARG_N, ARG_N} \ No newline at end of file diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..cc7ffa0 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,47 @@ +SLAPPER_DIR = ../slapper +SLAPPER_BUILD = $(SLAPPER_DIR)/target/release/slapper +SLAPPER = ./slapper +HBASM = ./hbasm +SPMEM = spmem.v + +INPUT_FILE = inputs.txt +BUILD_DEPS = ../src/beepo.v ../src/instructions.v ../src/uart_tx.v ../src/multi7.v ../src/bus.v + +%.clean: %/build + rm -r $< + +$(SLAPPER_BUILD): $(SLAPPER_DIR)/src/main.rs + cargo build --manifest-path $(SLAPPER_DIR)/Cargo.toml -r + +$(SLAPPER): $(SLAPPER_BUILD) + cp $< $@ + +%/build: + mkdir -p $@ + +%/build/program.bin: %/program.rhai %/build + $(HBASM) $< > $@ + +%/build/spmem_gen.v: %/build/program.bin $(SLAPPER) + $(SLAPPER) $< $(SPMEM) $@ + +%/build/out: $(INPUT_FILE) %/$(INPUT_FILE) $(BUILD_DEPS) %/top.v %/build/spmem_gen.v + iverilog -o $@ -c $< -c $(word 2, $^) -s tb_beepo + +%/build/dump.vcd: %/build/out + vvp $< + +%.wave: %/build/dump.vcd + gtkwave $< + +%.assemble: %/build/program.bin + echo Done + +%.insert-mem: %/build/spmem_gen.v + echo Done + +%.synth: %/build/out + echo Done + +%.run: %/build/dump.vcd + echo Done \ No newline at end of file diff --git a/tests/adding/Makefile b/tests/adding/Makefile deleted file mode 100644 index d42b002..0000000 --- a/tests/adding/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -SLAPPER_DIR = ../../slapper -SLAPPER_BUILD = ${SLAPPER_DIR}/target/release/slapper -SLAPPER = ../slapper -HBASM = ../hbasm -SPMEM = ../spmem.v - -INPUT_FILE = inputs.txt -BUILD_DEPS = ../../src/beepo.v ../../src/instructions.v adding.v ../../src/uart_tx.v ../../src/multi7.v ../../src/bus.v build/spmem_gen.v - -clean: - rm -r build - -${SLAPPER_BUILD}: - cargo build --manifest-path ${SLAPPER_DIR}/Cargo.toml -r - -${SLAPPER}: ${SLAPPER_BUILD} - cp $< $@ - -build: - mkdir -p $@ - -build/program.bin: program.rhai | build - ${HBASM} $< > $@ - -build/spmem_gen.v: build/program.bin ${SLAPPER} - ${SLAPPER} $< ${SPMEM} $@ - -build/out: ${INPUT_FILE} ${BUILD_DEPS} build/spmem_gen.v - iverilog -o $@ -c $< -s tb_adding - -build/dump.vcd: build/out - vvp $< - -wave: build/dump.vcd - gtkwave build/dump.vcd - -assemble: build/program.bin -insert-mem: build/spmem_gen.v -synth: build/out -run: build/dump.vcd diff --git a/tests/adding/adding.v b/tests/adding/adding.v deleted file mode 100644 index df49d0b..0000000 --- a/tests/adding/adding.v +++ /dev/null @@ -1,38 +0,0 @@ -`include "../../src/beepo.v" -`timescale 100us/10ns - -`define assert(signal, value) \ - if (signal !== value) begin \ - $display("ASSERTION FAILED in %m: signal != value"); \ - $finish; \ - end - -module tb_adding(); - reg clk = 0; - - Beepo #( - .FREQ(1), - .UART_BAUD(1_000_000) - ) bep ( - .i_clk(clk) - ); - - localparam CLK_PERIOD = 1.0; - always #(CLK_PERIOD/2) clk=~clk; - - initial begin - $dumpfile("build/dump.vcd"); - $dumpvars(0, tb_adding, - bep.r_arg_regs[0], bep.r_arg_regs[1], - bep.r_arg_regs[2], bep.r_arg_regs[3], - bep.r_registers[1] - ); - end - - // should probably do more granular tests - initial #10000 begin - `assert(bep.r_registers[1], 64'h2020202040406090); - $display("[ADDING] All tests passed"); - $finish; - end -endmodule \ No newline at end of file diff --git a/tests/adding/inputs.txt b/tests/adding/inputs.txt index 7701394..a7b8229 100644 --- a/tests/adding/inputs.txt +++ b/tests/adding/inputs.txt @@ -1,6 +1,2 @@ -../../src/instructions.v -adding.v -../../src/uart_tx.v -../../src/multi7.v -../../src/bus.v -build/spmem_gen.v +adding/top.v +adding/build/spmem_gen.v diff --git a/tests/adding/program.rhai b/tests/adding/program.rhai index f6f094d..7c9e205 100644 --- a/tests/adding/program.rhai +++ b/tests/adding/program.rhai @@ -2,15 +2,18 @@ li8 (r1, 0x10); li16 (r2, 0x1010); li32 (r3, 0x10101010); li64 (r4, 0x1010101010101010); +ebp(); -add8 (r1, r1, r1); -add16 (r1, r1, r2); -add32 (r1, r1, r3); -add64 (r1, r1, r4); +add8 (r1, r1, r1); // 20 +add16 (r1, r1, r2); // 1030 +add32 (r1, r1, r3); // 10102040 +add64 (r1, r1, r4); // 1010101020203050 +ebp(); -addi8 (r1, r1, 0x10); -addi16 (r1, r1, 0x1010); -addi32 (r1, r1, 0x10101010); -addi64 (r1, r1, 0x1010101010101010); +addi8 (r1, r1, 0x10); // 1010101020203060 +addi16 (r1, r1, 0x1010); // 1010101020204070 +addi32 (r1, r1, 0x10101010); // 1010101030305080 +addi64 (r1, r1, 0x1010101010101010); // 2020202040406090 +ebp(); tx(); \ No newline at end of file diff --git a/tests/adding/top.v b/tests/adding/top.v new file mode 100644 index 0000000..7c6c001 --- /dev/null +++ b/tests/adding/top.v @@ -0,0 +1,73 @@ +`include "../src/beepo.v" +`timescale 100us/10ns + +`define assert(signal, value) \ + if (signal !== value) begin \ + $display("ASSERTION FAILED in %m: signal != value"); \ + $finish; \ + end + +module tb_beepo(); + localparam T_LI = 0; + localparam T_ADD = 1; + localparam T_ADDI = 2; + + reg r_clk = 0; + reg r_resume = 0; + reg [1:0] r_test = 0; + + wire w_breakpoint; + + Beepo #( + .FREQ(1) + ) bep ( + .i_clk(r_clk), + .i_resume(r_resume), + .o_breakpoint(w_breakpoint) + ); + + localparam CLK_PERIOD = 1.0; + always #(CLK_PERIOD/2) r_clk=~r_clk; + + initial begin + $dumpfile("adding/build/dump.vcd"); + $dumpvars(0, tb_beepo, + bep.r_arg_regs[0], bep.r_arg_regs[1], + bep.r_arg_regs[2], bep.r_arg_regs[3], + bep.r_registers[1], bep.r_registers[3] + ); + end + + // should probably do more granular tests + always @(posedge w_breakpoint) begin + $display("BREAK"); + case (r_test) + T_LI: begin + `assert(bep.r_registers[1], 64'h10); + `assert(bep.r_registers[2], 64'h1010); + `assert(bep.r_registers[3], 64'h10101010); + `assert(bep.r_registers[4], 64'h1010101010101010); + $display("[ADDING] LI tests passed"); + end + T_ADD: begin + `assert(bep.r_registers[1], 64'h1010101020203050); + $display("[ADDING] ADD test passed"); + end + T_ADDI: begin + `assert(bep.r_registers[1], 64'h2020202040406090); + $display("[ADDING] ADDI test passed"); + $display("[ADDING] All tests passed"); + $finish; + end + endcase + + r_test <= r_test + 1; + r_resume = 1; + #2 r_resume = 0; + end + + initial #100000 begin + $display("[ADDING] Timeout"); + $finish; + end +endmodule \ No newline at end of file diff --git a/tests/gtkw_filters/arg_types.py b/tests/gtkw_filters/arg_types.py new file mode 100755 index 0000000..e970b88 --- /dev/null +++ b/tests/gtkw_filters/arg_types.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +import sys + +arg_types = { + "0": "R", + "1": "O", + "2": "P", + "3": "B", + "4": "H", + "5": "W", + "6": "D", + "7": "A", + "8": "N" +} + +def main(): + fh_in = sys.stdin + fh_out = sys.stdout + + while True: + # incoming values have newline + l = fh_in.readline() + if not l: + return 0 + + for arg_id in arg_types: + l = l.replace(arg_id, arg_types[arg_id]) + + fh_out.write(l) + fh_out.flush() + +if __name__ == '__main__': + sys.exit(main()) \ No newline at end of file diff --git a/tests/gtkw_filters/r_instr.py b/tests/gtkw_filters/r_instr.py new file mode 100755 index 0000000..69d9a2e --- /dev/null +++ b/tests/gtkw_filters/r_instr.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +import sys + +instructions = { + 0x00: "UN", + 0x01: "TX", + 0x02: "NOP", + 0x03: "ADD8", + 0x04: "ADD16", + 0x05: "ADD32", + 0x06: "ADD64", + 0x2D: "ADDI8", + 0x2E: "ADDI16", + 0x2F: "ADDI32", + 0x30: "ADDI64", + 0x48: "LI8", + 0x49: "LI16", + 0x4A: "LI32", + 0x4B: "LI64", + 0x4D: "LD", + 0x4E: "ST", + 0x5D: "EBP" +} + +def main(): + fh_in = sys.stdin + fh_out = sys.stdout + + while True: + # incoming values have newline + l = fh_in.readline() + if not l: + return 0 + + if "x" in l.lower() or "z" in l.lower(): + fh_out.write(l) + else: + fh_out.write(f"{instructions.get(int(l, 16))}\n") + + fh_out.flush() + +if __name__ == '__main__': + sys.exit(main()) \ No newline at end of file diff --git a/tests/gtkw_filters/state.py b/tests/gtkw_filters/state.py new file mode 100755 index 0000000..39496cc --- /dev/null +++ b/tests/gtkw_filters/state.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import sys + +states = [ + "IDLE", + "FETCHI", + "FETCHA", + "EXEC", + "MEMR", + "DONE" +] + +def main(): + fh_in = sys.stdin + fh_out = sys.stdout + + while True: + # incoming values have newline + l = fh_in.readline() + if not l: + return 0 + + num = int(l, 16) + + if "x" in l.lower() or "z" in l.lower(): + fh_out.write(l) + else: + if num >= len(states): + fh_out.write(l) + else: + fh_out.write(f"{states[num]}\n") + + fh_out.flush() + +if __name__ == '__main__': + sys.exit(main()) \ No newline at end of file diff --git a/tests/inputs.txt b/tests/inputs.txt new file mode 100644 index 0000000..a4e9858 --- /dev/null +++ b/tests/inputs.txt @@ -0,0 +1,4 @@ +../src/instructions.v +../src/uart_tx.v +../src/multi7.v +../src/bus.v diff --git a/tests/mem/inputs.txt b/tests/mem/inputs.txt new file mode 100644 index 0000000..f0121aa --- /dev/null +++ b/tests/mem/inputs.txt @@ -0,0 +1,2 @@ +mem/top.v +mem/build/spmem_gen.v diff --git a/tests/mem/program.rhai b/tests/mem/program.rhai new file mode 100644 index 0000000..648080c --- /dev/null +++ b/tests/mem/program.rhai @@ -0,0 +1,13 @@ +li64 (r4, 0x1020304050607080); +st (r4, r0, 0x400, 8); +ld (r1, r0, 0x400, 8); // 0x1020304050607080 +ebp(); + +ld (r2, r0, 0x404, 4); // 0x0000000010203040 +ebp(); + +li64 (r1, 0x1010202030304040); +li64 (r2, 0x5050606070708080); +st (r1, r0, 0x410, 16); +ld (r3, r0, 0x410, 16); +ebp(); \ No newline at end of file diff --git a/tests/mem/top.v b/tests/mem/top.v new file mode 100644 index 0000000..cfcab0b --- /dev/null +++ b/tests/mem/top.v @@ -0,0 +1,78 @@ +`include "../src/beepo.v" +`timescale 100us/10ns + +`define assert(signal, value) \ + if (signal !== value) begin \ + $display("ASSERTION FAILED in %m: signal != value"); \ + $finish; \ + end + +module tb_beepo(); + localparam T_STLD = 0; + localparam T_STLD_HALF = 1; + localparam T_STLD_DOUBLE = 2; + + localparam T_TESTS = 3; + + reg r_clk = 0; + reg r_resume = 0; + reg [1:0] r_test = 0; + + wire w_breakpoint; + + Beepo #( + .FREQ(1) + ) bep ( + .i_clk(r_clk), + .i_resume(r_resume), + .o_breakpoint(w_breakpoint) + ); + + localparam CLK_PERIOD = 1.0; + always #(CLK_PERIOD/2) r_clk=~r_clk; + + initial begin + $dumpfile("mem/build/dump.vcd"); + $dumpvars(0, tb_beepo, + bep.r_arg_regs[0], bep.r_arg_regs[1], + bep.r_arg_regs[2], bep.r_arg_regs[3], + bep.r_registers[1], bep.r_registers[2], + bep.r_registers[3], bep.r_registers[4] + ); + end + + // should probably do more granular tests + always @(posedge w_breakpoint) begin + $display("BREAK"); + case (r_test) + T_STLD: begin + `assert(bep.r_registers[1], 64'h1020304050607080); + $display("[MEM] ST/LD test passed"); + end + T_STLD_HALF: begin + `assert(bep.r_registers[2], 64'h0000000010203040); + $display("[MEM] ST/LD Half test passed"); + end + T_STLD_DOUBLE: begin + `assert(bep.r_registers[3], 64'h1010202030304040); + `assert(bep.r_registers[4], 64'h5050606070708080); + $display("[MEM] ST/LD Double test passed"); + end + endcase + + r_test = r_test + 1; + + if (r_test == T_TESTS) begin + $display("[MEM] All tests passed"); + $finish; + end + + r_resume = 1; + #2 r_resume = 0; + end + + initial #100000 begin + $display("[ADDING] Timeout"); + $finish; + end +endmodule \ No newline at end of file diff --git a/tests/spmem.v b/tests/spmem.v index d8929e0..d4174e1 100644 --- a/tests/spmem.v +++ b/tests/spmem.v @@ -18,7 +18,11 @@ module spMem( always @(negedge clk) begin // one full clock cycle before being fetched - if (r_ad_prev == ad) r_out <= mem[ad*8+:8]; + if (r_ad_prev == ad) begin + if (wre == 1) mem[ad*8+:8] = din; + r_out <= mem[ad*8+:8]; + + end else r_ad_prev = ad; end endmodule \ No newline at end of file