diff --git a/.gitignore b/.gitignore index 7552bee..6b3acaa 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ vsim. *.summary *.tcl *.txt # Explicitly add any text files used +*.bin *~ *example* *sopc_* diff --git a/Makefile b/Makefile index e76657a..ac349ed 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ DIR := ./xpacks/.bin SRC_DIR := ./tests/src HEX_DIR := ./tests/hex +BIN_DIR := ./tests/bin OBJ_DIR := ./tests/obj CC := $(DIR)/riscv-none-elf-gcc @@ -9,7 +10,7 @@ OBJDUMP := $(DIR)/riscv-none-elf-objdump OBJCOPY := $(DIR)/riscv-none-elf-objcopy MEM_WORD_LENGTH := 4 -CFLAGS := -O0 -ffunction-sections -Xlinker -g -T./tests/risc.ld -mbig-endian -nostdlib -ffreestanding -fno-pie -fno-stack-protector -Wall -mno-fdiv -march=rv32i -mabi=ilp32 +CFLAGS := -O0 -ffunction-sections -Xlinker -g -T./tests/risc.ld -msmall-data-limit=0 -mlittle-endian -nostdlib -ffreestanding -fno-pie -fno-stack-protector -Wall -mno-fdiv -march=rv32i -mabi=ilp32 SRCS = $(wildcard $(SRC_DIR)/*.c) @@ -19,10 +20,11 @@ PROGS = $(patsubst ${SRC_DIR}/%.c,%,$(SRCS)) all: $(PROGS) $(PROGS): + mkdir -p $(HEX_DIR) $(BIN_DIR) $(OBJ_DIR) $(CC) $(CFLAGS) -o $(OBJ_DIR)/$@.o $(SRC_DIR)/$@.c - $(OBJCOPY) --remove-section=.comment --reverse-bytes=$(MEM_WORD_LENGTH) \ - --verilog-data-width $(MEM_WORD_LENGTH) \ - $(OBJ_DIR)/$@.o -O verilog $(HEX_DIR)/$@.hex + $(OBJCOPY) --remove-section=.comment \ + $(OBJ_DIR)/$@.o -O binary $(BIN_DIR)/$@.bin + $(PYTHON) ./tests/freedom-bin2hex.py --bit-width=32 $(BIN_DIR)/$@.bin $(HEX_DIR)/$@.hex test: python3 -m pytest ./tests diff --git a/src/de10_peripherals.sv b/src/de10_peripherals.sv index c6572d6..e67de2b 100644 --- a/src/de10_peripherals.sv +++ b/src/de10_peripherals.sv @@ -26,6 +26,12 @@ module de10_peripherals( reg_dflop gpio1 [31:0] (.q(qn[0]), .d(idata), .we(we[0]), .clk(clk), .rst(rst)); reg_dflop gpio2 [31:0] (.q(qn[1]), .d(idata), .we(we[1]), .clk(clk), .rst(rst)); + wire [31:0] gpio1_debug; + wire [31:0] gpio2_debug; + + assign gpio1_debug = qn[0]; + assign gpio2_debug = qn[1]; + always @ (*) begin case({periph_addr}) 22'd0: begin diff --git a/src/fetch.sv b/src/fetch.sv index 4b4085b..1a224e3 100644 --- a/src/fetch.sv +++ b/src/fetch.sv @@ -14,7 +14,8 @@ module fetch ( input en_jmp, // Signal that enables jumps input [31:0] imm, // The immediate value from the instruction input stall, // Signal for a full pipeline a stall is occuring - input imem_stall, // Signal for specifcally a stall due to instruction cache + input first_stage_stall, // Signal for which the first stage is stalling + input pc_stall, // Signal for specifcally a stall due to instruction cache input clk, // Clock input rst); // Reset @@ -27,16 +28,16 @@ module fetch ( reg [31:0] next_addr; // Program Counter - pipeline_latch pc [31:0] (.q(curr_addr), .d(next_addr), .stall(stall | imem_stall), .clk(clk), .rst(rst)); + pipeline_latch pc [31:0] (.q(curr_addr), .d(next_addr), .stall(stall | pc_stall | first_stage_stall), .clk(clk), .rst(rst)); // Instruction Latch - pipeline_latch instr_latch [31:0] (.q(oinstr), .d(iinstr), .stall(stall), .clk(clk), .rst(rst)); + pipeline_latch instr_latch [31:0] (.q(oinstr), .d(iinstr), .stall(stall | first_stage_stall), .clk(clk), .rst(rst)); // Latch for the current address plus four bytes wire [31:0] curr_addr_step_conn_latch1; wire [31:0] curr_addr_step_conn_latch2; wire [31:0] curr_addr_step_conn_latch3; - pipeline_latch curr_addr_step_latch1 [31:0] (.q(curr_addr_step_conn_latch1), .d(curr_addr_step), .stall(stall), .clk(clk), .rst(rst)); + pipeline_latch curr_addr_step_latch1 [31:0] (.q(curr_addr_step_conn_latch1), .d(curr_addr_step), .stall(stall | first_stage_stall), .clk(clk), .rst(rst)); pipeline_latch curr_addr_step_latch2 [31:0] (.q(curr_addr_step_conn_latch2), .d(curr_addr_step_conn_latch1), .stall(stall), .clk(clk), .rst(rst)); pipeline_latch curr_addr_step_latch3 [31:0] (.q(curr_addr_step_conn_latch3), .d(curr_addr_step_conn_latch2), .stall(stall), .clk(clk), .rst(rst)); pipeline_latch curr_addr_step_latch4 [31:0] (.q(ocurr_addr_step), .d(curr_addr_step_conn_latch3), .stall(stall), .clk(clk), .rst(rst)); @@ -44,14 +45,14 @@ module fetch ( // Latch for the current address plus the additional value wire [31:0] curr_addr_addval_conn_latch1; wire [31:0] curr_addr_addval_conn_latch2; - pipeline_latch curr_addr_addval_latch1 [31:0] (.q(curr_addr_addval_conn_latch1), .d(curr_addr_addval), .stall(stall), .clk(clk), .rst(rst)); + pipeline_latch curr_addr_addval_latch1 [31:0] (.q(curr_addr_addval_conn_latch1), .d(curr_addr_addval), .stall(stall | first_stage_stall), .clk(clk), .rst(rst)); pipeline_latch curr_addr_addval_latch2 [31:0] (.q(curr_addr_addval_conn_latch2), .d(curr_addr_addval_conn_latch1), .stall(stall), .clk(clk), .rst(rst)); pipeline_latch curr_addr_addval_latch3 [31:0] (.q(ocurr_addr_reljmp), .d(curr_addr_addval_conn_latch2), .stall(stall), .clk(clk), .rst(rst)); // Latch for current wire [31:0] curr_addr_conn_latch1; wire [31:0] curr_addr_out; - pipeline_latch curr_addr_latch1 [31:0] (.q(curr_addr_conn_latch1), .d(curr_addr), .stall(stall), .clk(clk), .rst(rst)); + pipeline_latch curr_addr_latch1 [31:0] (.q(curr_addr_conn_latch1), .d(curr_addr), .stall(stall | first_stage_stall), .clk(clk), .rst(rst)); pipeline_latch curr_addr_latch2 [31:0] (.q(curr_addr_out), .d(curr_addr_conn_latch1), .stall(stall), .clk(clk), .rst(rst)); assign curr_addr_step = curr_addr + 4; diff --git a/src/memory_system.sv b/src/memory_system.sv index fbb3736..ad4d192 100644 --- a/src/memory_system.sv +++ b/src/memory_system.sv @@ -9,10 +9,9 @@ module memory_system #(parameter WORD_SIZE = 32) input [WORD_SIZE-1:0] dmem_data_in, input [WORD_SIZE-1:0] data_out, output reg [WORD_SIZE-1:0] data_in, - output imem_stall, - output dmem_stall, + output pc_stall, output stall, - output first_stage_stall, + output stage_1_stall, output squash, input mem_ready, input jump_taken, @@ -77,12 +76,11 @@ module memory_system #(parameter WORD_SIZE = 32) assign imem_re_en = 1'b1; assign imem_wr_en = 1'b0; - assign full_imem_stall = imem_stall & ~dmem_ext_mem_op & jump_taken; // Full pipeline stall for the icache if there is not a miss in the dcache and jump is going to be taken - assign imem_stall = ~imem_ready & ~control_hazard & imem_valid_addr; - assign dmem_stall = ~dmem_ready & dmem_valid_addr; - assign stall = dmem_stall | full_imem_stall; - assign first_stage_stall = stall | data_hazard | (imem_stall & control_hazard); - + assign pc_stall = (~imem_ready & ~control_hazard & imem_valid_addr) | (control_hazard & imem_cache_miss_stall); // Stall for specifcally the PC counter + assign stage_1_stall = stall | data_hazard; // Stall for specifically the first stage + assign full_dmem_stall = ~dmem_ready & dmem_valid_addr; // will only data mem stall if address if valid and dmem is not ready + assign full_imem_stall = pc_stall & ~dmem_ext_mem_op & jump_taken; // Full pipeline stall for the icache if there is not a miss in the dcache and jump is going to be taken + assign stall = full_dmem_stall | full_imem_stall; // Stall whole pipeline assign squash = data_hazard | control_hazard; pipeline_latch dmem_data_output_latch [31:0] (.q(dmem_data_out), .d(input_dmem_data_out), .stall(stall), .clk(clk), .rst(rst)); diff --git a/src/proc.sv b/src/proc.sv index 45c9876..90aa77b 100644 --- a/src/proc.sv +++ b/src/proc.sv @@ -11,7 +11,7 @@ module proc(input [31:0] data_out, `include "proc_params.h" - // Intruction + // Instruction wire [31:0] instr; // Output from ALU operation wire [31:0] ialu_odata; @@ -35,10 +35,8 @@ module proc(input [31:0] data_out, // Function Value (if there is one) wire [9:0] func; - // Stall from data memory - wire dmem_stall; // Stall from instruction memory - wire imem_stall; + wire pc_stall; // Enables if a jump can be taken wire en_jmp; // Enables unconditional jumps @@ -55,7 +53,7 @@ module proc(input [31:0] data_out, wire [31:0] curr_addr_step; wire [31:0] curr_addr_addval; wire stall; - wire first_stage_stall; + wire stage_1_stall; wire jump_taken; wire control_hazard; wire data_hazard; @@ -77,10 +75,9 @@ module proc(input [31:0] data_out, .dmem_data_in(data_to_cache), .data_out(data_out), .data_in(data_in), - .imem_stall(imem_stall), - .dmem_stall(dmem_stall), + .pc_stall(pc_stall), .stall(stall), - .first_stage_stall(first_stage_stall), + .stage_1_stall(stage_1_stall), .squash(squash), .mem_ready(mem_ready), .jump_taken(jump_taken), @@ -119,8 +116,9 @@ module proc(input [31:0] data_out, .en_branch(en_branch), .en_jmp(en_jmp), .imm(imm_to_addr), - .stall(first_stage_stall), - .imem_stall(imem_stall), + .stall(stall), + .first_stage_stall(stage_1_stall), + .pc_stall(pc_stall), .clk(clk), .rst(rst)); diff --git a/src/reg_file.sv b/src/reg_file.sv index cdef056..82a63cc 100644 --- a/src/reg_file.sv +++ b/src/reg_file.sv @@ -15,6 +15,38 @@ module reg_file(a0, a1, a2, din, reg_wr, d0, d1, clk, rst); output reg [31:0] d1; wire [31:0] qn [`REG_NUM-2:0]; reg [`REG_NUM-2:0] we; + + wire [31:0] x1_reg; + wire [31:0] x2_reg; + wire [31:0] x3_reg; + wire [31:0] x4_reg; + wire [31:0] x5_reg; + wire [31:0] x6_reg; + wire [31:0] x7_reg; + wire [31:0] x8_reg; + wire [31:0] x9_reg; + wire [31:0] x10_reg; + wire [31:0] x11_reg; + wire [31:0] x12_reg; + wire [31:0] x13_reg; + wire [31:0] x14_reg; + wire [31:0] x15_reg; + wire [31:0] x16_reg; + wire [31:0] x17_reg; + wire [31:0] x18_reg; + wire [31:0] x19_reg; + wire [31:0] x20_reg; + wire [31:0] x21_reg; + wire [31:0] x22_reg; + wire [31:0] x23_reg; + wire [31:0] x24_reg; + wire [31:0] x25_reg; + wire [31:0] x26_reg; + wire [31:0] x27_reg; + wire [31:0] x28_reg; + wire [31:0] x29_reg; + wire [31:0] x30_reg; + wire [31:0] x31_reg; // registers x1-x31, x0 is the zero register (always holds zero) reg_dflop x1 [31:0](.q(qn[0]), .d(din), .we(we[0]), .clk(clk), .rst(rst)); @@ -49,6 +81,38 @@ module reg_file(a0, a1, a2, din, reg_wr, d0, d1, clk, rst); reg_dflop x30 [31:0](.q(qn[29]), .d(din), .we(we[29]), .clk(clk), .rst(rst)); reg_dflop x31 [31:0](.q(qn[30]), .d(din), .we(we[30]), .clk(clk), .rst(rst)); + assign x1_reg = qn[0]; + assign x2_reg = qn[1]; + assign x3_reg = qn[2]; + assign x4_reg = qn[3]; + assign x5_reg = qn[4]; + assign x6_reg = qn[5]; + assign x7_reg = qn[6]; + assign x8_reg = qn[7]; + assign x9_reg = qn[8]; + assign x10_reg = qn[9]; + assign x11_reg = qn[10]; + assign x12_reg = qn[11]; + assign x13_reg = qn[12]; + assign x14_reg = qn[13]; + assign x15_reg = qn[14]; + assign x16_reg = qn[15]; + assign x17_reg = qn[16]; + assign x18_reg = qn[17]; + assign x19_reg = qn[18]; + assign x20_reg = qn[19]; + assign x21_reg = qn[20]; + assign x22_reg = qn[21]; + assign x23_reg = qn[22]; + assign x24_reg = qn[23]; + assign x25_reg = qn[24]; + assign x26_reg = qn[25]; + assign x27_reg = qn[26]; + assign x28_reg = qn[27]; + assign x29_reg = qn[28]; + assign x30_reg = qn[29]; + assign x31_reg = qn[30]; + // mux for reg value for d0 always @ (*) begin case({a0}) diff --git a/tests/fix_addr.py b/tests/fix_addr.py deleted file mode 100644 index ad7dcfa..0000000 --- a/tests/fix_addr.py +++ /dev/null @@ -1,49 +0,0 @@ -import argparse -from tempfile import mkstemp -from shutil import move, copymode -from os import fdopen, remove - - -def get_command_line_args(): - parser = argparse.ArgumentParser() - - parser.add_argument( - "-f", "--file_name", type=str, default="" - ) - - parser.add_argument( - "-w", "--data_width", type=int, default=1 - ) - - args = parser.parse_args() - - file_name = getattr(args, "file_name") - data_width = getattr(args, "data_width") - - return file_name, data_width - -def fix_address(line, data_width): - if line[0] == "@": - mem_addr = int(line[1:], 16) - mem_addr = mem_addr // 4 - line = f"@{mem_addr:0{8}X}\n" - return line - -def fix_addresses(file_name, data_width): - #Create temp file - fh, abs_path = mkstemp() - with fdopen(fh,'w') as new_file: - with open(file_name) as old_file: - for line in old_file: - new_file.write(fix_address(line, data_width)) - #Copy the file permissions from the old file to the new file - copymode(file_name, abs_path) - #Remove original file - remove(file_name) - #Move new file - move(abs_path, file_name) - -if __name__ == "__main__": - file_name, data_width = get_command_line_args() - fix_addresses(file_name, data_width) - diff --git a/tests/freedom-bin2hex.py b/tests/freedom-bin2hex.py new file mode 100644 index 0000000..80ed811 --- /dev/null +++ b/tests/freedom-bin2hex.py @@ -0,0 +1,69 @@ +# Copyright 2018 SiFive, Inc +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import sys + +try: +# Python 3 + from itertools import zip_longest +except ImportError: +# Python 2 + from itertools import izip_longest as zip_longest + + +# Copied from https://docs.python.org/3/library/itertools.html +def grouper(iterable, n, fillvalue=None): + """Collect data into fixed-length chunks or blocks""" + # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx + args = [iter(iterable)] * n + return zip_longest(*args, fillvalue=fillvalue) + + +def convert(bit_width, infile, outfile): + byte_width = bit_width // 8 + if sys.version_info >= (3, 0): + for row in grouper(infile.read(), byte_width, fillvalue=0): + # Reverse because in Verilog most-significant bit of vectors is first. + hex_row = ''.join('{:02x}'.format(b) for b in reversed(row)) + outfile.write(hex_row + '\n') + else: + for row in grouper(infile.read(), byte_width, fillvalue='\x00'): + # Reverse because in Verilog most-significant bit of vectors is first. + hex_row = ''.join('{:02x}'.format(ord(b)) for b in reversed(row)) + outfile.write(hex_row + '\n') + + +def main(): + parser = argparse.ArgumentParser( + description='Convert a binary file to a format that can be read in ' + 'verilog via $readmemh(). By default read from stdin ' + 'and write to stdout.' + ) + if sys.version_info >= (3, 0): + parser.add_argument('infile', + nargs='?', + type=argparse.FileType('rb'), + default=sys.stdin.buffer) + else: + parser.add_argument('infile', + nargs='?', + type=argparse.FileType('rb'), + default=sys.stdin) + parser.add_argument('outfile', + nargs='?', + type=argparse.FileType('w'), + default=sys.stdout) + parser.add_argument('--bit-width', '-w', + type=int, + required=True, + help='How many bits per row.') + args = parser.parse_args() + + if args.bit_width % 8 != 0: + sys.exit("Cannot handle non-multiple-of-8 bit width yet.") + convert(args.bit_width, args.infile, args.outfile) + + +if __name__ == '__main__': + main() diff --git a/tests/src/merge_sort.c b/tests/src/merge_sort_test_1.c similarity index 74% rename from tests/src/merge_sort.c rename to tests/src/merge_sort_test_1.c index 2be48ce..7524ad2 100644 --- a/tests/src/merge_sort.c +++ b/tests/src/merge_sort_test_1.c @@ -1,10 +1,12 @@ #include +#define ANSWER (uint32_t*) 0x100 + int merge_sort(uint32_t* numbers, uint32_t* work_array, uint32_t num); -int main(void)__attribute__ ((section (".text.start"))); +int main(void); -uint32_t nums[] = {1, 2, 1, 81}; -uint32_t wk_array[4]; +uint32_t nums[] = {1}; +uint32_t wk_array[1]; uint32_t copy(uint32_t* src, uint32_t* dst, uint32_t size) { for (uint32_t i = 0; i < size; i++) { @@ -40,8 +42,13 @@ int merge_sort(uint32_t* numbers, uint32_t* work_array, uint32_t num) { return 1; } +__attribute__((naked, section (".text.main"))) int main() { - asm volatile ("lui sp, 0x8; addi sp,sp,-16; sw ra,12(sp); sw s0,8(sp)"); - merge_sort(nums, wk_array, 4); - return 0; + asm volatile ("lui sp, 0x8"); + uint32_t* answer_arr = ANSWER; + merge_sort(nums, wk_array, 1); + for (int i = 0; i < 1; i++) { + *(answer_arr+i) = nums[i]; + } + while(1); } diff --git a/tests/src/merge_sort_test_2.c b/tests/src/merge_sort_test_2.c new file mode 100644 index 0000000..848789c --- /dev/null +++ b/tests/src/merge_sort_test_2.c @@ -0,0 +1,54 @@ +#include + +#define ANSWER (uint32_t*) 0x100 + +int merge_sort(uint32_t* numbers, uint32_t* work_array, uint32_t num); +int main(void); + +uint32_t nums[] = {1, 2}; +uint32_t wk_array[2]; + +uint32_t copy(uint32_t* src, uint32_t* dst, uint32_t size) { + for (uint32_t i = 0; i < size; i++) { + dst[i] = src[i]; + } + return 1; +} + +// Biggest to smallest sort +void sort(uint32_t* numbers, uint32_t* work_array, uint32_t num) { + merge_sort(&numbers[0], &work_array[0], num/2); + merge_sort(&numbers[num/2], &work_array[num/2], num/2); + uint32_t i = 0; + uint32_t j = num/2; + for (uint32_t k = 0; k < num; k++) { + if ((i < num/2 && numbers[i] > numbers[j]) || j >= num) { + work_array[k] = numbers[i++]; + } + else { + work_array[k] = numbers[j++]; + } + } + copy(work_array, numbers, num); +} + +int merge_sort(uint32_t* numbers, uint32_t* work_array, uint32_t num) { + if (num == 1) { + return 1; + } + else { + sort(numbers, work_array, num); + } + return 1; +} + +__attribute__((naked, section (".text.main"))) +int main() { + asm volatile ("lui sp, 0x8"); + uint32_t* answer_arr = ANSWER; + merge_sort(nums, wk_array, 2); + for (int i = 0; i < 2; i++) { + *(answer_arr+i) = nums[i]; + } + while(1); +} diff --git a/tests/test_merge_sort_1.py b/tests/test_merge_sort_1.py new file mode 100644 index 0000000..986a1d5 --- /dev/null +++ b/tests/test_merge_sort_1.py @@ -0,0 +1,62 @@ +import os +from os import listdir +from os.path import isfile, join +from pathlib import Path + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, Timer +from cocotb_test.simulator import run + +SRC_FILE_DIR = "./src/" + +@cocotb.test() +async def fib_test(dut): + + expected_vals = [1] + beginning_addr = 0x100 + + # Create a 10ns period clock + clock = Clock(dut.clk, 5, units="us") + cocotb.start_soon(clock.start()) + + # Reset DUT + dut.rst.value = 1 + await RisingEdge(dut.clk) + dut.rst.value = 0 + + for i in range(800): + await RisingEdge(dut.clk) + + received_vals = [] + addr = beginning_addr + idx = 0 + for exp_val in expected_vals: + sram_data = int(dut.sr.ram[(addr >> 2) + idx].value) + received_vals.append(sram_data) + idx += 1 + + print(received_vals) + + for exp_val, rec_val in zip(expected_vals, received_vals): + assert exp_val == rec_val + +def test(): + verilog_sources = [f"{SRC_FILE_DIR}{f}" for f in listdir(SRC_FILE_DIR) if isfile(join(SRC_FILE_DIR, f))] + toplevel = "risc_de10" + module_name = __file__.strip("/").split("/")[-1].removesuffix(".py") + test_file = os.getcwd() + "/tests/hex/merge_sort_test_1.hex" + + run( + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module_name, + includes=[SRC_FILE_DIR], + waves=True, + simulator="icarus", + parameters={"INIT_PROGRAM" : f"\"{test_file}\""}, + sim_build="build/merge_sort_1" + ) + +if __name__ == "__main__": + test() \ No newline at end of file diff --git a/tests/test_merge_sort_2.py b/tests/test_merge_sort_2.py new file mode 100644 index 0000000..df5f0c3 --- /dev/null +++ b/tests/test_merge_sort_2.py @@ -0,0 +1,63 @@ +import os +from os import listdir +from os.path import isfile, join +from pathlib import Path + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge, Timer +from cocotb_test.simulator import run + +SRC_FILE_DIR = "./src/" + +@cocotb.test() +async def fib_test(dut): + + expected_vals = [2,1] + beginning_addr = 0x100 + + # Create a 10ns period clock + clock = Clock(dut.clk, 5, units="us") + cocotb.start_soon(clock.start()) + + # Reset DUT + dut.rst.value = 1 + await RisingEdge(dut.clk) + dut.rst.value = 0 + + # Wait 2400 clock cycles + for i in range(7200): + await RisingEdge(dut.clk) + + received_vals = [] + addr = beginning_addr + idx = 0 + for exp_val in expected_vals: + sram_data = int(dut.sr.ram[(addr >> 2) + idx].value) + received_vals.append(sram_data) + idx += 1 + + print(received_vals) + + for exp_val, rec_val in zip(expected_vals, received_vals): + assert exp_val == rec_val + +def test(): + verilog_sources = [f"{SRC_FILE_DIR}{f}" for f in listdir(SRC_FILE_DIR) if isfile(join(SRC_FILE_DIR, f))] + toplevel = "risc_de10" + module_name = __file__.strip("/").split("/")[-1].removesuffix(".py") + test_file = os.getcwd() + "/tests/hex/merge_sort_test_2.hex" + + run( + verilog_sources=verilog_sources, + toplevel=toplevel, + module=module_name, + includes=[SRC_FILE_DIR], + waves=True, + simulator="icarus", + parameters={"INIT_PROGRAM" : f"\"{test_file}\""}, + sim_build="build/merge_sort_2" + ) + +if __name__ == "__main__": + test() \ No newline at end of file