harv/sim/sim_from_dump.vhd
2022-03-10 19:12:20 +01:00

238 lines
7.7 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
use ieee.std_logic_textio.all;
library work;
use work.harv_pkg.harv;
entity sim_from_dump is
end entity;
architecture arch of sim_from_dump is
constant period : time := 20 ns;
signal rstn : std_logic := '0';
signal clk : std_logic := '0';
signal start : std_logic := '0';
constant INST_BASE_ADDR : integer := 0;
constant INST_SIZE : integer := 4096;
constant DATA_BASE_ADDR : integer := 8192;
constant DATA_SIZE : integer := 4096;
type mem_t is array(natural range <>) of std_logic_vector(7 downto 0);
signal inst_mem : mem_t(INST_SIZE + INST_BASE_ADDR - 1 downto INST_BASE_ADDR);
signal data_mem : mem_t(DATA_SIZE + DATA_BASE_ADDR - 1 downto DATA_BASE_ADDR);
-- instruction memory interface
signal imem_instr_i : std_logic_vector(31 downto 0);
signal imem_pc_o : std_logic_vector(31 downto 0);
signal imem_req_o : std_logic;
signal imem_gnt_i : std_logic;
-- data memory interface
signal dmem_rdata_i : std_logic_vector(31 downto 0);
signal dmem_req_o : std_logic;
signal dmem_wren_o : std_logic;
signal dmem_gnt_i : std_logic;
signal dmem_err_i : std_logic;
signal dmem_ben_o : std_logic_vector(1 downto 0);
signal dmem_usgn_o : std_logic;
signal dmem_wdata_o : std_logic_vector(31 downto 0);
signal dmem_addr_o : std_logic_vector(31 downto 0);
constant INST_DUMP_FILE_PATH : string := "../../../../../src/test_text.dump";
constant DATA_DUMP_FILE_PATH : string := "../../../../../src/test_data.dump";
procedure load_memory (
constant FILE_PATH : in string;
constant BASE_ADDR : in integer;
signal mem : out mem_t
) is
file file_v : text;
variable line_v : line;
variable addr_v : integer;
variable byte_v : std_logic_vector(7 downto 0);
variable error_v : boolean;
begin
-- read data dump file
file_open(file_v, FILE_PATH, READ_MODE);
-- initialize instructions address counter
addr_v := BASE_ADDR;
-- iterate through all lines in the file
while not endfile(file_v) loop
-- read line from file_v
readline(file_v, line_v);
-- ensure that the line is not empty
if line_v'length > 0 then
-- iterate in each byte of the data
for i in 3 downto 0 loop
-- read hex byte from line
hread(line_v, byte_v, error_v);
-- assert if the hread had an error
assert (error_v) report "Text I/O read error" severity FAILURE;
-- write byte to memory
mem(addr_v + i) <= byte_v;
end loop;
-- increment address
addr_v := addr_v + 4;
end if;
end loop;
file_close(file_v);
end procedure;
begin
rstn <= '1' after period;
clk <= not clk after period/2;
start <= '1' after period * 2; -- set start signal after 2 clock cycles
harv_u : harv
generic map (
PROGRAM_START_ADDR => x"00000000",
TRAP_HANDLER_ADDR => x"00000000",
TMR_CONTROL => FALSE,
TMR_ALU => FALSE,
HAMMING_REGFILE => FALSE,
HAMMING_PC => FALSE
)
port map (
rstn_i => rstn,
clk_i => clk,
start_i => start,
poweron_rstn_i => rstn,
wdt_rstn_i => '1',
imem_instr_i => imem_instr_i,
imem_pc_o => imem_pc_o,
imem_req_o => imem_req_o,
imem_gnt_i => imem_gnt_i,
imem_err_i => '0',
hard_dmem_o => open,
dmem_rdata_i => dmem_rdata_i,
dmem_req_o => dmem_req_o,
dmem_wren_o => dmem_wren_o,
dmem_gnt_i => dmem_gnt_i,
dmem_err_i => dmem_err_i,
dmem_sbu_i => '0',
dmem_dbu_i => '0',
dmem_ben_o => dmem_ben_o,
dmem_usgn_o => dmem_usgn_o,
dmem_wdata_o => dmem_wdata_o,
dmem_addr_o => dmem_addr_o
);
-- INSTRUCTION MEMORY ACCESS
process
variable addr_v : integer;
begin
-- load instruction memory
report "Loading instruction memory from " & INST_DUMP_FILE_PATH severity NOTE;
load_memory(INST_DUMP_FILE_PATH, INST_BASE_ADDR, inst_mem);
-- infinite loop to provide instruction memory access
loop
-- disable grant signal
imem_gnt_i <= '0';
imem_instr_i <= (others => 'X');
-- wait memory request
wait until rising_edge(clk) and imem_req_o = '1';
-- wait 1 cycle to give response
wait for period;
-- grant response
imem_gnt_i <= '1';
addr_v := to_integer(unsigned(imem_pc_o));
imem_instr_i <= inst_mem(addr_v+3) &
inst_mem(addr_v+2) &
inst_mem(addr_v+1) &
inst_mem(addr_v);
-- grant response for 1 cycle
wait for period;
end loop;
end process;
-- DATA MEMORY ACCESS
process
variable addr_v : integer;
begin
-- if there is no data dump file
if DATA_DUMP_FILE_PATH = "" then
report "No data memory to load" severity NOTE;
else -- if data dump file is defined
-- load data memory from file
report "Loading data memory from " & DATA_DUMP_FILE_PATH severity NOTE;
load_memory (DATA_DUMP_FILE_PATH, DATA_BASE_ADDR, data_mem);
end if;
-- infinite loop to provide data memory access
loop
-- disable grant signal
dmem_gnt_i <= '0';
dmem_rdata_i <= (others => 'X');
dmem_err_i <= '0';
-- wait memory request
wait until rising_edge(clk) and dmem_req_o = '1';
-- wait 1 cycle to give response
wait for period;
-- convert address to integer
addr_v := to_integer(unsigned(dmem_addr_o));
-- check if range is ok
if addr_v < DATA_BASE_ADDR or addr_v >= (DATA_BASE_ADDR + DATA_SIZE) then
dmem_err_i <= '1';
else
-- grant response
dmem_gnt_i <= '1';
-- if it will perform a write
if dmem_wren_o = '1' then
-- write the first byte
data_mem(addr_v) <= dmem_wdata_o(7 downto 0);
-- write the second byte for half-word and word
if dmem_ben_o(0) = '1' then
data_mem(addr_v+1) <= dmem_wdata_o(15 downto 8);
end if;
-- write the upper 16 bits, only for full word
if dmem_ben_o(1) = '1' then
data_mem(addr_v+2) <= dmem_wdata_o(23 downto 16);
data_mem(addr_v+3) <= dmem_wdata_o(31 downto 24);
end if;
-- read data memory
else
-- case between all acess possibilities
case dmem_ben_o is
-- byte read with and without sign-extension
when "00" =>
if dmem_usgn_o = '1' then
dmem_rdata_i <= x"000000" & data_mem(addr_v);
else
dmem_rdata_i <= (31 downto 8 => data_mem(addr_v)(7)) & data_mem(addr_v);
end if;
-- half-word read with and without sign-extension
when "01" =>
if dmem_usgn_o = '1' then
dmem_rdata_i <= (
31 downto 16 => data_mem(addr_v + 1)(7),
15 downto 8 => data_mem(addr_v + 1),
7 downto 0 => data_mem(addr_v)
);
else
dmem_rdata_i <= x"000000" & data_mem(addr_v);
end if;
-- word read - concatanate bytes
when "11" =>
dmem_rdata_i <= data_mem(addr_v + 3) &
data_mem(addr_v + 2) &
data_mem(addr_v + 1) &
data_mem(addr_v);
when others =>
report "Wrong parameters to data memory" severity ERROR;
end case;
report to_hstring(dmem_addr_o) & ": " & to_hstring(dmem_rdata_i);
end if;
end if;
-- response for 1 cycle
wait for period;
end loop;
end process;
end architecture;