[英]type in vhdl corresponds to c-language: “uint32_t” or “unsigned long”
[英]need VHDL equivalent of c-language “strtok” and “strcmp” functions that can operator on vhdl string type
我正在尝试为vhdl testbench写一个激励阅读器。 它需要读取文本文件中的文本命令和两个由空格分隔的文本操作数。
entity tb is
end entity;
architecture sim is tb of
begin
process
variable L : line;
file STIMFILE : test is in "stim.txt";
variable s1 : string;
variable s2 : string;
variable s3 : string;
begin
while not endfile(STIMFILE) loop
readline(STIMFILE, L);
s1 := strtok(L, "\n\t ");
s2 := strtok(0, "\n\t ");
s3 := strtok(0, "\n\t ");
if (strcmp(s1, "ADDXYZ") = '1') then
report "ADDXYZ " & s2 & " " & s3;
end if;
end loop;
end process;
end architecture;
我将如何在VHDL中执行此操作?
到目前为止,我有一个strcmp函数:
FUNCTION strcmp(s1: STRING; s2: STRING) --string compare
RETURN BOOLEAN IS
BEGIN
IF(s1'LENGTH /= s2'LENGTH) THEN
RETURN FALSE;
ELSE
FOR i IN s1'RANGE LOOP
IF(s1(i) /= s2(i)) THEN
RETURN FALSE;
END IF;
END LOOP;
RETURN TRUE;
END IF;
END; --function strcmp
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
package pkg_fancy_strings is
-- Max Line length to tokenize
constant STRTOK_MAX : natural := 200;
procedure line2string(L: inout line; S: out string);
function is_space (c:character) return boolean;
function is_nul (c:character) return boolean;
-- structure to maintain state between strtok calls
type strtok_t is
record
str : string(1 to STRTOK_MAX); --input string
pos : natural; --input string iterator position
more : boolean; --call strtok_next until more equals false stop
tok : string(1 to STRTOK_MAX); --token string value
len : natural; --token string length
valid : boolean; --token string valid
error : natural; --token string had an error, ex: truncation
end record;
-- return string of length n padded with nul if less than n originally
function strpad(n: natural; x: string; rm_comment: boolean) return string;
-- Initialize strtok structure with unparsed string
function strtok_init(s : string) return strtok_t;
-- tokenize string in strtok buffer
function strtok_next(t: strtok_t) return strtok_t;
-- compare strings
function strcmpi(s1: string; s2: string) return boolean;
-- convert string into integer
function str2integer(s: string) return integer;
end package;
package body pkg_fancy_strings is
function is_space(c:character) return boolean is
begin
if (c = ' ') then
return true;
end if;
if (c <= character'val(13)) then
return true;
end if;
return false;
end function;
function is_nul(c:character) return boolean is
begin
if (c = character'val(0)) then
return true;
end if;
return false;
end function;
procedure line2string(L: inout line; S: out string) is
variable good :boolean;
variable ch :character;
variable str :string(1 to STRTOK_MAX);
variable i :integer := 1;
variable len :integer := 0;
begin
-- Zero Line Buffer
for i in 1 to str'length loop
str(i) := character'val(0);
end loop;
len := 1;
loop
read(L, ch, good);
if (good = false) then
exit;
end if;
str(len) := ch;
len := len + 1;
if (is_nul(ch)) then
exit;
end if;
if (len > str'length-1) then
exit;
end if;
end loop;
S := str;
end procedure;
-- return string of length n padded with nul if less than n originally
function strpad(n: natural; x: string; rm_comment: boolean)
return string is
variable r: string(1 to n);
variable stop: natural;
begin
for i in 1 to n loop
r(i) := character'val(0);
end loop;
stop := x'length;
if (stop >= n) then
stop := n-1;
end if;
for i in 1 to stop loop
-- ignore everything on line after '#'
if (x(i) = '#') then
exit;
end if;
r(i) := x(i);
end loop;
return r;
end function;
-- Initialize strtok structure with unparsed string
function strtok_init(
s : string
) return strtok_t is
variable t :strtok_t;
variable i :natural;
variable ch :character;
begin
t.str := strpad(STRTOK_MAX, s, true);
t.pos := 1;
t.more := true;
t.valid := false; --tok string not valid yet
t.error := 0;
return t;
end function;
-- tokenize string in strtok buffer
function strtok_next(
t: strtok_t
) return strtok_t is
variable ch :character := character'val(0);
variable i :natural := 0;
variable r :strtok_t;
begin
r := t;
-- Zero t.tok
r.len := 0;
for i in 1 to r.tok'length loop
r.tok(i) := character'val(0);
end loop;
-- Eat Spaces
loop
if (r.pos > r.str'length-1) then
r.valid := false;
r.more := false;
return r;
end if;
ch := r.str(r.pos);
if (is_nul(ch) = true) then
r.valid := false;
r.more := false;
return r;
end if;
if (is_space(ch) = false) then
exit;
else
r.pos := r.pos + 1;
end if;
end loop;
-- Save Token
i := 1;
loop
if (i > r.tok'length-1) then
r.valid := true;
r.more := true;
r.error := 1;
return r;
end if;
if ((r.pos > r.str'length) or is_nul(r.str(r.pos))) then
r.valid := (r.tok'length /= 0);
r.more := false;
r.error := 0;
return r;
end if;
ch := r.str(r.pos);
if (is_space(ch)) then
r.valid := true;
r.more := true;
r.error := 0;
return r;
else
r.tok(i) := ch;
r.len := i;
i := i + 1;
r.pos := r.pos + 1;
end if;
end loop;
-- shouldn't get here
r.error := 2;
r.valid := false;
r.more := false;
return r;
end function;
--string compare
function strcmpi(s1: string; s2: string)
return boolean is
variable max: natural := 0;
variable end_s1:boolean;
variable end_s2:boolean;
variable nul_s1:boolean;
variable nul_s2:boolean;
begin
if (s1'length >= s2'length) then max := s1'length; else max := s2'length; end if;
for i in 1 to max loop
end_s1 := (i > s1'length);
end_s2 := (i > s2'length);
if (end_s1 and end_s2) then return true; end if;
if (end_s1) then
nul_s2 := (s2(i) = character'val(0));
if (nul_s2) then return true; end if;
end if;
if (end_s2) then
nul_s1 := (s1(i) = character'val(0));
if (nul_s1) then return true; end if;
end if;
nul_s1 := (s1(i) = character'val(0));
nul_s2 := (s2(i) = character'val(0));
if (nul_s1 and nul_s2) then return true; end if;
if(s1(i) /= s2(i)) then
return false;
end if;
end loop;
return true;
end function;
-- read next whitespace delimited string
-- return string is terminated with null's
procedure read_string(L: inout Line; s: out string(1 to 80);
good: out boolean) is
variable c :character;
variable r :string(1 to 80);
variable i :natural;
begin
r := (others => character'val(0));
s := (others => character'val(0));
-- Skip WhiteSpace
loop
read(L, c, good);
report "c:" & character'image(c);
if (good = False) then
good := False;
return;
elsif ((c = ' ') or (c <= character'val(13)) ) then
next;
end if;
exit;
end loop;
-- Read Until Non-Whitespace
i := 1;
r(i) := c;
i := i+1;
loop
read(L, c, good);
if (good = false) then
s := r;
good := True;
return;
elsif ((c = ' ') or (c <= character'val(13)) ) then
s := r;
good := True;
return;
else
r(i) := c;
i := i + 1;
end if;
end loop;
end procedure;
end package body;
-- EXAMPLE OF FANCY STRINGS USAGE:
--
-- use work.pkg_fancy_strings.all;
--
-- entity tb is
-- end entity;
--
-- architecture rtl of tb is
-- begin
-- process
-- file stim_in :text open read_mode is "testcase1.txt";
-- variable L :line;
-- variable sbuf :string(1 to STRTOK_MAX);
-- variable slen :natural;
-- variable t :strtok_t;
-- begin
-- t := strtok_init(" mary had a little #lamb");
-- while(t.more) loop
-- t := strtok_next(t);
-- if (t.valid) then
-- report ">>" & t.tok(1 to t.len) & "<<";
-- end if;
-- end loop;
--
-- report "done." severity failure;
-- end process;
-- end architecture;
--
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.