Files
Archie_MiSTer/sim/stringprocessor.vhd
RobertPeip e272019a2e add reset to cpu
added more regs to reset for other modules
added simulation
some changes to be standard conform, mostly reordering of wire/reg defines
2020-08-08 22:53:38 +08:00

390 lines
12 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use STD.textio.all;
use work.globals.all;
entity estringprocessor is
generic
(
clk_speed : integer := 50000000
);
port
(
ready : in std_logic;
tx_command : out std_logic_vector(31 downto 0);
tx_bytes : out integer range 0 to 4;
tx_enable : out std_logic := '0';
rx_command : in std_logic_vector(31 downto 0);
rx_valid : in std_logic
);
end entity;
architecture arch of estringprocessor is
constant proc_busadr : integer := 28;
constant proc_buswidth : integer := 32;
constant clk_period : time := (1000000000 / clk_speed) * 1 ns;
signal string_command : string(1 to 3);
type t_internal_variables is array(0 to 256) of integer;
signal internal_variables : t_internal_variables := (others => 0);
type r_thread_record is record
id : integer;
waittime : integer;
waitcommand : line;
end record;
type t_thread_buffers is array(0 to 255) of r_thread_record;
procedure find_id
(
variable t_buf : inout t_thread_buffers;
variable id : in integer;
variable slot : out integer
) is
begin
for i in 0 to 255 loop
if (t_buf(i).id = id) then
slot := i;
exit;
elsif (t_buf(i).id = -1) then
t_buf(i).id := id;
slot := i;
exit;
end if;
end loop;
end procedure;
begin
process
file infile : text;
file outfile : text;
variable f_status : FILE_OPEN_STATUS;
variable newdat : LINE;
variable endfound : boolean;
variable buf : LINE;
variable run : boolean := true;
variable line_out : line;
variable debugline_out : line;
variable command : string(1 to 3);
variable dev_null_str3 : string (1 to 3);
variable dev_null_str6 : string (1 to 6);
variable OK : boolean := FALSE;
variable para_int1 : integer;
variable para_int2 : integer;
variable para_int3 : integer;
variable para_int4 : integer;
variable address : integer;
variable data : integer;
variable count : integer;
variable thread_buffers : t_thread_buffers := (others => (-1, 0, null));
variable freerun : boolean := false;
begin
file_open(f_status, outfile, "input.txt", write_mode);
file_close(outfile);
file_open(f_status, outfile, "output.txt", write_mode);
file_close(outfile);
file_open(f_status, infile, "input.txt", read_mode);
wait for 1000 ns;
while (run) loop
if not endfile(infile) then
endfound := false;
buf := null;
while (endfound = false) loop
if not endfile(infile) then
readline(infile,newdat);
for i in 1 to newdat'length loop
write(buf, newdat(i to i));
if (newdat(i to i) = "&") then
endfound := true;
end if;
end loop;
end if;
end loop;
command := buf(1 to 3);
string_command <= command;
line_out := null;
buf(buf'length) := ' ';
write(line_out, buf(1 to buf'length));
write(line_out, string'("# "));
if (command(1 to 3) = String'("set")) then
-- command
Read(buf, dev_null_str6);
-- command nr
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- process id
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- target for reading
Read(buf, para_int2, OK);
Read(buf, dev_null_str3);
-- count
Read(buf, count, OK);
Read(buf, dev_null_str3);
-- address in target space
Read(buf, address, OK);
Read(buf, dev_null_str3);
-- write address
if (ready = '0') then
wait until ready = '1';
end if;
tx_command <= "0000" & std_logic_vector(to_unsigned(address,proc_busadr));
if (count > 1) then
tx_command(31) <= '1';
end if;
tx_bytes <= 4;
tx_enable <= '1';
wait for clk_period*2;
tx_enable <= '0';
-- write block size
if (count > 1) then
if (ready = '0') then
wait until ready = '1';
end if;
tx_command <= std_logic_vector(to_unsigned(count - 1,32));
tx_bytes <= 4;
tx_enable <= '1';
wait for clk_period*2;
tx_enable <= '0';
end if;
for i in 1 to count loop
-- value to write
Read(buf, data, OK);
if (i < count) then
Read(buf, dev_null_str3);
end if;
-- write data
if (ready = '0') then
wait until ready = '1';
end if;
tx_command <= std_logic_vector(to_signed(data,proc_buswidth));
tx_bytes <= 4;
tx_enable <= '1';
wait for clk_period*2;
tx_enable <= '0';
wait for 20*clk_period; -- this is required, because there is no answer for write commands
address := address + 1;
end loop;
write(line_out, string'("&"));
file_open(f_status, outfile, "output.txt", append_mode);
writeline(outfile, line_out);
file_close(outfile);
end if;
if (command(1 to 3) = String'("get")) then
-- command
Read(buf, dev_null_str6);
-- command nr
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- process id
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- target for reading
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- count
Read(buf, count, OK);
Read(buf, dev_null_str3);
-- address in target space
Read(buf, address, OK);
-- write address
if (ready = '0') then
wait until ready = '1';
end if;
tx_command <= "0100" & std_logic_vector(to_unsigned(address,proc_busadr));
if (count > 1) then
tx_command(31) <= '1';
end if;
tx_bytes <= 4;
tx_enable <= '1';
wait for clk_period*2;
tx_enable <= '0';
-- write block size
if (count > 1) then
if (ready = '0') then
wait until ready = '1';
end if;
tx_command <= std_logic_vector(to_unsigned(count - 1,32));
tx_bytes <= 4;
tx_enable <= '1';
wait for clk_period*2;
tx_enable <= '0';
end if;
for i in 1 to count loop
if (rx_valid = '0') then
wait until rx_valid = '1';
end if;
data := to_integer(signed(rx_command(31 downto 0)));
wait until rx_valid = '0';
write(line_out, data);
write(line_out, string'("#"));
address := address + 1;
end loop;
write(line_out, string'("&"));
file_open(f_status, outfile, "output.txt", append_mode);
writeline(outfile, line_out);
file_close(outfile);
end if;
if (command(1 to 3) = String'("fil")) then
-- command
Read(buf, dev_null_str6);
-- command nr
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- process id
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- endianess
Read(buf, para_int2, OK);
Read(buf, dev_null_str3);
-- address in target space
Read(buf, address, OK);
Read(buf, dev_null_str3);
COMMAND_FILE_NAME <= (others => ' ');
COMMAND_FILE_NAME(1 to buf'length) <= buf(1 to buf'length);
COMMAND_FILE_NAMELEN <= buf'length;
COMMAND_FILE_TARGET <= address;
if (para_int2 = 1) then
COMMAND_FILE_ENDIAN <= '1';
else
COMMAND_FILE_ENDIAN <= '0';
end if;
COMMAND_FILE_START <= '1';
wait until COMMAND_FILE_ACK = '1';
COMMAND_FILE_START <= '0';
wait for 20 ns;
write(line_out, string'("&"));
file_open(f_status, outfile, "output.txt", append_mode);
writeline(outfile, line_out);
file_close(outfile);
end if;
if (command(1 to 3) = String'("brk")) then
run := false;
end if;
if (command(1 to 3) = String'("wtn")) then
-- command
Read(buf, dev_null_str6);
-- command nr
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- process id
Read(buf, para_int1, OK);
Read(buf, dev_null_str3);
-- time to wait
Read(buf, para_int2, OK);
write(line_out, string'("&"));
if (para_int2 = -1) then
freerun := true;
find_id(thread_buffers, para_int1, para_int3);
thread_buffers(para_int3).waittime := 2;
thread_buffers(para_int3).waitcommand := line_out;
else
find_id(thread_buffers, para_int1, para_int3);
thread_buffers(para_int3).waittime := para_int2;
thread_buffers(para_int3).waitcommand := line_out;
end if;
end if;
wait for 1 ps;
end if;
OK := false;
for i in 0 to 255 loop
if (thread_buffers(i).id /= -1) then
if (thread_buffers(i).waittime = 1) then
file_open(f_status, outfile, "output.txt", append_mode);
writeline(outfile, thread_buffers(i).waitcommand);
file_close(outfile);
end if;
if (thread_buffers(i).waittime > 0) then
OK := true;
thread_buffers(i).waittime := thread_buffers(i).waittime - 1;
end if;
end if;
end loop;
if (OK = true or freerun = true) then
wait for 1 ns;
end if;
end loop;
file_close(infile);
wait;
end process;
end architecture;