繁体   English   中英

需要VHDL等效于可以对vhdl字符串类型进行运算的c语言“ strtok”和“ strcmp”函数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM