memory !!
This commit is contained in:
parent
51ecf47862
commit
2e4cd0240c
|
@ -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);
|
||||
|
||||
|
|
198
src/beepo.v
198
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
|
|
@ -58,4 +58,8 @@
|
|||
`define ST_ARGS {ARG_R, ARG_R, ARG_A, ARG_H}
|
||||
|
||||
// Conditional jump
|
||||
`define JEQ 'h56
|
||||
`define JEQ 'h56
|
||||
|
||||
// Environment traps
|
||||
`define EBP 'h5D
|
||||
`define EBP_ARGS {ARG_N, ARG_N, ARG_N, ARG_N}
|
47
tests/Makefile
Normal file
47
tests/Makefile
Normal file
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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();
|
73
tests/adding/top.v
Normal file
73
tests/adding/top.v
Normal file
|
@ -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
|
33
tests/gtkw_filters/arg_types.py
Executable file
33
tests/gtkw_filters/arg_types.py
Executable file
|
@ -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())
|
43
tests/gtkw_filters/r_instr.py
Executable file
43
tests/gtkw_filters/r_instr.py
Executable file
|
@ -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())
|
36
tests/gtkw_filters/state.py
Executable file
36
tests/gtkw_filters/state.py
Executable file
|
@ -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())
|
4
tests/inputs.txt
Normal file
4
tests/inputs.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
../src/instructions.v
|
||||
../src/uart_tx.v
|
||||
../src/multi7.v
|
||||
../src/bus.v
|
2
tests/mem/inputs.txt
Normal file
2
tests/mem/inputs.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
mem/top.v
|
||||
mem/build/spmem_gen.v
|
13
tests/mem/program.rhai
Normal file
13
tests/mem/program.rhai
Normal file
|
@ -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();
|
78
tests/mem/top.v
Normal file
78
tests/mem/top.v
Normal file
|
@ -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
|
|
@ -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
|
Loading…
Reference in a new issue