需要与c语言等效的VHDL“;斯特托克“;及;strcmp“;可以在vhdl字符串类型上使用运算符的函数
我正在尝试为vhdl测试台编写一个刺激读取器。它需要读取文本文件中由空格分隔的一个文本命令和两个文本操作数需要与c语言等效的VHDL“;斯特托克“;及;strcmp“;可以在vhdl字符串类型上使用运算符的函数,vhdl,Vhdl,我正在尝试为vhdl测试台编写一个刺激读取器。它需要读取文本文件中由空格分隔的一个文本命令和两个文本操作数 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
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
ieee库;
使用ieee.std_logic_1164.all;
使用std.textio.all;
包裹包装花式字符串为
--标记化的最大行长度
常数STRTOK_MAX:自然值=200;
过程行2字符串(L:inout行;S:out字符串);
函数是_空间(c:字符)返回布尔值;
函数为_num(c:字符)返回布尔值;
--结构来维护strtok调用之间的状态
strtok_t类型为
记录
str:字符串(1到STRTOK_MAX)--输入字符串
pos:自然--输入字符串迭代器位置
更多:布尔--下一步调用strtok_,直到更多等于错误停止
tok:字符串(1到STRTOK_MAX)--令牌字符串值
len:自然的--令牌字符串长度
有效值:布尔值--令牌字符串有效
误差:自然--令牌字符串出错,例如:截断
结束记录;
--返回长度为n的字符串,如果最初小于n,则用nul填充
函数strpad(n:natural;x:string;rm_comment:boolean)返回字符串;
--使用未解析的字符串初始化strtok结构
函数strtok_init(s:string)返回strtok_t;
--strtok缓冲区中的标记化字符串
函数strtok_next(t:strtok_t)返回strtok_t;
--比较字符串
函数strcmpi(s1:string;s2:string)返回布尔值;
--将字符串转换为整数
函数str2integer(s:string)返回整数;
端包装;
包装体包装花式字符串为
函数is_空间(c:字符)返回布尔值is
开始
如果(c=''),那么
返回true;
如果结束;
如果(c str'length-1)那么
出口
如果结束;
端环;
S:=str;
结束程序;
--返回长度为n的字符串,如果最初小于n,则用nul填充
函数strpad(n:natural;x:string;rm\u注释:boolean)
返回字符串为
变量r:字符串(1到n);
可变停止:自然;
开始
对于1到n循环中的i
r(i):=字符值(0);
端环;
停止:=x'长度;
如果(停止>=n),则
停止:=n-1;
如果结束;
对于1中的i,停止循环
--忽略“#”之后的所有在线内容
如果(x(i)='#'),那么
出口
如果结束;
r(i):=x(i);
端环;
返回r;
末端功能;
--使用未解析的字符串初始化strtok结构
函数strtok_init(
s:字符串
)返回strtok\u t is
变量t:strtok_t;
变量一:自然变量;
变量ch:字符;
开始
t、 str:=strpad(STRTOK_MAX,s,true);
t、 位置:=1;
t、 更多:=正确;
t、 有效:=假--tok字符串尚未生效
t、 误差:=0;
返回t;
末端功能;
--strtok缓冲区中的标记化字符串
函数strtok_next(
t:strtok\u t
)返回strtok\u t is
变量ch:character:=character'val(0);
变量i:自然:=0;
变量r:strtok_t;
开始
r:=t;
--零t.tok
r、 len:=0;
对于1到r.tok'长度循环中的i
r、 tok(i):=字符'val(0);
端环;
--就餐空间
环
如果(r.pos>r.str'length-1),则
r、 有效:=假;
r、 更多:=假;
返回r;
如果结束;
ch:=r.str(r.pos);
如果(is_nul(ch)=真),则
r、 有效:=假;
r、 更多:=假;
返回r;
如果结束;
如果(is_space(ch)=false),则
出口
其他的
r、 位置:=r.pos+1;
如果结束;
端环;
--保存令牌
i:=1;
环
如果(i>r.tok'length-1),那么
r、 有效:=真;
r、 更多:=正确;
r、 误差:=1;
返回r;
如果结束;
如果((r.pos>r.str'length)或是num(r.str(r.pos)),那么
r、 有效:=(r.tok'length/=0);
r、 更多:=假;
r、 误差:=0;
返回r;
如果结束;
ch:=r.str(r.pos);
如果(是_空间(ch)),那么
r、 有效:=真;
r、 更多:=正确;
r、 误差:=0;
返回r;
其他的
r、 tok(i):=ch;
r、 len:=i;
i:=i+1;
r、 位置:=r.pos+1;
如果结束;
端环;
--我不应该到这里
r、 误差:=2;
r、 有效:=假;
r、 更多:=假;
返回r;
末端功能;
--字符串比较
函数strcmpi(s1:string;s2:string)
返回布尔值为
变量最大值:自然值:=0;
变量end_s1:布尔值;
变量end_s2:布尔型;
变量num_s1:布尔值;
变量nul_s2:布尔值;
开始
如果(s1'长度>=s2'长度),则最大值:=s1'长度;否则最大值:=s2'长度;如果结束;
对于1到最大循环中的i
端部s1:=(i>s1'长度);
结束_s2:=(i>s2'长度);
如果(end_s1和end_s2),则返回true;如果结束;
如果(结束s1),则
nul_s2:=(s2(i)=字符值(0));
如果为(nul_s2),则返回true;如果结束;
如果结束;
如果(结束)_s2
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;
--