123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
- use ieee.std_logic_textio.all;
- library std; -- for Printing
- use std.textio.all;
- use work.mem_pkg.all;
- use work.op_pkg.all;
- use work.core_pkg.all;
- use work.tb_util_pkg.all;
- entity tb is
- end entity;
- architecture bench of tb is
- constant CLK_PERIOD : time := 10 ns;
- signal clk : std_logic;
- signal res_n : std_logic := '0';
- signal stop : boolean := false;
- signal start : std_logic := '0';
-
- file input_file : text;
- file output_ref_file : text;
- subtype addr is std_logic_vector(REG_BITS-1 downto 0);
- subtype data is std_logic_vector(DATA_WIDTH-1 downto 0);
-
- type data_arr is array(0 to 400) of MEM_DATA_TYPE;
- type input_t is
- record
- stall : std_logic;
- flush : std_logic;
- pc_in : pc_type;
- op : exec_op_type;
- memop_in : mem_op_type;
- wbop_in : wb_op_type;
- reg_write_mem : reg_write_type;
- reg_write_wr : reg_write_type;
- end record;
- type output_t is
- record
- pc_old_out : pc_type;
- pc_new_out : pc_type;
- aluresult : data_type;
- zero : std_logic;
- wrdata : data_type;
- exec_op : exec_op_type;
- memop_out : mem_op_type;
- wbop_out : wb_op_type;
- end record;
- signal inp : input_t := (
- '0',
- '0',
- (others => '0'),
- EXEC_NOP,
- MEM_NOP,
- WB_NOP,
- (write => '0', reg => (others => '0'), data => (others => '0')),
- (write => '0', reg => (others => '0'), data => (others => '0'))
- );
- signal outp : output_t;
- impure function read_next_input(file f : text) return input_t is
- variable l : line;
- variable result : input_t;
- begin
- l := get_next_valid_line(f);
- result.stall := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.flush := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.pc_in := bin_to_slv(l.all, inp.pc_in'LENGTH);
- l := get_next_valid_line(f);
- result.op.aluop := str_to_alu_op(l.all);
- l := get_next_valid_line(f);
- result.op.alusrc1 := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.op.alusrc2 := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.op.alusrc3 := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.op.rs1 := bin_to_slv(l.all, inp.op.rs1'LENGTH);
- l := get_next_valid_line(f);
- result.op.rs2 := bin_to_slv(l.all, inp.op.rs2'LENGTH);
- l := get_next_valid_line(f);
- result.op.readdata1 := bin_to_slv(l.all, inp.op.readdata1'LENGTH);
- l := get_next_valid_line(f);
- result.op.readdata2 := bin_to_slv(l.all, inp.op.readdata2'LENGTH);
- l := get_next_valid_line(f);
- result.op.imm := bin_to_slv(l.all, inp.op.imm'LENGTH);
- l := get_next_valid_line(f);
- result.memop_in.branch := str_to_branch(l.all);
- l := get_next_valid_line(f);
- result.memop_in.mem.memread := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.memop_in.mem.memwrite := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.memop_in.mem.memtype := str_to_mem_op(l.all);
- l := get_next_valid_line(f);
- result.wbop_in.rd := bin_to_slv(l.all, inp.wbop_in.rd'LENGTH);
- l := get_next_valid_line(f);
- result.wbop_in.write := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.wbop_in.src := str_to_wbs_op(l.all);
- l := get_next_valid_line(f);
- result.reg_write_mem.write := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.reg_write_mem.reg := bin_to_slv(l.all, inp.reg_write_mem.reg'LENGTH);
- l := get_next_valid_line(f);
- result.reg_write_mem.data := bin_to_slv(l.all, inp.reg_write_mem.data'LENGTH);
- l := get_next_valid_line(f);
- result.reg_write_wr.write := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.reg_write_wr.reg := bin_to_slv(l.all, inp.reg_write_wr.reg'LENGTH);
- l := get_next_valid_line(f);
- result.reg_write_wr.data := bin_to_slv(l.all, inp.reg_write_wr.data'LENGTH);
- return result;
- end function;
- impure function read_next_output(file f : text) return output_t is
- variable l : line;
- variable result : output_t;
- begin
- l := get_next_valid_line(f);
- result.pc_old_out := bin_to_slv(l.all, outp.pc_old_out'LENGTH);
- l := get_next_valid_line(f);
- result.pc_new_out := bin_to_slv(l.all, outp.pc_new_out'LENGTH);
- l := get_next_valid_line(f);
- result.aluresult := bin_to_slv(l.all, outp.aluresult'LENGTH);
- l := get_next_valid_line(f);
- result.zero := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.wrdata := bin_to_slv(l.all, outp.wrdata'LENGTH);
- l := get_next_valid_line(f);
- result.exec_op.aluop := str_to_alu_op(l.all);
- l := get_next_valid_line(f);
- result.exec_op.alusrc1 := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.exec_op.alusrc2 := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.exec_op.alusrc3 := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.exec_op.rs1 := bin_to_slv(l.all, outp.exec_op.rs1'LENGTH);
- l := get_next_valid_line(f);
- result.exec_op.rs2 := bin_to_slv(l.all, outp.exec_op.rs2'LENGTH);
- l := get_next_valid_line(f);
- result.exec_op.readdata1 := bin_to_slv(l.all, outp.exec_op.readdata1'LENGTH);
- l := get_next_valid_line(f);
- result.exec_op.readdata2 := bin_to_slv(l.all, outp.exec_op.readdata2'LENGTH);
- l := get_next_valid_line(f);
- result.exec_op.imm := bin_to_slv(l.all, outp.exec_op.imm'LENGTH);
- l := get_next_valid_line(f);
- result.memop_out.branch := str_to_branch(l.all);
- l := get_next_valid_line(f);
- result.memop_out.mem.memread := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.memop_out.mem.memwrite := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.memop_out.mem.memtype := str_to_mem_op(l.all);
- l := get_next_valid_line(f);
- result.wbop_out.rd := bin_to_slv(l.all, outp.wbop_out.rd'LENGTH);
- l := get_next_valid_line(f);
- result.wbop_out.write := str_to_sl(l(1));
- l := get_next_valid_line(f);
- result.wbop_out.src := str_to_wbs_op(l.all);
- return result;
- end function;
- procedure check_output(output_ref : output_t) is
- variable passed : boolean;
- begin
- passed := (outp = output_ref);
- if passed then
- report "PASSED: " & lf
- & "** stall=" & to_string(inp.stall) & lf
- & "** flush=" & to_string(inp.flush) & lf
- & "** pc_in=" & to_string(inp.pc_in) & lf
- & "** op.aluop=" & to_string(inp.op.aluop) & lf
- & "** op.alusrc1=" & to_string(inp.op.alusrc1) & lf
- & "** op.alusrc2=" & to_string(inp.op.alusrc2) & lf
- & "** op.alusrc3=" & to_string(inp.op.alusrc3) & lf
- & "** op.rs1=" & to_string(inp.op.rs1) & lf
- & "** op.rs1=" & to_string(inp.op.rs2) & lf
- & "** op.readdata1=" & to_string(inp.op.readdata1) & lf
- & "** op.readdata2=" & to_string(inp.op.readdata2) & lf
- & "** op.imm=" & to_string(inp.op.imm) & lf
- & "** memop_in.branch=" & to_string(inp.memop_in.branch) & lf
- & "** memop_in.memread=" & to_string(inp.memop_in.mem.memread) & lf
- & "** memop_in.memwrite=" & to_string(inp.memop_in.mem.memwrite) & lf
- & "** memop_in.memtype=" & to_string(inp.memop_in.mem.memtype) & lf
- & "** wbop_in.rd=" & to_string(inp.wbop_in.rd) & lf
- & "** wbop_in.write=" & to_string(inp.wbop_in.write) & lf
- & "** wbop_in.src=" & to_string(inp.wbop_in.src) & lf
- & "** reg_write_mem.write=" & to_string(inp.reg_write_mem.write) & lf
- & "** reg_write_mem.reg=" & to_string(inp.reg_write_mem.reg) & lf
- & "** reg_write_mem.data=" & to_string(inp.reg_write_mem.data) & lf
- & "** reg_write_wr.write=" & to_string(inp.reg_write_wr.write) & lf
- & "** reg_write_wr.reg=" & to_string(inp.reg_write_wr.reg) & lf
- & "** reg_write_wr.data=" & to_string(inp.reg_write_wr.data) & lf
- severity note;
- else
- report "FAILED: " & lf
- & "** stall=" & to_string(inp.stall) & lf
- & "** flush=" & to_string(inp.flush) & lf
- & "** pc_in=" & to_string(inp.pc_in) & lf
- & "** op.aluop=" & to_string(inp.op.aluop) & lf
- & "** op.alusrc1=" & to_string(inp.op.alusrc1) & lf
- & "** op.alusrc2=" & to_string(inp.op.alusrc2) & lf
- & "** op.alusrc3=" & to_string(inp.op.alusrc3) & lf
- & "** op.rs1=" & to_string(inp.op.rs1) & lf
- & "** op.rs1=" & to_string(inp.op.rs2) & lf
- & "** op.readdata1=" & to_string(inp.op.readdata1) & lf
- & "** op.readdata2=" & to_string(inp.op.readdata2) & lf
- & "** op.imm=" & to_string(inp.op.imm) & lf
- & "** memop_in.branch=" & to_string(inp.memop_in.branch) & lf
- & "** memop_in.memread=" & to_string(inp.memop_in.mem.memread) & lf
- & "** memop_in.memwrite=" & to_string(inp.memop_in.mem.memwrite) & lf
- & "** memop_in.memtype=" & to_string(inp.memop_in.mem.memtype) & lf
- & "** wbop_in.rd=" & to_string(inp.wbop_in.rd) & lf
- & "** wbop_in.write=" & to_string(inp.wbop_in.write) & lf
- & "** wbop_in.src=" & to_string(inp.wbop_in.src) & lf
- & "** reg_write_mem.write=" & to_string(inp.reg_write_mem.write) & lf
- & "** reg_write_mem.reg=" & to_string(inp.reg_write_mem.reg) & lf
- & "** reg_write_mem.data=" & to_string(inp.reg_write_mem.data) & lf
- & "** reg_write_wr.write=" & to_string(inp.reg_write_wr.write) & lf
- & "** reg_write_wr.reg=" & to_string(inp.reg_write_wr.reg) & lf
- & "** reg_write_wr.data=" & to_string(inp.reg_write_wr.data) & lf;
- report lf & "** expected: pc_old_out=" & to_string(output_ref.pc_old_out) & ", actual: " & to_string(outp.pc_old_out) & lf
- & "** expected: pc_new_out=" & to_string(output_ref.pc_new_out) & ", actual: " & to_string(outp.pc_new_out) & lf
- & "** expected: aluresult=" & to_string(output_ref.aluresult) & ", actual: " & to_string(outp.aluresult) & lf
- & "** expected: zero=" & to_string(output_ref.zero) & ", actual: " & to_string(outp.zero) & lf
- & "** expected: wrdata=" & to_string(output_ref.wrdata) & ", actual: " & to_string(outp.wrdata) & lf
- & "** expected: exec_op.aluop=" & to_string(output_ref.exec_op.aluop) & ", actual: " & to_string(outp.exec_op.aluop) & lf
- & "** expected: exec_op.alusrc1=" & to_string(output_ref.exec_op.alusrc1) & ", actual: " & to_string(outp.exec_op.alusrc1) & lf
- & "** expected: exec_op.alusrc2=" & to_string(output_ref.exec_op.alusrc2) & ", actual: " & to_string(outp.exec_op.alusrc2) & lf
- & "** expected: exec_op.alusrc3=" & to_string(output_ref.exec_op.alusrc3) & ", actual: " & to_string(outp.exec_op.alusrc3) & lf
- & "** expected: exec_op.rs1=" & to_string(output_ref.exec_op.rs1) & ", actual: " & to_string(outp.exec_op.rs1) & lf
- & "** expected: exec_op.rs2=" & to_string(output_ref.exec_op.rs2) & ", actual: " & to_string(outp.exec_op.rs2) & lf
- & "** expected: exec_op.readdata1=" & to_string(output_ref.exec_op.readdata1) & ", actual: " & to_string(outp.exec_op.readdata1) & lf
- & "** expected: exec_op.readdata2=" & to_string(output_ref.exec_op.readdata2) & ", actual: " & to_string(outp.exec_op.readdata2) & lf
- & "** expected: exec_op.imm=" & to_string(output_ref.exec_op.imm) & ", actual: " & to_string(outp.exec_op.imm) & lf
- & "** expected: memop_out.branch=" & to_string(output_ref.memop_out.branch) & ", actual: " & to_string(outp.memop_out.branch) & lf
- & "** expected: memop_out.mem.memread=" & to_string(output_ref.memop_out.mem.memread) & ", actual: " & to_string(outp.memop_out.mem.memread) & lf
- & "** expected: memop_out.mem.memwrite=" & to_string(output_ref.memop_out.mem.memwrite) & ", actual: " & to_string(outp.memop_out.mem.memwrite) & lf
- & "** expected: memop_out.mem.memtype=" & to_string(output_ref.memop_out.mem.memtype) & ", actual: " & to_string(outp.memop_out.mem.memtype) & lf
- & "** expected: wbop_out.rd=" & to_string(output_ref.wbop_out.rd) & ", actual: " & to_string(outp.wbop_out.rd) & lf
- & "** expected: wbop_out.write=" & to_string(output_ref.wbop_out.write) & ", actual: " & to_string(outp.wbop_out.write) & lf
- & "** expected: wbop_out.src=" & to_string(output_ref.wbop_out.src) & ", actual: " & to_string(outp.wbop_out.src) & lf
- severity error;
- end if;
- end procedure;
- begin
- exec_inst : entity work.exec
- port map (
- clk => clk,
- res_n => res_n,
- stall => inp.stall,
- flush => inp.flush,
- -- from DEC
- op => inp.op,
- pc_in => inp.pc_in,
- -- to MEM
- pc_old_out => outp.pc_old_out,
- pc_new_out => outp.pc_new_out,
- aluresult => outp.aluresult,
- wrdata => outp.wrdata,
- zero => outp.zero,
- memop_in => inp.memop_in,
- memop_out => outp.memop_out,
- wbop_in => inp.wbop_in,
- wbop_out => outp.wbop_out,
- -- FWD
- exec_op => outp.exec_op,
- reg_write_mem => inp.reg_write_mem,
- reg_write_wr => inp.reg_write_wr
- );
- stimulus : process
- variable fstatus: file_open_status;
- begin
-
- res_n <= '0';
- wait until rising_edge(clk);
- res_n <= '1';
-
- file_open(fstatus, input_file, "testdata/input.txt", READ_MODE);
-
- wait until falling_edge(clk);
- wait for CLK_PERIOD/10;
- while not endfile(input_file) loop
- inp <= read_next_input(input_file);
- start <= '1';
- timeout(1, CLK_PERIOD);
- end loop;
-
- wait;
- end process;
- output_checker : process
- variable fstatus: file_open_status;
- variable output_ref : output_t;
- begin
- file_open(fstatus, output_ref_file, "testdata/output.txt", READ_MODE);
- wait until res_n = '1';
- wait until start = '1';
- while not endfile(output_ref_file) loop
- output_ref := read_next_output(output_ref_file);
- wait until falling_edge(clk);
- check_output(output_ref);
- wait until rising_edge(clk);
- end loop;
- stop <= true;
-
- wait;
- end process;
- generate_clk : process
- begin
- clk_generate(clk, CLK_PERIOD, stop);
- wait;
- end process;
- end architecture;
|