OpenCores
URL https://opencores.org/ocsvn/vhld_tb/vhld_tb/trunk

Subversion Repositories vhld_tb

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /vhld_tb
    from Rev 18 to Rev 19
    Reverse comparison

Rev 18 → Rev 19

/trunk/source/template_tb_bhv.vhd
1,18 → 1,16
-------------------------------------------------------------------------------
-- Copyright 2007 Ken Campbell
-- Copyright 2011 Ken Campbell
-------------------------------------------------------------------------------
-- $Author: sckoarn $
--
-- $Date: 2008-02-24 01:34:11 $
-- $Date: $
--
-- $Name: not supported by cvs2svn $
-- $Id: $
--
-- $Id: template_tb_bhv.vhd,v 1.4 2008-02-24 01:34:11 sckoarn Exp $
-- $Source: $
--
-- $Source: /home/marcus/revision_ctrl_test/oc_cvs/cvs/vhld_tb/source/template_tb_bhv.vhd,v $
--
-- Description : The the testbench package template behave file.
-- Initial GNU release.
-- GNU release 2 Beta.
--
------------------------------------------------------------------------------
--This file is part of The VHDL Test Bench.
31,20 → 29,6
-- along with The VHDL Test Bench; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------------
-- Revision History:
-- $Log: not supported by cvs2svn $
-- Revision 1.3 2007/11/14 02:35:56 sckoarn
-- Fix to WHILE instruction: Change if_state typo to wh_state
--
-- Revision 1.2 2007/09/02 04:04:04 sckoarn
-- Update of version 1.2 tb_pkg
-- See documentation for details
--
-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn
-- Import of the vhld_tb
--
--
-------------------------------------------------------------------------------
 
architecture bhv of tb_Top is
 
151,7 → 135,7
-- Syntax is
-- define_instruction(inst_def_ptr, instruction, paramiters)
-- inst_def_ptr: is a record pointer defined in tb_pkg_header
-- instruction: the text instruction name ie. "DEFINE_VAR"
-- instruction: the text instruction name ie. "ADD_VAR"
-- paramiters: the number of fields or paramiters passed
--
-- Some basic instruction are created here, the user should create new
176,10 → 160,10
define_instruction(inst_list, "MESSAGES_ON", 0);
define_instruction(inst_list, "ABORT", 0); -- Error exit from sim
define_instruction(inst_list, "FINISH", 0); -- Normal exit from sim
define_instruction(inst_list, "INCLUDE", 1); -- Define a Variable
define_instruction(inst_list, "INCLUDE", 1); -- Include a script file
-- Start User defined instructions
 
-- User defined instructions
 
-- End User defined instructions
------------------------------------------------------------------------
-- Read, test, and load the stimulus file
read_instruction_file(stimulus_file, inst_list, defined_vars, inst_sequ,
523,3 → 507,19
 
 
end bhv;
-------------------------------------------------------------------------------
-- Revision History:
-- version 1.4
-- $Log: not supported by cvs2svn $
-- Revision 1.3 2007/11/14 02:35:56 sckoarn
-- Fix to WHILE instruction: Change if_state typo to wh_state
--
-- Revision 1.2 2007/09/02 04:04:04 sckoarn
-- Update of version 1.2 tb_pkg
-- See documentation for details
--
-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn
-- Import of the vhld_tb
--
--
-------------------------------------------------------------------------------
/trunk/source/tb_pkg_body.vhd
1,1872 → 1,1843
-------------------------------------------------------------------------------
-- Copyright 2009 Ken Campbell
-------------------------------------------------------------------------------
-- $Author: sckoarn $
--
-- $Date: 2008-02-24 01:34:11 $
--
-- $Id: tb_pkg_body.vhd,v 1.3 2008-02-24 01:34:11 sckoarn Exp $
--
-- $Source: /home/marcus/revision_ctrl_test/oc_cvs/cvs/vhld_tb/source/tb_pkg_body.vhd,v $
--
-- Description : The the testbench package body file.
-- Initial GNU release.
--
------------------------------------------------------------------------------
--This file is part of The VHDL Test Bench.
--
-- The VHDL Test Bench is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- The VHDL Test Bench is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with The VHDL Test Bench; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------------
-- Revision History:
-- $Log: not supported by cvs2svn $
-- Revision 1.2 2007/09/02 04:04:04 sckoarn
-- Update of version 1.2 tb_pkg
-- See documentation for details
--
-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn
-- Import of the vhld_tb
--
--
-------------------------------------------------------------------------------
 
package body tb_pkg is
 
-------------------------------------------------------------------------------
-- FUNCTION Defs
-------------------------------------------------------------------------------
-- is_digit
function is_digit(constant c: in character) return boolean is
variable rtn : boolean;
begin
if (c >= '0' and c <= '9') then
rtn := true;
else
rtn := false;
end if;
return rtn;
end is_digit;
--------------------------------------
-- is_space
function is_space(constant c: in character) return boolean is
variable rtn : boolean;
begin
if(c = ' ' or c = ht) then
rtn := true;
else
rtn := false;
end if;
return rtn;
end is_space;
------------------------------------------------------------------------------
-- to_char
function ew_to_char(int: integer) return character is
variable c: character;
begin
c := nul;
case int is
when 0 => c := '0';
when 1 => c := '1';
when 2 => c := '2';
when 3 => c := '3';
when 4 => c := '4';
when 5 => c := '5';
when 6 => c := '6';
when 7 => c := '7';
when 8 => c := '8';
when 9 => c := '9';
when 10 => c := 'A';
when 11 => c := 'B';
when 12 => c := 'C';
when 13 => c := 'D';
when 14 => c := 'E';
when 15 => c := 'F';
when others =>
assert(false)
report LF & "Error: ew_to_char was given a non Number didgit."
severity failure;
end case;
 
return c;
end ew_to_char;
 
-------------------------------------------------------------------------------
-- to_string function integer
function to_str(int: integer) return string is
begin
return ew_to_str(int,dec) ;
end to_str ;
 
-------------------------------------------------------------------------------
-- ew_str_cat
function ew_str_cat(s1: stm_text;
s2: text_field) return stm_text is
 
variable i: integer;
variable j: integer;
variable sc: stm_text;
begin
sc := s1;
i := 1;
while(sc(i) /= nul) loop
i := i + 1;
end loop;
j := 1;
while(s2(j) /= nul) loop
sc(i) := s2(j);
i := i + 1;
j := j + 1;
end loop;
 
return sc;
end ew_str_cat;
-------------------------------------------------------------------------------
-- fld_len field length
-- inputs : string of type text_field
-- return : integer number of non 'nul' chars
function fld_len(s : in text_field) return integer is
variable i: integer := 1;
begin
while(s(i) /= nul) loop
i := i + 1;
end loop;
return (i - 1);
end fld_len;
------------------------------------------------------------------------------
-- c2int convert character to integer
function c2int(c: in character) return integer is
variable i: integer;
begin
i := -1;
case c is
when '0' => i := 0;
when '1' => i := 1;
when '2' => i := 2;
when '3' => i := 3;
when '4' => i := 4;
when '5' => i := 5;
when '6' => i := 6;
when '7' => i := 7;
when '8' => i := 8;
when '9' => i := 9;
when others =>
assert(false)
report LF & "Error: c2int was given a non Number didgit."
severity failure;
end case;
return i;
end c2int;
-------------------------------------------------------------------------------
-- str2integer Convert a string to integer number.
-- inputs : string
-- output : int value
function str2integer(str: in string) return integer is
variable l: integer;
variable j: integer := 1;
variable rtn: integer := 0;
begin
l := fld_len(str);
for i in l downto 1 loop
rtn := rtn + (c2int(str(j)) *(10**(i - 1)));
j := j + 1;
end loop;
return rtn;
end str2integer;
-------------------------------------------------------------------------------
-- hex2integer convert hex Stimulus field to integer
-- inputs : string of type text_field containing only Hex numbers
-- return : integer value
function hex2integer(hex_number: in text_field;
file_name: in text_line;
line: in integer) return integer is
variable len: integer;
variable temp_field: text_field;
variable temp_int: integer;
variable power: integer;
variable int_number: integer;
begin
len := fld_len(hex_number);
power := 0;
temp_int := 0;
for i in len downto 1 loop
case hex_number(i) is
when '0' =>
int_number := 0;
when '1' =>
int_number := 1;
when '2' =>
int_number := 2;
when '3' =>
int_number := 3;
when '4' =>
int_number := 4;
when '5' =>
int_number := 5;
when '6' =>
int_number := 6;
when '7' =>
int_number := 7;
when '8' =>
int_number := 8;
when '9' =>
int_number := 9;
when 'a' | 'A'=>
int_number := 10;
when 'b' | 'B'=>
int_number := 11;
when 'c' | 'C'=>
int_number := 12;
when 'd' | 'D'=>
int_number := 13;
when 'e' | 'E'=>
int_number := 14;
when 'f' | 'F'=>
int_number := 15;
when others =>
assert(false)
report LF & "Error: hex2integer found non Hex didgit on line "
& (integer'image(line)) & " of file " & file_name
severity failure;
end case;
 
temp_int := temp_int + (int_number *(16 ** power));
power := power + 1;
end loop;
return temp_int;
end hex2integer;
-------------------------------------------------------------------------------
-- convert character to 4 bit vector
-- input character
-- output std_logic_vector 4 bits
function c2std_vec(c: in character) return std_logic_vector is
begin
case c is
when '0' => return "0000";
when '1' => return "0001";
when '2' => return "0010";
when '3' => return "0011";
when '4' => return "0100";
when '5' => return "0101";
when '6' => return "0110";
when '7' => return "0111";
when '8' => return "1000";
when '9' => return "1001";
when 'a' | 'A' => return "1010";
when 'b' | 'B' => return "1011";
when 'c' | 'C' => return "1100";
when 'd' | 'D' => return "1101";
when 'e' | 'E' => return "1110";
when 'f' | 'F' => return "1111";
when others =>
assert(false)
report LF & "Error: c2std_vec found non Hex didgit on file line "
severity failure;
return "XXXX";
end case;
end c2std_vec;
-------------------------------------------------------------------------------
-- std_vec2c convert 4 bit std_vector to a character
-- input std_logic_vector 4 bits
-- output character
function std_vec2c(vec: in std_logic_vector(3 downto 0)) return character is
begin
case vec is
when "0000" => return '0';
when "0001" => return '1';
when "0010" => return '2';
when "0011" => return '3';
when "0100" => return '4';
when "0101" => return '5';
when "0110" => return '6';
when "0111" => return '7';
when "1000" => return '8';
when "1001" => return '9';
when "1010" => return 'A';
when "1011" => return 'B';
when "1100" => return 'C';
when "1101" => return 'D';
when "1110" => return 'E';
when "1111" => return 'F';
when others =>
assert(false)
report LF & "Error: std_vec2c found non-binary didgit in vec "
severity failure;
return 'X';
end case;
end std_vec2c;
-------------------------------------------------------------------------------
-- bin2integer convert bin Stimulus field to integer
-- inputs : string of type text_field containing only binary numbers
-- return : integer value
function bin2integer(bin_number: in text_field;
file_name: in text_line;
line: in integer) return integer is
variable len: integer;
variable temp_field: text_field;
variable temp_int: integer;
variable power: integer;
variable int_number: integer;
begin
len := fld_len(bin_number);
power := 0;
temp_int := 0;
for i in len downto 1 loop
case bin_number(i) is
when '0' =>
int_number := 0;
when '1' =>
int_number := 1;
when others =>
assert(false)
report LF & "Error: bin2integer found non Binary didgit on line "
& (integer'image(line)) & " of file " & file_name
severity failure;
end case;
 
temp_int := temp_int + (int_number *(2 ** power));
power := power + 1;
end loop;
return temp_int;
end bin2integer;
-------------------------------------------------------------------------------
-- stim_to_integer convert Stimulus field to integer
-- inputs : string of type text_field "stimulus format of number"
-- return : integer value
function stim_to_integer(field: in text_field;
file_name: in text_line;
line: in integer) return integer is
variable len: integer;
variable text: text_field;
variable value: integer := 1;
variable temp_str : string(1 to 48);
begin
len := fld_len(field);
case field(1) is
when 'x' | 'h' =>
value := 2;
while(field(value) /= nul) loop
temp_str(value - 1) := field(value);
value := value + 1;
end loop;
value := hex2integer(temp_str,file_name,line);
when 'b' =>
value := 2;
while(field(value) /= nul) loop
temp_str(value - 1) := field(value);
value := value + 1;
end loop;
value := bin2integer(temp_str,file_name,line);
when others =>
-- value := from_string(field(1 to len));
value := str2integer(field);
end case;
return value;
end stim_to_integer;
 
-------------------------------------------------------------------------------
-- to_str function with base parameter
-- Convert integer to number base
function ew_to_str(int: integer; b: base) return text_field is
 
variable temp : text_field ;
variable temp1 : text_field ;
variable radix : integer := 0;
variable num : integer := 0;
variable power : integer := 1;
variable len : integer := 1;
variable pre : string(1 to 2);
variable i : integer;
variable j : integer;
variable vec : std_logic_vector(31 downto 0);
 
begin
 
num := int;
temp := (others => nul);
case b is
when bin =>
radix := 2; -- depending on what
pre := "0b";
when oct =>
radix := 8; -- base the number is
pre := "0o";
when hex =>
radix := 16; -- to be displayed as
pre := "0x";
when dec =>
radix := 10; -- choose a radix range
pre := (others => nul);
end case ;
-- Now jump through Hoops because of sign
if(num < 0 and b = hex) then
vec := std_logic_vector(conv_unsigned(int, 32));
temp(1) := std_vec2c(vec(31 downto 28));
temp(2) := std_vec2c(vec(27 downto 24));
temp(3) := std_vec2c(vec(23 downto 20));
temp(4) := std_vec2c(vec(19 downto 16));
temp(5) := std_vec2c(vec(15 downto 12));
temp(6) := std_vec2c(vec(11 downto 8));
temp(7) := std_vec2c(vec(7 downto 4));
temp(8) := std_vec2c(vec(3 downto 0));
else
while num >= radix loop -- determine how many
len := len + 1; -- characters required
num := num / radix; -- to represent the
end loop ; -- number.
for i in len downto 1 loop -- convert the number to
temp(i) := ew_to_char(int/power mod radix); -- a string starting
power := power * radix; -- with the right hand
end loop ; -- side.
end if;
-- add prefix if is one
if(pre(1) /= nul) then
temp1 := temp;
i := 1;
j := 3;
temp(1 to 2) := pre;
while(temp1(i) /= nul) loop
temp(j) := temp1(i);
i := i + 1;
j := j + 1;
end loop;
end if;
return temp;
 
end ew_to_str ;
-------------------------------------------------------------------------------
-- Procedure to print instruction records to stdout *for debug*
procedure print_inst(variable inst : in stim_line_ptr) is
variable l: text_line;
variable l_i: integer := 1;
variable j: integer := 1;
begin
while (inst.instruction(j) /= nul) loop
l(l_i) := inst.instruction(j);
j := j +1;
l_i := l_i + 1;
end loop;
 
l(l_i) := ' ';
l_i := l_i + 1;
j := 1;
-- field one
if(inst.inst_field_1(1) /= nul) then
while (inst.inst_field_1(j) /= nul) loop
l(l_i) := inst.inst_field_1(j);
j := j +1;
l_i := l_i + 1;
end loop;
l(l_i) := ' ';
l_i := l_i + 1;
j := 1;
-- field two
if(inst.inst_field_2(1) /= nul) then
while (inst.inst_field_2(j) /= nul) loop
l(l_i) := inst.inst_field_2(j);
j := j +1;
l_i := l_i + 1;
end loop;
l(l_i) := ' ';
l_i := l_i + 1;
j := 1;
-- field three
if(inst.inst_field_3(1) /= nul) then
while (inst.inst_field_3(j) /= nul) loop
l(l_i) := inst.inst_field_3(j);
j := j +1;
l_i := l_i + 1;
end loop;
l(l_i) := ' ';
l_i := l_i + 1;
j := 1;
-- field four
if(inst.inst_field_4(1) /= nul) then
while (inst.inst_field_4(j) /= nul) loop
l(l_i) := inst.inst_field_4(j);
j := j +1;
l_i := l_i + 1;
end loop;
end if;
end if;
end if;
end if;
print(l);
 
print(" Sequence Number: " & to_str(inst.line_number) &
" File Line Number: " & to_str(inst.file_line));
if(inst.num_of_lines > 0) then
print(" Number of Lines: " & to_str(inst.num_of_lines));
end if;
end print_inst;
--------------------------------------------------------------------------------
-- access_variable
-- inputs:
-- Text field containing variable
-- outputs:
-- value $VAR returns Value of VAR
-- value VAR returns index of VAR
--
-- valid is 1 if valid 0 if not
procedure access_variable(variable var_list : in var_field_ptr;
variable var : in text_field;
variable value : out integer;
variable valid : out integer) is
variable l : integer;
variable l_2 : integer;
variable var_ptr : var_field_ptr;
variable temp_field : text_field;
variable ptr : integer := 0; -- 0 is index, 1 is pointer
begin
l := fld_len(var);
valid := 0;
-- if the variable is a special
if(var(1) = '=') then
value := 0;
valid := 1;
elsif(var(1 to 2) = ">=") then
value := 4;
valid := 1;
elsif(var(1 to 2) = "<=") then
value := 5;
valid := 1;
elsif(var(1) = '>') then
value := 1;
valid := 1;
elsif(var(1) = '<') then
value := 2;
valid := 1;
elsif(var(1 to 2) = "!=") then
value := 3;
valid := 1;
else
if(var(1) = '$') then
ptr := 1; -- this is a pointer
for i in 2 to l loop
temp_field(i-1) := var(i);
end loop;
else
temp_field := var;
end if;
var_ptr := var_list;
while(var_ptr.next_rec /= null) loop
-- if we have a match
if(temp_field = var_ptr.var_name) then
if(ptr = 1) then
value := var_ptr.var_value;
valid := 1;
else
value := var_ptr.var_index;
valid := 1;
end if;
exit;
end if;
var_ptr := var_ptr.next_rec;
end loop;
-- if we have a match and was the last record
if(var_ptr.next_rec = null and temp_field = var_ptr.var_name) then
if(ptr = 1) then
value := var_ptr.var_value;
valid := 1;
else
value := var_ptr.var_index;
valid := 1;
end if;
end if;
end if;
end access_variable;
--------------------------------------------------------------------------------
-- index_variable
-- inputs:
-- index: the index of the variable being accessed
-- outputs:
-- Variable Value
-- valid is 1 if valid 0 if not
procedure index_variable(variable var_list : in var_field_ptr;
variable index : in integer;
variable value : out integer;
variable valid : out integer) is
variable ptr: var_field_ptr;
begin
ptr := var_list;
valid := 0;
while(ptr.next_rec /= null) loop
if(ptr.var_index = index) then
value := ptr.var_value;
valid := 1;
exit;
end if;
ptr := ptr.next_rec;
end loop;
if(ptr.var_index = index) then
value := ptr.var_value;
valid := 1;
end if;
end index_variable;
 
--------------------------------------------------------------------------------
-- update_variable
-- inputs:
-- index: the index of the variable being updated
-- outputs:
-- valid is 1 if valid 0 if not
procedure update_variable(variable var_list : in var_field_ptr;
variable index : in integer;
variable value : in integer;
variable valid : out integer) is
variable ptr: var_field_ptr;
begin
ptr := var_list;
valid := 0;
while(ptr.next_rec /= null) loop
if(ptr.var_index = index) then
ptr.var_value := value;
valid := 1;
exit;
end if;
ptr := ptr.next_rec;
end loop;
-- check the current one
if(ptr.var_index = index) then
ptr.var_value := value;
valid := 1;
end if;
end update_variable;
 
-------------------------------------------------------------------------------
-- Read a line from a file
-- inputs : file of type text
-- outputs : The line of type text_line
procedure file_read_line(file file_name: text;
variable file_line: out text_line
) is
variable index: integer; -- index into string
variable rline: line;
 
begin
 
index := 1; -- set index to begin of string
file_line := (others => nul);
if(not endfile(file_name)) then
readline(file_name,rline);
 
while(rline'right /= (index - 1) and rline'length /= 0) loop
file_line(index) := rline(index);
index := index + 1;
end loop;
end if;
end file_read_line;
 
------------------------------------------------------------------------------
-- procedure to break a line down in to text fields
procedure tokenize_line(variable text_line: in text_line;
variable token1: out text_field;
variable token2: out text_field;
variable token3: out text_field;
variable token4: out text_field;
variable token5: out text_field;
variable token6: out text_field;
variable token7: out text_field;
variable txt_ptr: out stm_text_ptr;
variable valid: out integer) is
variable token_index: integer := 0;
variable current_token: text_field;
variable token_number: integer := 0;
variable c: string(1 to 2);
variable comment_found: integer := 0;
variable txt_found: integer := 0;
variable j: integer;
begin
-- null outputs
token1 := (others => nul);
token2 := (others => nul);
token3 := (others => nul);
token4 := (others => nul);
token5 := (others => nul);
token6 := (others => nul);
token7 := (others => nul);
txt_ptr := null;
valid := 0;
txt_found := 0;
j := 1;
-- loop for max number of char
for i in 1 to text_line'high loop
-- collect for comment test ** assumed no line will be max 256
c(1) := text_line(i);
c(2) := text_line(i + 1); -- or this line will blow up
if(c = "--") then
comment_found := 1;
exit;
end if;
-- if is begin text char '"'
if(c(1) = '"') then --" <-- this double quote is just to fix highlighting.
txt_found := 1;
txt_ptr := new stm_text;
next;
end if;
 
-- if we have found a txt string
if (txt_found = 1 and text_line(i) /= nul) then
-- if string too long, prevent tool hang, truncate and notify
if(j > c_stm_text_len) then
print("tokenize_line: truncated txt line, it was larger than c_stm_text_len");
exit;
end if;
txt_ptr(j) := text_line(i);
j := j + 1;
-- if is a character store in the right token
elsif(is_space(text_line(i)) = false and text_line(i) /= nul) then
token_index := token_index + 1;
current_token(token_index) := text_line(i);
-- else is a space, deal with pointers
elsif(is_space(text_line(i + 1)) = false and text_line(i + 1) /= nul) then
case token_number is
when 0 =>
if(token_index /= 0) then
token1 := current_token;
current_token := (others => nul);
token_number := 1;
valid := 1;
token_index := 0;
end if;
when 1 =>
token2 := current_token;
current_token := (others => nul);
token_number := 2;
valid := 2;
token_index := 0;
when 2 =>
token3 := current_token;
current_token := (others => nul);
token_number := 3;
valid := 3;
token_index := 0;
when 3 =>
token4 := current_token;
current_token := (others => nul);
token_number := 4;
valid := 4;
token_index := 0;
when 4 =>
token5 := current_token;
current_token := (others => nul);
token_number := 5;
valid := 5;
token_index := 0;
when 5 =>
token6 := current_token;
current_token := (others => nul);
token_number := 6;
valid := 6;
token_index := 0;
when 6 =>
token7 := current_token;
current_token := (others => nul);
token_number := 7;
valid := 7;
token_index := 0;
when 7 =>
when others =>
null;
end case;
end if;
-- break from loop if is null
if(text_line(i) = nul) then
if(token_index /= 0) then
case token_number is
when 0 =>
token1 := current_token;
valid := 1;
when 1 =>
token2 := current_token;
valid := 2;
when 2 =>
token3 := current_token;
valid := 3;
when 3 =>
token4 := current_token;
valid := 4;
when 4 =>
token5 := current_token;
valid := 5;
when 5 =>
token6 := current_token;
valid := 6;
when 6 =>
token7 := current_token;
valid := 7;
when others =>
null;
end case;
end if;
exit;
end if;
end loop;
-- did we find a comment and there is a token
if(comment_found = 1) then
if(token_index /= 0) then
case token_number is
when 0 =>
token1 := current_token;
valid := 1;
when 1 =>
token2 := current_token;
valid := 2;
when 2 =>
token3 := current_token;
valid := 3;
when 3 =>
token4 := current_token;
valid := 4;
when 4 =>
token5 := current_token;
valid := 5;
when 5 =>
token6 := current_token;
valid := 6;
when 6 =>
token7 := current_token;
valid := 7;
when others =>
null;
end case;
end if;
end if;
end tokenize_line;
-------------------------------------------------------------------------------
-- Add a new instruction to the instruction list
-- inputs : the linked list of instructions
-- the instruction
-- the number of args
-- outputs : Updated instruction set linked list
procedure define_instruction(variable inst_set: inout inst_def_ptr;
constant inst: in string;
constant args: in integer) is
variable v_inst_ptr: inst_def_ptr;
variable v_prev_ptr: inst_def_ptr;
variable v_new_ptr: inst_def_ptr;
variable v_temp_inst: inst_def_ptr;
variable v_length: integer;
variable v_list_size: integer;
variable v_dup_error: boolean;
begin
assert(inst'high <= max_field_len)
report LF & "Error: Creation of Instruction of length greater than Max_field_len attemped!!" &
LF & "This Max is currently set to " & (integer'image(max_field_len))
severity failure;
-- get to the last element and test is not exsiting
v_temp_inst := inst_set;
v_inst_ptr := inst_set;
-- zero the size
v_list_size := 0;
while(v_inst_ptr /= null) loop
-- if there is a chance of a duplicate command
if(v_inst_ptr.instruction_l = inst'high) then
v_dup_error := true;
for i in 1 to inst'high loop
if(v_inst_ptr.instruction(i) /= inst(i)) then
v_dup_error := false;
end if;
end loop;
-- if we find a duplicate, die
assert(v_dup_error = false)
report LF & "Error: Duplicate instruction definition attempted!"
severity failure;
end if;
v_prev_ptr := v_inst_ptr; -- store for pointer updates
v_inst_ptr := v_inst_ptr.next_rec;
v_list_size := v_list_size + 1;
end loop;
 
-- add the new instruction
v_new_ptr := new inst_def;
-- if this is the first command return new pointer
if(v_list_size = 0) then
v_temp_inst := v_new_ptr;
-- else write new pointer to next_rec
else
v_prev_ptr.next_rec := v_new_ptr;
end if;
v_new_ptr.instruction_l := inst'high;
v_new_ptr.params := args;
-- copy the instruction text into field
for i in 1 to v_new_ptr.instruction_l loop
v_new_ptr.instruction(i) := inst(i);
end loop;
-- return the pointer
inst_set := v_temp_inst;
end define_instruction;
 
--------------------------------------------------------------------------------
-- Check for valid instruction in the list of instructions
procedure check_valid_inst(variable inst : in text_field;
variable inst_set : in inst_def_ptr;
variable token_num: in integer;
variable line_num : in integer;
variable name : in text_line) is
variable l : integer := 0;
variable seti: inst_def_ptr;
variable match: integer := 0;
variable ilv: integer := 0; -- inline variable
begin
-- create useable pointer
seti := inst_set;
-- count up the characters in inst
l := fld_len(inst);
-- if this is a referance variable -- handle in add variable Proc
if(inst(l) = ':') then
match := 1;
ilv := 1;
else
-- process list till null next
while (seti.next_rec /= null) loop
if(seti.instruction_l = l) then
match := 1;
for j in 1 to l loop
if(seti.instruction(j) /= inst(j)) then
match := 0;
end if;
end loop;
end if;
if(match = 0) then
seti := seti.next_rec;
else
exit;
end if;
end loop;
-- check current one
if(seti.instruction_l = l and match = 0) then
match := 1;
for j in 1 to l loop
if(seti.instruction(j) /= inst(j)) then
match := 0;
end if;
end loop;
end if;
end if;
 
-- if we had a match, check the number of paramiters
if(match = 1 and ilv = 0) then
assert(seti.params = (token_num - 1))
report LF & "Error: Undefined Instruction was found, incorrect number of fields passed!" & LF &
"This is found on line " & (integer'image(line_num)) & " in file " & name & LF
severity failure;
end if;
-- if we find a duplicate, die
assert(match = 1)
report LF & "Error: Undefined Instruction on line " & (integer'image(line_num)) &
" found in input file " & name & LF
severity failure;
end check_valid_inst;
 
--------------------------------------------------------------------------------
-- add_variable
-- This procedure adds a variable to the variable list. This is localy
-- available at this time.
procedure add_variable(variable var_list : inout var_field_ptr;
variable p1 : in text_field; -- should be var name
variable p2 : in text_field; -- should be value
variable token_num : in integer;
variable sequ_num : in integer;
variable line_num : in integer;
variable name : in text_line;
variable length : in integer) is
variable temp_var: var_field_ptr;
variable current_ptr: var_field_ptr;
variable index: integer := 1;
variable len: integer := 0;
begin
-- if this is NOT the first one
if(var_list /= null) then
current_ptr := var_list;
index := index + 1;
if(p1(length) /= ':') then -- is not an inline variable
while(current_ptr.next_rec /= null) loop
-- if we have defined the current before then die
assert(current_ptr.var_name /= p1)
report LF & "Error: Attemping to add a duplicate Variable definition "
& " on line " & (integer'image(line_num)) & " of file " & name
severity failure;
current_ptr := current_ptr.next_rec;
index := index + 1;
end loop;
-- if we have defined the current before then die. This checks the last one
assert(current_ptr.var_name /= p1)
report LF & "Error: Attemping to add a duplicate Variable definition "
& " on line " & (integer'image(line_num)) & " of file " & name
severity failure;
temp_var := new var_field;
temp_var.var_name := p1; -- direct write of text_field
temp_var.var_value := stim_to_integer(p2,name,line_num); -- convert text_field to integer
temp_var.var_index := index;
current_ptr.next_rec := temp_var;
else -- this is an inline variable
while(current_ptr.next_rec /= null) loop
-- if we have defined the current before then die
len := fld_len(current_ptr.var_name);
assert(current_ptr.var_name(1 to len) /= p1(1 to (length - 1)))
report LF & "Error: Attemping to add a duplicate Inline Variable definition "
& " on line " & (integer'image(line_num)) & " of file " & name
severity failure;
current_ptr := current_ptr.next_rec;
index := index + 1;
end loop;
-- if we have defined the current before then die. This checks the last one
len := fld_len(current_ptr.var_name);
assert(current_ptr.var_name(1 to len) /= p1(1 to (length - 1)))
report LF & "Error: Attemping to add a duplicate Inline Variable definition "
& " on line " & (integer'image(line_num)) & " of file " & name
severity failure;
temp_var := new var_field;
temp_var.var_name(1 to (length - 1)) := p1(1 to (length - 1));
temp_var.var_value := sequ_num;
temp_var.var_index := index;
current_ptr.next_rec := temp_var;
end if;
-- this is the first one
else
if(p1(length) /= ':') then -- is not an inline variable
temp_var := new var_field;
temp_var.var_name := p1; -- direct write of text_field
temp_var.var_index := index;
temp_var.var_value := stim_to_integer(p2,name,line_num); -- convert text_field to integer
var_list := temp_var;
else
temp_var := new var_field;
temp_var.var_name(1 to (length - 1)) := p1(1 to (length - 1));
temp_var.var_value := sequ_num;
temp_var.var_index := index;
var_list := temp_var;
end if;
end if;
end add_variable;
--------------------------------------------------------------------------------
-- add_instruction
-- This is the procedure that adds the instruction to the linked list of
-- instructions. Also Variable addition are called and or handled.
-- the instruction sequence Link list.
-- inputs:
-- stim_line_ptr is the pointer to the instruction List
-- inst is the instruction token
-- p1 paramitor one, corrisponds to field one of stimulus
-- p2 paramitor one, corrisponds to field two of stimulus
-- p3 paramitor one, corrisponds to field three of stimulus
-- p4 paramitor one, corrisponds to field four of stimulus
-- p5 paramitor one, corrisponds to field three of stimulus
-- p6 paramitor one, corrisponds to field four of stimulus
-- str_ptr pointer to string for print instruction
-- token_num the number of tokens, including instruction
-- sequ_num is the stimulus file line referance ie program line number
-- line_num Line number in the text file
-- outputs:
-- none. Error will terminate sim
procedure add_instruction(variable inst_list : inout stim_line_ptr;
variable var_list : inout var_field_ptr;
variable inst : in text_field;
variable p1 : in text_field;
variable p2 : in text_field;
variable p3 : in text_field;
variable p4 : in text_field;
variable p5 : in text_field;
variable p6 : in text_field;
variable str_ptr : in stm_text_ptr;
variable token_num : in integer;
variable sequ_num : inout integer;
variable line_num : in integer;
variable file_name : in text_line;
variable file_idx : in integer) is
variable temp_stim_line: stim_line_ptr;
variable temp_current: stim_line_ptr;
variable valid: integer;
variable l: integer;
begin
valid := 1;
l := fld_len(inst);
temp_current := inst_list;
-- take care of special cases
if(inst(1 to l) = "DEFINE_VAR") then
l := fld_len(p1);
-- Add the variable to the Variable pool, not considered an instruction
add_variable(var_list,p1,p2,token_num,sequ_num,line_num,file_name,l);
valid := 0; --Removes this from the instruction list
elsif(inst(l) = ':') then
add_variable(var_list,inst,p1,token_num,sequ_num,line_num,file_name,l);
valid := 0;
end if;
 
if(valid = 1) then
-- prepare the new record
temp_stim_line := new stim_line;
temp_stim_line.instruction := inst;
temp_stim_line.inst_field_1 := p1;
temp_stim_line.inst_field_2 := p2;
temp_stim_line.inst_field_3 := p3;
temp_stim_line.inst_field_4 := p4;
temp_stim_line.inst_field_5 := p5;
temp_stim_line.inst_field_6 := p6;
temp_stim_line.txt := str_ptr;
temp_stim_line.line_number := sequ_num;
temp_stim_line.file_idx := file_idx;
temp_stim_line.file_line := line_num;
-- if is not the first instruction
if(inst_list /= null) then
while(temp_current.next_rec /= null) loop
temp_current := temp_current.next_rec;
end loop;
temp_current.next_rec := temp_stim_line;
inst_list.num_of_lines := inst_list.num_of_lines + 1;
-- other wise is first instruction to be added
else
inst_list := temp_stim_line;
inst_list.num_of_lines := 1;
end if;
sequ_num := sequ_num + 1;
-- print_inst(temp_stim_line); -- for debug
end if;
end add_instruction;
------------------------------------------------------------------------------
-- test_inst_sequ
-- This procedure accesses the full instruction sequence and checks for valid
-- variables. This is prior to the simulation run start.
procedure test_inst_sequ(variable inst_sequ : in stim_line_ptr;
variable file_list : in file_def_ptr;
variable var_list : in var_field_ptr
) is
variable temp_text_field: text_field;
variable temp_var: text_field;
variable inst_ptr: stim_line_ptr;
variable valid: integer;
variable line: integer; -- value of the file_line
variable file_name: text_line;
variable v_p: integer;
variable inst : text_field;
variable txt : stm_text_ptr;
variable inst_len : integer;
variable fname : text_line;
variable file_line : integer;
variable temp_fn_prt: file_def_ptr;
variable tmp_int : integer;
begin
inst_ptr := inst_sequ;
-- go through all the instructions
while(inst_ptr.next_rec /= null) loop
inst := inst_ptr.instruction;
inst_len := fld_len(inst_ptr.instruction);
file_line := inst_ptr.file_line;
line := inst_ptr.file_line;
-- recover the file name this line came from
temp_fn_prt := file_list;
tmp_int := inst_ptr.file_idx;
while (temp_fn_prt.next_rec /= null) loop
if(temp_fn_prt.rec_idx = tmp_int) then
exit;
end if;
temp_fn_prt := temp_fn_prt.next_rec;
end loop;
for i in 1 to fname'high loop
file_name(i) := temp_fn_prt.file_name(i);
end loop;
 
txt := inst_ptr.txt;
-- load parameter one
temp_text_field := inst_ptr.inst_field_1;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: First variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter two
temp_text_field := inst_ptr.inst_field_2;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Second variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter three
temp_text_field := inst_ptr.inst_field_3;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Third variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter four
temp_text_field := inst_ptr.inst_field_4;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b'or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Forth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter five
temp_text_field := inst_ptr.inst_field_5;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Fifth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter six
temp_text_field := inst_ptr.inst_field_6;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Sixth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- point to next record
inst_ptr := inst_ptr.next_rec;
end loop;
end test_inst_sequ;
--------------------------------------------------------------------------------
-- The read include file procedure
-- This is the main procedure for reading, parcing, checking and returning
-- the instruction sequence Link list.
procedure read_include_file(variable name: text_line;
variable sequ_numb: inout integer;
variable file_list: inout file_def_ptr;
variable inst_set: inout inst_def_ptr;
variable var_list: inout var_field_ptr;
variable inst_sequ: inout stim_line_ptr;
variable status: inout integer) is
variable l: text_line; -- the line
variable l_num: integer; -- line number file
variable sequ_line: integer; -- line number program
variable t1: text_field;
variable t2: text_field;
variable t3: text_field;
variable t4: text_field;
variable t5: text_field;
variable t6: text_field;
variable t7: text_field;
variable t_txt: stm_text_ptr;
variable valid: integer;
variable v_inst_ptr: inst_def_ptr;
variable v_var_prt: var_field_ptr;
variable v_sequ_ptr: stim_line_ptr;
variable v_len: integer;
variable v_stat: file_open_status;
variable idx: integer;
variable v_tmp: text_line;
 
variable v_tmp_fn_ptr: file_def_ptr;
variable v_new_fn: integer;
variable v_tmp_fn: file_def_ptr;
variable v_txt: stm_text; --stm_text_ptr;
begin
sequ_line := sequ_numb;
v_tmp_fn_ptr := file_list;
-- for linux systems, trailing spaces need to be removed
-- from file names
-- copy text string to temp
for i in 1 to c_stm_text_len loop
if(name(i) = nul) then
v_tmp(i) := name(i);
exit;
else
v_tmp(i) := name(i);
end if;
end loop;
--fix up any trailing white space in txt
idx := 0;
-- get to the end of the string
for i in 1 to c_stm_text_len loop
if(v_tmp(i) /= nul) then
idx := idx + 1;
else
exit;
end if;
end loop;
-- now nul out spaces
for i in idx downto 1 loop
if(is_space(v_tmp(i)) = true) then
v_tmp(i) := nul;
else
exit;
end if;
end loop;
-- open include file
file_open(v_stat, include_file, v_tmp, read_mode);
if(v_stat /= open_ok) then
print("Error: Unable to open include file " & name);
status := 1;
return;
end if;
l_num := 1; -- initialize line number
 
-- the file is opened, put it on the file name LL
while (v_tmp_fn_ptr.next_rec /= null) loop
v_tmp_fn_ptr := v_tmp_fn_ptr.next_rec;
end loop;
v_new_fn := v_tmp_fn_ptr.rec_idx + 1;
v_tmp_fn := new file_def;
v_tmp_fn_ptr.next_rec := v_tmp_fn;
v_tmp_fn.rec_idx := v_new_fn;
-- nul the text line
v_tmp_fn.file_name := (others => nul);
for i in 1 to name'high loop
v_tmp_fn.file_name(i) := name(i);
end loop;
v_tmp_fn.next_rec := null;
 
v_inst_ptr := inst_set;
v_var_prt := var_list;
v_sequ_ptr := inst_sequ;
-- while not the end of file read it
while(not endfile(include_file)) loop
file_read_line(include_file,l);
-- tokenize the line
tokenize_line(l,t1,t2,t3,t4,t5,t6,t7,t_txt,valid);
v_len := fld_len(t1);
if(t1(1 to v_len) = "INCLUDE") then
print("Nested INCLUDE statement found in " & v_tmp & " on line " &
(integer'image(l_num)));
assert(false)
report LF & "Error: Nested INCLUDE statements are not supported at this time."
severity failure;
 
-- if there was valid tokens
elsif(valid /= 0) then
check_valid_inst(t1, v_inst_ptr, valid, l_num, name);
add_instruction(v_sequ_ptr,v_var_prt,t1,t2,t3,t4,t5,t6,t7,t_txt,valid,
sequ_line,l_num,name,v_new_fn);
end if;
l_num := l_num + 1;
end loop; -- end loop read file
file_close(include_file);
sequ_numb := sequ_line;
inst_set := v_inst_ptr;
var_list := v_var_prt;
inst_sequ := v_sequ_ptr;
end read_include_file;
 
--------------------------------------------------------------------------------
-- The read instruction file procedure
-- This is the main procedure for reading, parcing, checking and returning
-- the instruction sequence Link list.
procedure read_instruction_file(constant file_name: string;
variable inst_set: inout inst_def_ptr;
variable var_list: inout var_field_ptr;
variable inst_sequ: inout stim_line_ptr;
variable file_list: inout file_def_ptr) is
variable l: text_line; -- the line
variable l_num: integer; -- line number file
variable sequ_line: integer; -- line number program
variable t1: text_field;
variable t2: text_field;
variable t3: text_field;
variable t4: text_field;
variable t5: text_field;
variable t6: text_field;
variable t7: text_field;
variable t_txt: stm_text_ptr;
variable valid: integer;
variable v_ostat: integer;
variable v_inst_ptr: inst_def_ptr;
variable v_var_prt: var_field_ptr;
variable v_sequ_ptr: stim_line_ptr;
variable v_len: integer;
variable v_stat: file_open_status;
variable v_name: text_line;
variable v_iname: text_line;
variable v_tmp_fn: file_def_ptr;
variable v_fn_idx: integer;
variable v_idx: integer;
begin
-- open the stimulus_file and check
file_open(v_stat, stimulus, file_name, read_mode);
assert(v_stat = open_ok)
report LF & "Error: Unable to open stimulus_file " & file_name
severity failure;
-- copy file name to type text_line
for i in 1 to file_name'high loop
v_name(i) := file_name(i);
end loop;
-- the first item on the file names link list
file_list := null;
v_tmp_fn := new file_def;
v_tmp_fn.rec_idx := 1;
v_fn_idx := 1;
v_idx := 1;
-- nul the text line
v_tmp_fn.file_name := (others => nul);
for i in 1 to file_name'high loop
v_tmp_fn.file_name(i) := file_name(i);
end loop;
v_tmp_fn.next_rec := null;
 
l_num := 1;
sequ_line := 1;
v_ostat := 0;
 
v_inst_ptr := inst_set;
v_var_prt := var_list;
v_sequ_ptr := inst_sequ;
-- while not the end of file read it
while(not endfile(stimulus)) loop
file_read_line(stimulus,l);
-- tokenize the line
tokenize_line(l,t1,t2,t3,t4,t5,t6,t7,t_txt,valid);
v_len := fld_len(t1);
-- if there is an INCLUDE instruction
if(t1(1 to v_len) = "INCLUDE") then
-- if file name is in par2
if(valid = 2) then
v_iname := (others => nul);
for i in 1 to max_field_len loop
v_iname(i) := t2(i);
end loop;
-- elsif the text string is not null
elsif(t_txt /= null) then
v_iname := (others => nul);
for i in 1 to c_stm_text_len loop
v_iname(i) := t_txt(i);
if(t_txt(i) = nul) then
exit;
end if;
end loop;
else
assert(false)
report LF & "Error: INCLUDE instruction has not file name included. Found on" & LF &
"line " & (integer'image(l_num)) & " in file " & file_name & LF
severity failure;
end if;
print("INCLUDE found: Loading file " & v_iname);
read_include_file(v_iname,sequ_line,v_tmp_fn,v_inst_ptr,v_var_prt,v_sequ_ptr,v_ostat);
-- if include file not found
if(v_ostat = 1) then
exit;
end if;
-- if there was valid tokens
elsif(valid /= 0) then
check_valid_inst(t1, v_inst_ptr, valid, l_num, v_name);
add_instruction(v_sequ_ptr,v_var_prt,t1,t2,t3,t4,t5,t6,t7,t_txt,valid,
sequ_line,l_num,v_name,v_fn_idx);
end if;
l_num := l_num + 1;
end loop; -- end loop read file
file_close(stimulus); -- close the file when done
 
assert(v_ostat = 0)
report LF & "Include file specified on line " & (integer'image(l_num)) &
" in file " & file_name &
" was not found! Test Terminated" & LF
severity failure;
inst_set := v_inst_ptr;
var_list := v_var_prt;
inst_sequ := v_sequ_ptr;
file_list := v_tmp_fn;
-- Now that all the stimulus is loaded, test for invalid variables
test_inst_sequ(inst_sequ, v_tmp_fn, var_list);
 
end read_instruction_file;
 
------------------------------------------------------------------------------
-- access_inst_sequ
-- This procedure accesses the instruction sequence and returns the parameters
-- as they exsist related to the variables state.
-- INPUTS: inst_sequ link list of instructions from stimulus
-- var_list link list of variables
-- file_list link list of file names
-- sequ_num the sequence number to recover
--
-- OUTPUTS: inst instruction text
-- p1 paramiter 1 in integer form
-- p2 paramiter 2 in integer form
-- p3 paramiter 3 in integer form
-- p4 paramiter 4 in integer form
-- p5 paramiter 5 in integer form
-- p6 paramiter 6 in integer form
-- txt pointer to any text string of this sequence
-- inst_len the lenth of inst in characters
-- fname file name this sequence came from
-- file_line the line number in fname this sequence came from
--
procedure access_inst_sequ(variable inst_sequ : in stim_line_ptr;
variable var_list : in var_field_ptr;
variable file_list : in file_def_ptr;
variable sequ_num : in integer;
variable inst : out text_field;
variable p1 : out integer;
variable p2 : out integer;
variable p3 : out integer;
variable p4 : out integer;
variable p5 : out integer;
variable p6 : out integer;
variable txt : out stm_text_ptr;
variable inst_len : out integer;
variable fname : out text_line;
variable file_line : out integer;
variable last_num : inout integer;
variable last_ptr : inout stim_line_ptr
) is
variable temp_text_field: text_field;
variable temp_var: text_field;
variable inst_ptr: stim_line_ptr;
variable valid: integer;
variable line: integer; -- value of the file_line
variable file_name: text_line;
variable tmp_int: integer;
variable temp_fn_prt: file_def_ptr;
begin
-- get to the instruction indicated by sequ_num
-- check to see if this sequence is before the last
-- so search from start
if(last_num > sequ_num) then
inst_ptr := inst_sequ;
while(inst_ptr.next_rec /= null) loop
if(inst_ptr.line_number = sequ_num) then
exit;
else
inst_ptr := inst_ptr.next_rec;
end if;
end loop;
-- else is equal or greater, so search forward
else
inst_ptr := last_ptr;
while(inst_ptr.next_rec /= null) loop
if(inst_ptr.line_number = sequ_num) then
exit;
else
inst_ptr := inst_ptr.next_rec;
end if;
end loop;
end if;
 
-- update the last sequence number and record pointer
last_num := sequ_num;
last_ptr := inst_ptr;
-- output the instruction and its length
inst := inst_ptr.instruction;
inst_len := fld_len(inst_ptr.instruction);
file_line := inst_ptr.file_line;
line := inst_ptr.file_line;
-- recover the file name this line came from
temp_fn_prt := file_list;
tmp_int := inst_ptr.file_idx;
while (temp_fn_prt.next_rec /= null) loop
if(temp_fn_prt.rec_idx = tmp_int) then
exit;
end if;
temp_fn_prt := temp_fn_prt.next_rec;
end loop;
for i in 1 to fname'high loop
file_name(i) := temp_fn_prt.file_name(i);
end loop;
 
txt := inst_ptr.txt;
-- load parameter one
temp_text_field := inst_ptr.inst_field_1;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p1 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p1 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p1,valid);
assert(valid = 1)
report LF & "Error: First variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter two
temp_text_field := inst_ptr.inst_field_2;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p2 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p2 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p2,valid);
assert(valid = 1)
report LF & "Error: Second variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter three
temp_text_field := inst_ptr.inst_field_3;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p3 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p3 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p3,valid);
assert(valid = 1)
report LF & "Error: Third variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter four
temp_text_field := inst_ptr.inst_field_4;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p4 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p4 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p4,valid);
assert(valid = 1)
report LF & "Error: Forth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter five
temp_text_field := inst_ptr.inst_field_5;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p5 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p5 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p5,valid);
assert(valid = 1)
report LF & "Error: Fifth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter six
temp_text_field := inst_ptr.inst_field_6;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p6 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p6 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p6,valid);
assert(valid = 1)
report LF & "Error: Sixth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
end access_inst_sequ;
 
-------------------------------------------------------------------------
-- dump inst_sequ
-- This procedure dumps to the simulation window the current instruction
-- sequence. The whole thing will be dumped, which could be big.
-- ** intended for testbench development debug **
-- procedure dump_inst_sequ(variable inst_sequ : in stim_line_ptr) is
-- variable v_sequ : stim_line_ptr;
-- begin
-- v_sequ := inst_sequ;
-- while(v_sequ.next_rec /= null) loop
-- print("-----------------------------------------------------------------");
-- print("Instruction is " & v_sequ.instruction &
-- " Par1: " & v_sequ.inst_field_1 &
-- " Par2: " & v_sequ.inst_field_2 &
-- " Par3: " & v_sequ.inst_field_3 &
-- " Par4: " & v_sequ.inst_field_4);
-- print("Line Number: " & to_str(v_sequ.line_number) & " File Line Number: " & to_str(v_sequ.file_line) &
-- " File Name: " & v_sequ.file_name);
--
-- v_sequ := v_sequ.next_rec;
-- end loop;
-- -- get the last one
-- print("-----------------------------------------------------------------");
-- print("Instruction is " & v_sequ.instruction & " Par1: " & v_sequ.inst_field_1 &
-- " Par2: " & v_sequ.inst_field_2 & " Par3: " & v_sequ.inst_field_3 &
-- " Par4: " & v_sequ.inst_field_4);
-- print("Line Number: " & to_str(v_sequ.line_number) & " File Line Number: " & to_str(v_sequ.file_line) &
-- " File Name: " & v_sequ.file_name);
-- end dump_inst_sequ;
 
-------------------------------------------------------------------------------
-- Procedure to print messages to stdout
procedure print(s: in string) is
variable l: line;
begin
write(l, s);
writeline(output,l);
end print;
 
-------------------------------------------------------------------------------
-- procedure to print to the stdout the txt pointer
procedure txt_print(variable ptr: in stm_text_ptr) is
variable txt_str : stm_text;
begin
if (ptr /= null) then
txt_str := (others => nul);
for i in 1 to c_stm_text_len loop
if (ptr(i) = nul) then
exit;
end if;
txt_str(i) := ptr(i);
end loop;
print(txt_str);
end if;
end txt_print;
 
-------------------------------------------------------------------------------
-- procedure to print to the stdout the txt pointer, and
-- sub any variables found
procedure txt_print_wvar(variable var_list : in var_field_ptr;
variable ptr : in stm_text_ptr;
constant b : in base) is
 
variable i: integer;
variable j: integer;
variable k: integer;
variable txt_str: stm_text;
variable tmp_str: stm_text;
variable v1: integer;
variable valid: integer;
variable tmp_field: text_field;
variable tmp_i: integer;
begin
if(ptr /= null) then
i := 1;
j := 1;
txt_str := (others => nul);
while(i <= c_stm_text_len and j <= c_stm_text_len) loop
if(ptr(i) /= '$') then
txt_str(j) := ptr(i);
i := i + 1;
j := j + 1;
else
tmp_field := (others => nul);
tmp_i := 1;
tmp_field(tmp_i) := ptr(i);
i := i + 1;
tmp_i := tmp_i + 1;
-- parse to the next space
while(ptr(i) /= ' ' and ptr(i) /= nul) loop
tmp_field(tmp_i) := ptr(i);
i := i + 1;
tmp_i := tmp_i + 1;
end loop;
access_variable(var_list,tmp_field,v1,valid);
assert(valid = 1)
report LF & "Invalid Variable found in stm_text_ptr: ignoring."
severity warning;
 
if(valid = 1) then
 
txt_str := ew_str_cat(txt_str, ew_to_str(v1, b));
k := 1;
while(txt_str(k) /= nul) loop
k := k + 1;
end loop;
j := k;
end if;
end if;
end loop;
-- print the created string
print(txt_str);
end if;
end txt_print_wvar;
end tb_pkg;
 
-------------------------------------------------------------------------------
-- Copyright 2011 Ken Campbell
-------------------------------------------------------------------------------
-- $Author: sckoarn $
--
-- $Date: $
--
-- $Id: $
--
-- $Source: $
--
-- Description : The the testbench package body file.
-- GNU release 2 Beta.
--
------------------------------------------------------------------------------
--This file is part of The VHDL Test Bench.
--
-- The VHDL Test Bench is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- The VHDL Test Bench is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with The VHDL Test Bench; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------------
 
package body tb_pkg is
 
-------------------------------------------------------------------------------
-- FUNCTION Defs
-------------------------------------------------------------------------------
-- is_digit
function is_digit(constant c: in character) return boolean is
variable rtn : boolean;
begin
if (c >= '0' and c <= '9') then
rtn := true;
else
rtn := false;
end if;
return rtn;
end is_digit;
--------------------------------------
-- is_space
function is_space(constant c: in character) return boolean is
variable rtn : boolean;
begin
if(c = ' ' or c = ht) then
rtn := true;
else
rtn := false;
end if;
return rtn;
end is_space;
------------------------------------------------------------------------------
-- to_char
function ew_to_char(int: integer) return character is
variable c: character;
begin
c := nul;
case int is
when 0 => c := '0';
when 1 => c := '1';
when 2 => c := '2';
when 3 => c := '3';
when 4 => c := '4';
when 5 => c := '5';
when 6 => c := '6';
when 7 => c := '7';
when 8 => c := '8';
when 9 => c := '9';
when 10 => c := 'A';
when 11 => c := 'B';
when 12 => c := 'C';
when 13 => c := 'D';
when 14 => c := 'E';
when 15 => c := 'F';
when others =>
assert(false)
report LF & "Error: ew_to_char was given a non Number didgit."
severity failure;
end case;
 
return c;
end ew_to_char;
 
-------------------------------------------------------------------------------
-- to_string function integer
function to_str(int: integer) return string is
begin
return ew_to_str(int,dec) ;
end to_str ;
 
-------------------------------------------------------------------------------
-- ew_str_cat
function ew_str_cat(s1: stm_text;
s2: text_field) return stm_text is
 
variable i: integer;
variable j: integer;
variable sc: stm_text;
 
begin
sc := s1;
i := 1;
while(sc(i) /= nul) loop
i := i + 1;
end loop;
j := 1;
while(s2(j) /= nul) loop
sc(i) := s2(j);
i := i + 1;
j := j + 1;
end loop;
 
return sc;
end ew_str_cat;
 
-------------------------------------------------------------------------------
-- fld_len field length
-- inputs : string of type text_field
-- return : integer number of non 'nul' chars
function fld_len(s : in text_field) return integer is
variable i: integer := 1;
begin
while(s(i) /= nul) loop
i := i + 1;
end loop;
return (i - 1);
end fld_len;
------------------------------------------------------------------------------
-- c2int convert character to integer
function c2int(c: in character) return integer is
variable i: integer;
begin
i := -1;
case c is
when '0' => i := 0;
when '1' => i := 1;
when '2' => i := 2;
when '3' => i := 3;
when '4' => i := 4;
when '5' => i := 5;
when '6' => i := 6;
when '7' => i := 7;
when '8' => i := 8;
when '9' => i := 9;
when others =>
assert(false)
report LF & "Error: c2int was given a non Number didgit."
severity failure;
end case;
return i;
end c2int;
-------------------------------------------------------------------------------
-- str2integer Convert a string to integer number.
-- inputs : string
-- output : int value
function str2integer(str: in string) return integer is
variable l: integer;
variable j: integer := 1;
variable rtn: integer := 0;
begin
l := fld_len(str);
 
for i in l downto 1 loop
rtn := rtn + (c2int(str(j)) *(10**(i - 1)));
j := j + 1;
end loop;
 
return rtn;
end str2integer;
-------------------------------------------------------------------------------
-- hex2integer convert hex Stimulus field to integer
-- inputs : string of type text_field containing only Hex numbers
-- return : integer value
function hex2integer(hex_number: in text_field;
file_name: in text_line;
line: in integer) return integer is
variable len: integer;
variable temp_field: text_field;
variable temp_int: integer;
variable power: integer;
variable int_number: integer;
begin
len := fld_len(hex_number);
power := 0;
temp_int := 0;
for i in len downto 1 loop
case hex_number(i) is
when '0' =>
int_number := 0;
when '1' =>
int_number := 1;
when '2' =>
int_number := 2;
when '3' =>
int_number := 3;
when '4' =>
int_number := 4;
when '5' =>
int_number := 5;
when '6' =>
int_number := 6;
when '7' =>
int_number := 7;
when '8' =>
int_number := 8;
when '9' =>
int_number := 9;
when 'a' | 'A'=>
int_number := 10;
when 'b' | 'B'=>
int_number := 11;
when 'c' | 'C'=>
int_number := 12;
when 'd' | 'D'=>
int_number := 13;
when 'e' | 'E'=>
int_number := 14;
when 'f' | 'F'=>
int_number := 15;
when others =>
assert(false)
report LF & "Error: hex2integer found non Hex didgit on line "
& (integer'image(line)) & " of file " & file_name
severity failure;
end case;
 
temp_int := temp_int + (int_number *(16 ** power));
power := power + 1;
end loop;
 
return temp_int;
end hex2integer;
-------------------------------------------------------------------------------
-- convert character to 4 bit vector
-- input character
-- output std_logic_vector 4 bits
function c2std_vec(c: in character) return std_logic_vector is
begin
case c is
when '0' => return "0000";
when '1' => return "0001";
when '2' => return "0010";
when '3' => return "0011";
when '4' => return "0100";
when '5' => return "0101";
when '6' => return "0110";
when '7' => return "0111";
when '8' => return "1000";
when '9' => return "1001";
when 'a' | 'A' => return "1010";
when 'b' | 'B' => return "1011";
when 'c' | 'C' => return "1100";
when 'd' | 'D' => return "1101";
when 'e' | 'E' => return "1110";
when 'f' | 'F' => return "1111";
when others =>
assert(false)
report LF & "Error: c2std_vec found non Hex didgit on file line "
severity failure;
return "XXXX";
end case;
end c2std_vec;
-------------------------------------------------------------------------------
-- std_vec2c convert 4 bit std_vector to a character
-- input std_logic_vector 4 bits
-- output character
function std_vec2c(vec: in std_logic_vector(3 downto 0)) return character is
begin
case vec is
when "0000" => return '0';
when "0001" => return '1';
when "0010" => return '2';
when "0011" => return '3';
when "0100" => return '4';
when "0101" => return '5';
when "0110" => return '6';
when "0111" => return '7';
when "1000" => return '8';
when "1001" => return '9';
when "1010" => return 'A';
when "1011" => return 'B';
when "1100" => return 'C';
when "1101" => return 'D';
when "1110" => return 'E';
when "1111" => return 'F';
when others =>
assert(false)
report LF & "Error: std_vec2c found non-binary didgit in vec "
severity failure;
return 'X';
end case;
end std_vec2c;
-------------------------------------------------------------------------------
-- bin2integer convert bin Stimulus field to integer
-- inputs : string of type text_field containing only binary numbers
-- return : integer value
function bin2integer(bin_number: in text_field;
file_name: in text_line;
line: in integer) return integer is
variable len: integer;
variable temp_field: text_field;
variable temp_int: integer;
variable power: integer;
variable int_number: integer;
begin
len := fld_len(bin_number);
power := 0;
temp_int := 0;
for i in len downto 1 loop
case bin_number(i) is
when '0' =>
int_number := 0;
when '1' =>
int_number := 1;
when others =>
assert(false)
report LF & "Error: bin2integer found non Binary didgit on line "
& (integer'image(line)) & " of file " & file_name
severity failure;
end case;
 
if (int_number = 1) then
temp_int := temp_int + (int_number *(2 ** power));
end if;
power := power + 1;
end loop;
 
return temp_int;
end bin2integer;
-------------------------------------------------------------------------------
-- stim_to_integer convert Stimulus field to integer
-- inputs : string of type text_field "stimulus format of number"
-- return : integer value
function stim_to_integer(field: in text_field;
file_name: in text_line;
line: in integer) return integer is
variable len: integer;
variable value: integer := 1;
variable temp_str : string(1 to 48);
begin
len := fld_len(field);
 
case field(1) is
when 'x' | 'h' =>
value := 2;
while(field(value) /= nul) loop
temp_str(value - 1) := field(value);
value := value + 1;
end loop;
value := hex2integer(temp_str,file_name,line);
when 'b' =>
value := 2;
while(field(value) /= nul) loop
temp_str(value - 1) := field(value);
value := value + 1;
end loop;
value := bin2integer(temp_str,file_name,line);
when others =>
-- value := from_string(field(1 to len));
value := str2integer(field);
end case;
return value;
end stim_to_integer;
 
-------------------------------------------------------------------------------
-- to_str function with base parameter
-- Convert integer to number base
function ew_to_str(int: integer; b: base) return text_field is
 
variable temp : text_field ;
variable temp1 : text_field ;
variable radix : integer := 0;
variable num : integer := 0;
variable power : integer := 1;
variable len : integer := 1;
variable pre : string(1 to 2);
variable i : integer;
variable j : integer;
variable vec : std_logic_vector(31 downto 0);
 
begin
 
num := int;
temp := (others => nul);
case b is
when bin =>
radix := 2; -- depending on what
pre := "0b";
when oct =>
radix := 8; -- base the number is
pre := "0o";
when hex =>
radix := 16; -- to be displayed as
pre := "0x";
when dec =>
radix := 10; -- choose a radix range
pre := (others => nul);
end case ;
-- Now jump through Hoops because of sign
if(num < 0 and b = hex) then
vec := std_logic_vector(conv_unsigned(int, 32));
temp(1) := std_vec2c(vec(31 downto 28));
temp(2) := std_vec2c(vec(27 downto 24));
temp(3) := std_vec2c(vec(23 downto 20));
temp(4) := std_vec2c(vec(19 downto 16));
temp(5) := std_vec2c(vec(15 downto 12));
temp(6) := std_vec2c(vec(11 downto 8));
temp(7) := std_vec2c(vec(7 downto 4));
temp(8) := std_vec2c(vec(3 downto 0));
else
while num >= radix loop -- determine how many
len := len + 1; -- characters required
num := num / radix; -- to represent the
end loop ; -- number.
for i in len downto 1 loop -- convert the number to
temp(i) := ew_to_char(int/power mod radix); -- a string starting
power := power * radix; -- with the right hand
end loop ; -- side.
end if;
-- add prefix if is one
if(pre(1) /= nul) then
temp1 := temp;
i := 1;
j := 3;
temp(1 to 2) := pre;
while(temp1(i) /= nul) loop
temp(j) := temp1(i);
i := i + 1;
j := j + 1;
end loop;
end if;
 
return temp;
 
end ew_to_str ;
 
---------------------------------------------------------------------------------------
-- convert std_logic_vector to an unsigned integer
function to_uninteger ( constant vect : in std_logic_vector
) return integer is
variable result : integer := 0;
variable len : integer := vect'length;
variable idx : integer;
variable tmp_str : text_field;
variable file_name: text_line;
begin
-- point to start of string
idx := 1;
-- convert std_logic_vector to text_field
for i in len - 1 downto 0 loop
if(vect(i) = '1') then
tmp_str(idx) := '1';
elsif(vect(i) = '0') then
tmp_str(idx) := '0';
else
assert(false)
report LF & "ERROR: Non 0/1 value found in std_logic_vector passed to to_uninteger function!!" & LF &
"Returning 0."
severity note;
return result;
end if;
idx := idx + 1;
end loop;
-- call bin txt to int fuction with dummy fn and sequ idx
result := bin2integer(tmp_str, file_name, idx);
return result;
 
end to_uninteger;
 
 
--------------------
-- stm neut
function stm_neut return stm_sctl is
variable tmp : stm_sctl;
begin
tmp.rst_n := '1';
tmp.addr := (others => 'Z');
tmp.wdat := (others => 'Z');
tmp.rwn := 'Z';
tmp.req_n := 'Z';
return tmp;
end stm_neut;
 
function stm_neut return stm_sack is
variable tmp : stm_sack;
begin
tmp.rdat := (others => 'Z');
tmp.ack_n := '1';
tmp.rdy_n := '1';
tmp.irq_n := '1';
return tmp;
end stm_neut;
--------------------------------------------------------------------------------
-- access_variable
-- inputs:
-- Text field containing variable
-- outputs:
-- value $VAR returns Value of VAR
-- value VAR returns index of VAR
--
-- valid is 1 if valid 0 if not
procedure access_variable(variable var_list : in var_field_ptr;
variable var : in text_field;
variable value : out integer;
variable valid : out integer) is
variable l : integer;
variable l_2 : integer;
variable var_ptr : var_field_ptr;
variable temp_field : text_field;
variable ptr : integer := 0; -- 0 is index, 1 is pointer
begin
l := fld_len(var);
valid := 0;
-- if the variable is a special
if(var(1) = '=') then
value := 0;
valid := 1;
elsif(var(1 to 2) = ">=") then
value := 4;
valid := 1;
elsif(var(1 to 2) = "<=") then
value := 5;
valid := 1;
elsif(var(1) = '>') then
value := 1;
valid := 1;
elsif(var(1) = '<') then
value := 2;
valid := 1;
elsif(var(1 to 2) = "!=") then
value := 3;
valid := 1;
 
else
if(var(1) = '$') then
ptr := 1; -- this is a pointer
for i in 2 to l loop
temp_field(i-1) := var(i);
end loop;
else
temp_field := var;
end if;
 
var_ptr := var_list;
while(var_ptr.next_rec /= null) loop
-- if we have a match
if(temp_field = var_ptr.var_name) then
if(ptr = 1) then
value := var_ptr.var_value;
valid := 1;
else
value := var_ptr.var_index;
valid := 1;
end if;
exit;
end if;
var_ptr := var_ptr.next_rec;
end loop;
 
-- if we have a match and was the last record
if(var_ptr.next_rec = null and temp_field = var_ptr.var_name) then
if(ptr = 1) then
value := var_ptr.var_value;
valid := 1;
else
value := var_ptr.var_index;
valid := 1;
end if;
end if;
end if;
end access_variable;
--------------------------------------------------------------------------------
-- index_variable
-- inputs:
-- index: the index of the variable being accessed
-- outputs:
-- Variable Value
-- valid is 1 if valid 0 if not
procedure index_variable(variable var_list : in var_field_ptr;
variable index : in integer;
variable value : out integer;
variable valid : out integer) is
variable ptr: var_field_ptr;
begin
ptr := var_list;
valid := 0;
while(ptr.next_rec /= null) loop
if(ptr.var_index = index) then
value := ptr.var_value;
valid := 1;
exit;
end if;
ptr := ptr.next_rec;
end loop;
if(ptr.var_index = index) then
value := ptr.var_value;
valid := 1;
end if;
end index_variable;
 
--------------------------------------------------------------------------------
-- update_variable
-- inputs:
-- index: the index of the variable being updated
-- outputs:
-- valid is 1 if valid 0 if not
procedure update_variable(variable var_list : in var_field_ptr;
variable index : in integer;
variable value : in integer;
variable valid : out integer) is
variable ptr: var_field_ptr;
begin
ptr := var_list;
valid := 0;
while(ptr.next_rec /= null) loop
if(ptr.var_index = index) then
ptr.var_value := value;
valid := 1;
exit;
end if;
ptr := ptr.next_rec;
end loop;
-- check the current one
if(ptr.var_index = index) then
ptr.var_value := value;
valid := 1;
end if;
end update_variable;
 
-------------------------------------------------------------------------------
-- Read a line from a file
-- inputs : file of type text
-- outputs : The line of type text_line
procedure file_read_line(file file_name: text;
variable file_line: out text_line
) is
variable index: integer; -- index into string
variable rline: line;
 
begin
 
index := 1; -- set index to begin of string
file_line := (others => nul);
if(not endfile(file_name)) then
readline(file_name,rline);
 
while(rline'right /= (index - 1) and rline'length /= 0) loop
file_line(index) := rline(index);
index := index + 1;
end loop;
end if;
end file_read_line;
 
------------------------------------------------------------------------------
-- procedure to break a line down in to text fields
procedure tokenize_line(variable text_line: in text_line;
variable token1: out text_field;
variable token2: out text_field;
variable token3: out text_field;
variable token4: out text_field;
variable token5: out text_field;
variable token6: out text_field;
variable token7: out text_field;
variable txt_ptr: out stm_text_ptr;
variable valid: out integer) is
variable token_index: integer := 0;
variable current_token: text_field;
variable token_number: integer := 0;
variable c: string(1 to 2);
variable comment_found: integer := 0;
variable txt_found: integer := 0;
variable j: integer;
 
begin
-- null outputs
token1 := (others => nul);
token2 := (others => nul);
token3 := (others => nul);
token4 := (others => nul);
token5 := (others => nul);
token6 := (others => nul);
token7 := (others => nul);
txt_ptr := null;
valid := 0;
txt_found := 0;
j := 1;
 
-- loop for max number of char
for i in 1 to text_line'high loop
-- collect for comment test ** assumed no line will be max 256
c(1) := text_line(i);
c(2) := text_line(i + 1); -- or this line will blow up
if(c = "--") then
comment_found := 1;
exit;
end if;
-- if is begin text char '"'
if(c(1) = '"') then --" <-- this double quote is just to fix highlighting.
txt_found := 1;
txt_ptr := new stm_text;
next;
end if;
 
-- if we have found a txt string
if (txt_found = 1 and text_line(i) /= nul) then
-- if string too long, prevent tool hang, truncate and notify
if(j > c_stm_text_len) then
print("tokenize_line: truncated txt line, it was larger than c_stm_text_len");
exit;
end if;
txt_ptr(j) := text_line(i);
j := j + 1;
-- if is a character store in the right token
elsif(is_space(text_line(i)) = false and text_line(i) /= nul) then
token_index := token_index + 1;
current_token(token_index) := text_line(i);
-- else is a space, deal with pointers
elsif(is_space(text_line(i + 1)) = false and text_line(i + 1) /= nul) then
case token_number is
when 0 =>
if(token_index /= 0) then
token1 := current_token;
current_token := (others => nul);
token_number := 1;
valid := 1;
token_index := 0;
end if;
when 1 =>
token2 := current_token;
current_token := (others => nul);
token_number := 2;
valid := 2;
token_index := 0;
when 2 =>
token3 := current_token;
current_token := (others => nul);
token_number := 3;
valid := 3;
token_index := 0;
when 3 =>
token4 := current_token;
current_token := (others => nul);
token_number := 4;
valid := 4;
token_index := 0;
when 4 =>
token5 := current_token;
current_token := (others => nul);
token_number := 5;
valid := 5;
token_index := 0;
when 5 =>
token6 := current_token;
current_token := (others => nul);
token_number := 6;
valid := 6;
token_index := 0;
when 6 =>
token7 := current_token;
current_token := (others => nul);
token_number := 7;
valid := 7;
token_index := 0;
when 7 =>
when others =>
null;
end case;
end if;
-- break from loop if is null
if(text_line(i) = nul) then
if(token_index /= 0) then
case token_number is
when 0 =>
token1 := current_token;
valid := 1;
when 1 =>
token2 := current_token;
valid := 2;
when 2 =>
token3 := current_token;
valid := 3;
when 3 =>
token4 := current_token;
valid := 4;
when 4 =>
token5 := current_token;
valid := 5;
when 5 =>
token6 := current_token;
valid := 6;
when 6 =>
token7 := current_token;
valid := 7;
when others =>
null;
end case;
end if;
exit;
end if;
end loop;
-- did we find a comment and there is a token
if(comment_found = 1) then
if(token_index /= 0) then
case token_number is
when 0 =>
token1 := current_token;
valid := 1;
when 1 =>
token2 := current_token;
valid := 2;
when 2 =>
token3 := current_token;
valid := 3;
when 3 =>
token4 := current_token;
valid := 4;
when 4 =>
token5 := current_token;
valid := 5;
when 5 =>
token6 := current_token;
valid := 6;
when 6 =>
token7 := current_token;
valid := 7;
when others =>
null;
end case;
end if;
end if;
end tokenize_line;
-------------------------------------------------------------------------------
-- Add a new instruction to the instruction list
-- inputs : the linked list of instructions
-- the instruction
-- the number of args
-- outputs : Updated instruction set linked list
procedure define_instruction(variable inst_set: inout inst_def_ptr;
constant inst: in string;
constant args: in integer) is
variable v_inst_ptr: inst_def_ptr;
variable v_prev_ptr: inst_def_ptr;
variable v_new_ptr: inst_def_ptr;
variable v_temp_inst: inst_def_ptr;
variable v_length: integer;
variable v_list_size: integer;
variable v_dup_error: boolean;
 
begin
assert(inst'high <= max_field_len)
report LF & "Error: Creation of Instruction of length greater than Max_field_len attemped!!" &
LF & "This Max is currently set to " & (integer'image(max_field_len))
severity failure;
-- get to the last element and test is not exsiting
v_temp_inst := inst_set;
v_inst_ptr := inst_set;
-- zero the size
v_list_size := 0;
while(v_inst_ptr /= null) loop
-- if there is a chance of a duplicate command
if(v_inst_ptr.instruction_l = inst'high) then
v_dup_error := true;
for i in 1 to inst'high loop
if(v_inst_ptr.instruction(i) /= inst(i)) then
v_dup_error := false;
end if;
end loop;
-- if we find a duplicate, die
assert(v_dup_error = false)
report LF & "Error: Duplicate instruction definition attempted!"
severity failure;
end if;
v_prev_ptr := v_inst_ptr; -- store for pointer updates
v_inst_ptr := v_inst_ptr.next_rec;
v_list_size := v_list_size + 1;
end loop;
 
-- add the new instruction
v_new_ptr := new inst_def;
-- if this is the first command return new pointer
if(v_list_size = 0) then
v_temp_inst := v_new_ptr;
-- else write new pointer to next_rec
else
v_prev_ptr.next_rec := v_new_ptr;
end if;
v_new_ptr.instruction_l := inst'high;
v_new_ptr.params := args;
-- copy the instruction text into field
for i in 1 to v_new_ptr.instruction_l loop
v_new_ptr.instruction(i) := inst(i);
end loop;
-- return the pointer
inst_set := v_temp_inst;
 
end define_instruction;
 
--------------------------------------------------------------------------------
-- Check for valid instruction in the list of instructions
procedure check_valid_inst(variable inst : in text_field;
variable inst_set : in inst_def_ptr;
variable token_num: in integer;
variable line_num : in integer;
variable name : in text_line) is
variable l : integer := 0;
variable seti: inst_def_ptr;
variable match: integer := 0;
variable ilv: integer := 0; -- inline variable
begin
-- create useable pointer
seti := inst_set;
-- count up the characters in inst
l := fld_len(inst);
-- if this is a referance variable -- handle in add variable Proc
if(inst(l) = ':') then
match := 1;
ilv := 1;
else
-- process list till null next
while (seti.next_rec /= null) loop
if(seti.instruction_l = l) then
match := 1;
for j in 1 to l loop
if(seti.instruction(j) /= inst(j)) then
match := 0;
end if;
end loop;
end if;
if(match = 0) then
seti := seti.next_rec;
else
exit;
end if;
end loop;
-- check current one
if(seti.instruction_l = l and match = 0) then
match := 1;
for j in 1 to l loop
if(seti.instruction(j) /= inst(j)) then
match := 0;
end if;
end loop;
end if;
end if;
 
-- if instruction was not found, die
assert(match = 1)
report LF & "Error: Undefined Instruction on line " & (integer'image(line_num)) &
" found in input file " & name & LF
severity failure;
 
-- if the definition of the number of parameters is > 6 skip testing
-- this is how the variable number of parameters is implemented
-- just skip testing for specified number
if(seti.params > 6) then
return;
end if;
-- if we had a match, check the number of paramiters
if(match = 1 and ilv = 0) then
assert(seti.params = (token_num - 1))
report LF & "Error: Undefined Instruction was found, incorrect number of fields passed!" & LF &
"This is found on line " & (integer'image(line_num)) & " in file " & name & LF
severity failure;
end if;
end check_valid_inst;
 
--------------------------------------------------------------------------------
-- add_variable
-- This procedure adds a variable to the variable list. This is localy
-- available at this time.
procedure add_variable(variable var_list : inout var_field_ptr;
variable p1 : in text_field; -- should be var name
variable p2 : in text_field; -- should be value
variable token_num : in integer;
variable sequ_num : in integer;
variable line_num : in integer;
variable name : in text_line;
variable length : in integer) is
 
variable temp_var: var_field_ptr;
variable current_ptr: var_field_ptr;
variable index: integer := 1;
variable len: integer := 0;
 
begin
-- if this is NOT the first one
if(var_list /= null) then
current_ptr := var_list;
index := index + 1;
if(p1(length) /= ':') then -- is not an inline variable
while(current_ptr.next_rec /= null) loop
-- if we have defined the current before then die
assert(current_ptr.var_name /= p1)
report LF & "Error: Attemping to add a duplicate Variable definition "
& " on line " & (integer'image(line_num)) & " of file " & name
severity failure;
 
current_ptr := current_ptr.next_rec;
index := index + 1;
end loop;
-- if we have defined the current before then die. This checks the last one
assert(current_ptr.var_name /= p1)
report LF & "Error: Attemping to add a duplicate Variable definition "
& " on line " & (integer'image(line_num)) & " of file " & name
severity failure;
 
temp_var := new var_field;
temp_var.var_name := p1; -- direct write of text_field
temp_var.var_value := stim_to_integer(p2,name,line_num); -- convert text_field to integer
temp_var.var_index := index;
current_ptr.next_rec := temp_var;
else -- this is an inline variable
while(current_ptr.next_rec /= null) loop
-- if we have defined the current before then die
len := fld_len(current_ptr.var_name);
assert(current_ptr.var_name(1 to len) /= p1(1 to (length - 1)))
report LF & "Error: Attemping to add a duplicate Inline Variable definition "
& " on line " & (integer'image(line_num)) & " of file " & name
severity failure;
 
current_ptr := current_ptr.next_rec;
index := index + 1;
end loop;
-- if we have defined the current before then die. This checks the last one
len := fld_len(current_ptr.var_name);
assert(current_ptr.var_name(1 to len) /= p1(1 to (length - 1)))
report LF & "Error: Attemping to add a duplicate Inline Variable definition "
& " on line " & (integer'image(line_num)) & " of file " & name
severity failure;
 
temp_var := new var_field;
temp_var.var_name(1 to (length - 1)) := p1(1 to (length - 1));
temp_var.var_value := sequ_num;
temp_var.var_index := index;
current_ptr.next_rec := temp_var;
end if;
-- this is the first one
else
if(p1(length) /= ':') then -- is not an inline variable
temp_var := new var_field;
temp_var.var_name := p1; -- direct write of text_field
temp_var.var_index := index;
temp_var.var_value := stim_to_integer(p2,name,line_num); -- convert text_field to integer
var_list := temp_var;
else
temp_var := new var_field;
temp_var.var_name(1 to (length - 1)) := p1(1 to (length - 1));
temp_var.var_value := sequ_num;
temp_var.var_index := index;
var_list := temp_var;
end if;
end if;
end add_variable;
--------------------------------------------------------------------------------
-- add_instruction
-- This is the procedure that adds the instruction to the linked list of
-- instructions. Also Variable addition are called and or handled.
-- the instruction sequence Link list.
-- inputs:
-- stim_line_ptr is the pointer to the instruction List
-- inst is the instruction token
-- p1 paramitor one, corrisponds to field one of stimulus
-- p2 paramitor one, corrisponds to field two of stimulus
-- p3 paramitor one, corrisponds to field three of stimulus
-- p4 paramitor one, corrisponds to field four of stimulus
-- p5 paramitor one, corrisponds to field three of stimulus
-- p6 paramitor one, corrisponds to field four of stimulus
-- str_ptr pointer to string for print instruction
-- token_num the number of tokens, including instruction
-- sequ_num is the stimulus file line referance ie program line number
-- line_num Line number in the text file
-- outputs:
-- none. Error will terminate sim
procedure add_instruction(variable inst_list : inout stim_line_ptr;
variable var_list : inout var_field_ptr;
variable inst : in text_field;
variable p1 : in text_field;
variable p2 : in text_field;
variable p3 : in text_field;
variable p4 : in text_field;
variable p5 : in text_field;
variable p6 : in text_field;
variable str_ptr : in stm_text_ptr;
variable token_num : in integer;
variable sequ_num : inout integer;
variable line_num : in integer;
variable file_name : in text_line;
variable file_idx : in integer) is
variable temp_stim_line: stim_line_ptr;
variable temp_current: stim_line_ptr;
variable valid: integer;
variable l: integer;
begin
valid := 1;
l := fld_len(inst);
temp_current := inst_list;
-- take care of special cases
if(inst(1 to l) = "DEFINE_VAR") then
l := fld_len(p1);
-- Add the variable to the Variable pool, not considered an instruction
add_variable(var_list,p1,p2,token_num,sequ_num,line_num,file_name,l);
valid := 0; --Removes this from the instruction list
elsif(inst(l) = ':') then
add_variable(var_list,inst,p1,token_num,sequ_num,line_num,file_name,l);
valid := 0;
end if;
 
if(valid = 1) then
-- prepare the new record
temp_stim_line := new stim_line;
temp_stim_line.instruction := inst;
temp_stim_line.inst_field_1 := p1;
temp_stim_line.inst_field_2 := p2;
temp_stim_line.inst_field_3 := p3;
temp_stim_line.inst_field_4 := p4;
temp_stim_line.inst_field_5 := p5;
temp_stim_line.inst_field_6 := p6;
temp_stim_line.txt := str_ptr;
temp_stim_line.line_number := sequ_num;
temp_stim_line.file_idx := file_idx;
temp_stim_line.file_line := line_num;
 
-- if is not the first instruction
if(inst_list /= null) then
while(temp_current.next_rec /= null) loop
temp_current := temp_current.next_rec;
end loop;
temp_current.next_rec := temp_stim_line;
inst_list.num_of_lines := inst_list.num_of_lines + 1;
-- other wise is first instruction to be added
else
inst_list := temp_stim_line;
inst_list.num_of_lines := 1;
end if;
sequ_num := sequ_num + 1;
-- print_inst(temp_stim_line); -- for debug
end if;
 
end add_instruction;
------------------------------------------------------------------------------
-- test_inst_sequ
-- This procedure accesses the full instruction sequence and checks for valid
-- variables. This is prior to the simulation run start.
procedure test_inst_sequ(variable inst_sequ : in stim_line_ptr;
variable file_list : in file_def_ptr;
variable var_list : in var_field_ptr
) is
variable temp_text_field: text_field;
variable temp_var: text_field;
variable inst_ptr: stim_line_ptr;
variable valid: integer;
variable line: integer; -- value of the file_line
variable file_name: text_line;
variable v_p: integer;
variable inst : text_field;
variable txt : stm_text_ptr;
variable inst_len : integer;
variable fname : text_line;
variable file_line : integer;
variable temp_fn_prt: file_def_ptr;
variable tmp_int : integer;
 
begin
inst_ptr := inst_sequ;
-- go through all the instructions
while(inst_ptr.next_rec /= null) loop
inst := inst_ptr.instruction;
inst_len := fld_len(inst_ptr.instruction);
file_line := inst_ptr.file_line;
line := inst_ptr.file_line;
-- recover the file name this line came from
temp_fn_prt := file_list;
tmp_int := inst_ptr.file_idx;
while (temp_fn_prt.next_rec /= null) loop
if(temp_fn_prt.rec_idx = tmp_int) then
exit;
end if;
temp_fn_prt := temp_fn_prt.next_rec;
end loop;
for i in 1 to fname'high loop
file_name(i) := temp_fn_prt.file_name(i);
end loop;
 
txt := inst_ptr.txt;
-- load parameter one
temp_text_field := inst_ptr.inst_field_1;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: First variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter two
temp_text_field := inst_ptr.inst_field_2;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Second variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter three
temp_text_field := inst_ptr.inst_field_3;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Third variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter four
temp_text_field := inst_ptr.inst_field_4;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b'or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Forth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter five
temp_text_field := inst_ptr.inst_field_5;
if(temp_text_field(1) /= nul) then
-- if this is a numaric do nothing
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Fifth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter six
temp_text_field := inst_ptr.inst_field_6;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
null;
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,v_p,valid);
assert(valid = 1)
report LF & "Error: Sixth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- point to next record
inst_ptr := inst_ptr.next_rec;
end loop;
 
end test_inst_sequ;
--------------------------------------------------------------------------------
-- The read include file procedure
-- This is the main procedure for reading, parcing, checking and returning
-- the instruction sequence Link list.
procedure read_include_file(variable name: text_line;
variable sequ_numb: inout integer;
variable file_list: inout file_def_ptr;
variable inst_set: inout inst_def_ptr;
variable var_list: inout var_field_ptr;
variable inst_sequ: inout stim_line_ptr;
variable status: inout integer) is
variable l: text_line; -- the line
variable l_num: integer; -- line number file
variable sequ_line: integer; -- line number program
variable t1: text_field;
variable t2: text_field;
variable t3: text_field;
variable t4: text_field;
variable t5: text_field;
variable t6: text_field;
variable t7: text_field;
variable t_txt: stm_text_ptr;
variable valid: integer;
variable v_inst_ptr: inst_def_ptr;
variable v_var_prt: var_field_ptr;
variable v_sequ_ptr: stim_line_ptr;
variable v_len: integer;
variable v_stat: file_open_status;
variable idx: integer;
variable v_tmp: text_line;
 
variable v_tmp_fn_ptr: file_def_ptr;
variable v_new_fn: integer;
variable v_tmp_fn: file_def_ptr;
variable v_txt: stm_text; --stm_text_ptr;
 
begin
sequ_line := sequ_numb;
v_tmp_fn_ptr := file_list;
-- for linux systems, trailing spaces need to be removed
-- from file names
-- copy text string to temp
for i in 1 to c_stm_text_len loop
if(name(i) = nul) then
v_tmp(i) := name(i);
exit;
else
v_tmp(i) := name(i);
end if;
end loop;
--fix up any trailing white space in txt
idx := 0;
-- get to the end of the string
for i in 1 to c_stm_text_len loop
if(v_tmp(i) /= nul) then
idx := idx + 1;
else
exit;
end if;
end loop;
-- now nul out spaces
for i in idx downto 1 loop
if(is_space(v_tmp(i)) = true) then
v_tmp(i) := nul;
else
exit;
end if;
end loop;
-- open include file
file_open(v_stat, include_file, v_tmp, read_mode);
if(v_stat /= open_ok) then
print("Error: Unable to open include file " & name);
status := 1;
return;
end if;
l_num := 1; -- initialize line number
 
-- the file is opened, put it on the file name LL
while (v_tmp_fn_ptr.next_rec /= null) loop
v_tmp_fn_ptr := v_tmp_fn_ptr.next_rec;
end loop;
v_new_fn := v_tmp_fn_ptr.rec_idx + 1;
v_tmp_fn := new file_def;
v_tmp_fn_ptr.next_rec := v_tmp_fn;
v_tmp_fn.rec_idx := v_new_fn;
 
-- nul the text line
v_tmp_fn.file_name := (others => nul);
for i in 1 to name'high loop
v_tmp_fn.file_name(i) := name(i);
end loop;
v_tmp_fn.next_rec := null;
 
 
v_inst_ptr := inst_set;
v_var_prt := var_list;
v_sequ_ptr := inst_sequ;
 
-- while not the end of file read it
while(not endfile(include_file)) loop
file_read_line(include_file,l);
-- tokenize the line
tokenize_line(l,t1,t2,t3,t4,t5,t6,t7,t_txt,valid);
v_len := fld_len(t1);
if(t1(1 to v_len) = "INCLUDE") then
print("Nested INCLUDE statement found in " & v_tmp & " on line " &
(integer'image(l_num)));
assert(false)
report LF & "Error: Nested INCLUDE statements are not supported at this time."
severity failure;
 
-- if there was valid tokens
elsif(valid /= 0) then
check_valid_inst(t1, v_inst_ptr, valid, l_num, name);
add_instruction(v_sequ_ptr,v_var_prt,t1,t2,t3,t4,t5,t6,t7,t_txt,valid,
sequ_line,l_num,name,v_new_fn);
end if;
l_num := l_num + 1;
end loop; -- end loop read file
file_close(include_file);
sequ_numb := sequ_line;
inst_set := v_inst_ptr;
var_list := v_var_prt;
inst_sequ := v_sequ_ptr;
end read_include_file;
 
--------------------------------------------------------------------------------
-- The read instruction file procedure
-- This is the main procedure for reading, parcing, checking and returning
-- the instruction sequence Link list.
procedure read_instruction_file(constant file_name: string;
variable inst_set: inout inst_def_ptr;
variable var_list: inout var_field_ptr;
variable inst_sequ: inout stim_line_ptr;
variable file_list: inout file_def_ptr) is
variable l: text_line; -- the line
variable l_num: integer; -- line number file
variable sequ_line: integer; -- line number program
variable t1: text_field;
variable t2: text_field;
variable t3: text_field;
variable t4: text_field;
variable t5: text_field;
variable t6: text_field;
variable t7: text_field;
variable t_txt: stm_text_ptr;
variable valid: integer;
variable v_ostat: integer;
variable v_inst_ptr: inst_def_ptr;
variable v_var_prt: var_field_ptr;
variable v_sequ_ptr: stim_line_ptr;
variable v_len: integer;
variable v_stat: file_open_status;
variable v_name: text_line;
variable v_iname: text_line;
variable v_tmp_fn: file_def_ptr;
variable v_fn_idx: integer;
variable v_idx: integer;
 
begin
-- open the stimulus_file and check
file_open(v_stat, stimulus, file_name, read_mode);
assert(v_stat = open_ok)
report LF & "Error: Unable to open stimulus_file " & file_name
severity failure;
-- copy file name to type text_line
for i in 1 to file_name'high loop
v_name(i) := file_name(i);
end loop;
-- the first item on the file names link list
file_list := null;
v_tmp_fn := new file_def;
v_tmp_fn.rec_idx := 1;
v_fn_idx := 1;
v_idx := 1;
-- nul the text line
v_tmp_fn.file_name := (others => nul);
for i in 1 to file_name'high loop
v_tmp_fn.file_name(i) := file_name(i);
end loop;
v_tmp_fn.next_rec := null;
 
l_num := 1;
sequ_line := 1;
v_ostat := 0;
 
v_inst_ptr := inst_set;
v_var_prt := var_list;
v_sequ_ptr := inst_sequ;
 
-- while not the end of file read it
while(not endfile(stimulus)) loop
file_read_line(stimulus,l);
-- tokenize the line
tokenize_line(l,t1,t2,t3,t4,t5,t6,t7,t_txt,valid);
v_len := fld_len(t1);
-- if there is an INCLUDE instruction
if(t1(1 to v_len) = "INCLUDE") then
-- if file name is in par2
if(valid = 2) then
v_iname := (others => nul);
for i in 1 to max_field_len loop
v_iname(i) := t2(i);
end loop;
-- elsif the text string is not null
elsif(t_txt /= null) then
v_iname := (others => nul);
for i in 1 to c_stm_text_len loop
v_iname(i) := t_txt(i);
if(t_txt(i) = nul) then
exit;
end if;
end loop;
else
assert(false)
report LF & "Error: INCLUDE instruction has not file name included. Found on" & LF &
"line " & (integer'image(l_num)) & " in file " & file_name & LF
severity failure;
end if;
print("INCLUDE found: Loading file " & v_iname);
read_include_file(v_iname,sequ_line,v_tmp_fn,v_inst_ptr,v_var_prt,v_sequ_ptr,v_ostat);
-- if include file not found
if(v_ostat = 1) then
exit;
end if;
-- if there was valid tokens
elsif(valid /= 0) then
check_valid_inst(t1, v_inst_ptr, valid, l_num, v_name);
add_instruction(v_sequ_ptr,v_var_prt,t1,t2,t3,t4,t5,t6,t7,t_txt,valid,
sequ_line,l_num,v_name,v_fn_idx);
end if;
l_num := l_num + 1;
end loop; -- end loop read file
 
file_close(stimulus); -- close the file when done
 
assert(v_ostat = 0)
report LF & "Include file specified on line " & (integer'image(l_num)) &
" in file " & file_name &
" was not found! Test Terminated" & LF
severity failure;
 
inst_set := v_inst_ptr;
var_list := v_var_prt;
inst_sequ := v_sequ_ptr;
file_list := v_tmp_fn;
 
-- Now that all the stimulus is loaded, test for invalid variables
test_inst_sequ(inst_sequ, v_tmp_fn, var_list);
 
end read_instruction_file;
 
------------------------------------------------------------------------------
-- access_inst_sequ
-- This procedure accesses the instruction sequence and returns the parameters
-- as they exsist related to the variables state.
-- INPUTS: inst_sequ link list of instructions from stimulus
-- var_list link list of variables
-- file_list link list of file names
-- sequ_num the sequence number to recover
--
-- OUTPUTS: inst instruction text
-- p1 paramiter 1 in integer form
-- p2 paramiter 2 in integer form
-- p3 paramiter 3 in integer form
-- p4 paramiter 4 in integer form
-- p5 paramiter 5 in integer form
-- p6 paramiter 6 in integer form
-- txt pointer to any text string of this sequence
-- inst_len the lenth of inst in characters
-- fname file name this sequence came from
-- file_line the line number in fname this sequence came from
--
procedure access_inst_sequ(variable inst_sequ : in stim_line_ptr;
variable var_list : in var_field_ptr;
variable file_list : in file_def_ptr;
variable sequ_num : in integer;
variable inst : out text_field;
variable p1 : out integer;
variable p2 : out integer;
variable p3 : out integer;
variable p4 : out integer;
variable p5 : out integer;
variable p6 : out integer;
variable txt : out stm_text_ptr;
variable inst_len : out integer;
variable fname : out text_line;
variable file_line : out integer;
variable last_num : inout integer;
variable last_ptr : inout stim_line_ptr
) is
variable temp_text_field: text_field;
variable temp_var: text_field;
variable inst_ptr: stim_line_ptr;
variable valid: integer;
variable line: integer; -- value of the file_line
variable file_name: text_line;
variable tmp_int: integer;
variable temp_fn_prt: file_def_ptr;
begin
-- get to the instruction indicated by sequ_num
-- check to see if this sequence is before the last
-- so search from start
if(last_num > sequ_num) then
inst_ptr := inst_sequ;
while(inst_ptr.next_rec /= null) loop
if(inst_ptr.line_number = sequ_num) then
exit;
else
inst_ptr := inst_ptr.next_rec;
end if;
end loop;
-- else is equal or greater, so search forward
else
inst_ptr := last_ptr;
while(inst_ptr.next_rec /= null) loop
if(inst_ptr.line_number = sequ_num) then
exit;
else
inst_ptr := inst_ptr.next_rec;
end if;
end loop;
end if;
 
-- update the last sequence number and record pointer
last_num := sequ_num;
last_ptr := inst_ptr;
 
-- output the instruction and its length
inst := inst_ptr.instruction;
inst_len := fld_len(inst_ptr.instruction);
file_line := inst_ptr.file_line;
line := inst_ptr.file_line;
-- recover the file name this line came from
temp_fn_prt := file_list;
tmp_int := inst_ptr.file_idx;
while (temp_fn_prt.next_rec /= null) loop
if(temp_fn_prt.rec_idx = tmp_int) then
exit;
end if;
temp_fn_prt := temp_fn_prt.next_rec;
end loop;
for i in 1 to fname'high loop --<<<<<<<<<<<<< Fix for file name output Apr 2011.
file_name(i) := temp_fn_prt.file_name(i);
fname(i) := temp_fn_prt.file_name(i);
if(temp_fn_prt.file_name(i) = nul) then
exit;
end if;
end loop;
 
txt := inst_ptr.txt;
-- load parameter one
temp_text_field := inst_ptr.inst_field_1;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p1 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p1 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p1,valid);
assert(valid = 1)
report LF & "Error: First variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter two
temp_text_field := inst_ptr.inst_field_2;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p2 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p2 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p2,valid);
assert(valid = 1)
report LF & "Error: Second variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter three
temp_text_field := inst_ptr.inst_field_3;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p3 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p3 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p3,valid);
assert(valid = 1)
report LF & "Error: Third variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter four
temp_text_field := inst_ptr.inst_field_4;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p4 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p4 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p4,valid);
assert(valid = 1)
report LF & "Error: Forth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter five
temp_text_field := inst_ptr.inst_field_5;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p5 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p5 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p5,valid);
assert(valid = 1)
report LF & "Error: Fifth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
-- load parameter six
temp_text_field := inst_ptr.inst_field_6;
if(temp_text_field(1) /= nul) then
-- if this is a numaric field convert to integer
if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
temp_text_field(1) = 'b') then
p6 := stim_to_integer(temp_text_field,file_name,line);
elsif(is_digit(temp_text_field(1)) = true) then
p6 := stim_to_integer(temp_text_field,file_name,line);
else -- else is a variable, get the value or halt incase of error
access_variable(var_list,temp_text_field,p6,valid);
assert(valid = 1)
report LF & "Error: Sixth variable on stimulus line " & (integer'image(line))
& " is not valid!!" & LF & "In file " & file_name
severity failure;
end if;
end if;
end access_inst_sequ;
 
-------------------------------------------------------------------------------
-- Procedure to print messages to stdout
procedure print(s: in string) is
variable l: line;
begin
write(l, s);
writeline(output,l);
end print;
 
-------------------------------------------------------------------------------
-- procedure to print to the stdout the txt pointer
procedure txt_print(variable ptr: in stm_text_ptr) is
variable txt_str : stm_text;
begin
 
if (ptr /= null) then
txt_str := (others => nul);
for i in 1 to c_stm_text_len loop
if (ptr(i) = nul) then
exit;
end if;
txt_str(i) := ptr(i);
end loop;
print(txt_str);
end if;
end txt_print;
 
-------------------------------------------------------------------------------
-- procedure to print to the stdout the txt pointer, and
-- sub any variables found
procedure txt_print_wvar(variable var_list : in var_field_ptr;
variable ptr : in stm_text_ptr;
constant b : in base) is
 
variable i: integer;
variable j: integer;
variable k: integer;
variable txt_str: stm_text;
variable tmp_str: stm_text;
variable v1: integer;
variable valid: integer;
variable tmp_field: text_field;
variable tmp_i: integer;
 
begin
if(ptr /= null) then
i := 1;
j := 1;
txt_str := (others => nul);
while(i <= c_stm_text_len and j <= c_stm_text_len) loop
if(ptr(i) /= '$') then
txt_str(j) := ptr(i);
i := i + 1;
j := j + 1;
else
tmp_field := (others => nul);
tmp_i := 1;
tmp_field(tmp_i) := ptr(i);
i := i + 1;
tmp_i := tmp_i + 1;
-- parse to the next space
while(ptr(i) /= ' ' and ptr(i) /= nul) loop
tmp_field(tmp_i) := ptr(i);
i := i + 1;
tmp_i := tmp_i + 1;
end loop;
access_variable(var_list,tmp_field,v1,valid);
assert(valid = 1)
report LF & "Invalid Variable found in stm_text_ptr: ignoring."
severity warning;
 
if(valid = 1) then
 
txt_str := ew_str_cat(txt_str, ew_to_str(v1, b));
k := 1;
while(txt_str(k) /= nul) loop
k := k + 1;
end loop;
j := k;
end if;
end if;
end loop;
-- print the created string
print(txt_str);
end if;
end txt_print_wvar;
 
end tb_pkg;
 
-------------------------------------------------------------------------------
-- Revision 1.3
-- Revision History:
-- $Log: not supported by cvs2svn $
-- Revision 1.2 2007/09/02 04:04:04 sckoarn
-- Update of version 1.2 tb_pkg
-- See documentation for details
--
-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn
-- Import of the vhld_tb
-------------------------------------------------------------------------------
/trunk/source/tb_pkg_header.vhd
1,239 → 1,273
-------------------------------------------------------------------------------
-- Copyright 2007 Ken Campbell
-------------------------------------------------------------------------------
-- $Author: sckoarn $
--
-- $Date: 2008-02-24 01:34:11 $
--
-- $Name: not supported by cvs2svn $
--
-- $Id: tb_pkg_header.vhd,v 1.4 2008-02-24 01:34:11 sckoarn Exp $
--
-- $Source: /home/marcus/revision_ctrl_test/oc_cvs/cvs/vhld_tb/source/tb_pkg_header.vhd,v $
--
-- Description : The the testbench package header file.
-- Initial GNU release.
--
------------------------------------------------------------------------------
--This file is part of The VHDL Test Bench.
--
-- The VHDL Test Bench is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- The VHDL Test Bench is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with The VHDL Test Bench; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------------
-- Revision History:
-- $Log: not supported by cvs2svn $
-- Revision 1.3 2007/09/02 04:04:04 sckoarn
-- Update of version 1.2 tb_pkg
-- See documentation for details
--
-- Revision 1.2 2007/08/21 02:43:14 sckoarn
-- Fix package definition to match with body
--
-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn
-- Import of the vhld_tb
--
--
-------------------------------------------------------------------------------
library IEEE;
 
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use std.textio.all;
library ieee_proposed;
use ieee_proposed.STD_LOGIC_1164_additions.all;
 
package tb_pkg is
 
-- Constants
constant max_str_len : integer := 256;
constant max_field_len : integer := 48;
constant c_stm_text_len : integer := 200;
-- file handles
file stimulus : text; -- file main file
file include_file : text; -- file declaration for includes
 
-- Type Def's
type base is (bin, oct, hex, dec);
-- subtype stack_element is integer range 0 to 8192;
type stack_register is array(7 downto 0) of integer;
type state_register is array(7 downto 0) of boolean;
type int_array is array(1 to 16) of integer;
subtype text_line is string(1 to max_str_len);
subtype text_field is string(1 to max_field_len);
subtype stm_text is string(1 to c_stm_text_len);
type stm_text_ptr is access stm_text;
-- define the stimulus line record and access
type stim_line;
type stim_line_ptr is access stim_line; -- Pointer to stim_line record
type stim_line is record
instruction: text_field;
inst_field_1: text_field;
inst_field_2: text_field;
inst_field_3: text_field;
inst_field_4: text_field;
inst_field_5: text_field;
inst_field_6: text_field;
txt: stm_text_ptr;
line_number: integer; -- sequence line
num_of_lines: integer; -- total number of lines
file_line: integer; -- file line number
file_idx: integer;
next_rec: stim_line_ptr;
end record;
-- define the variables field and pointer
type var_field;
type var_field_ptr is access var_field; -- pointer to var_field
type var_field is record
var_name: text_field;
var_index: integer;
var_value: integer;
next_rec: var_field_ptr;
end record;
-- define the instruction structure
type inst_def;
type inst_def_ptr is access inst_def;
type inst_def is record
instruction: text_field;
instruction_l: integer;
params: integer;
next_rec: inst_def_ptr;
end record;
-- define the file handle record
type file_def;
type file_def_ptr is access file_def;
type file_def is record
rec_idx: integer;
file_name: text_line;
next_rec: file_def_ptr;
end record;
---*****************************************************************************
-- Function Declaration
-- function str_len(variable line: text_line) return text_field;
-- function fld_len(s : in text_field) integer;
 
function c2std_vec(c: in character) return std_logic_vector;
--------------------------------------------------------------------------------
-- Procedure declarations
--------------------------------------------------------------------------
-- define_instruction
-- inputs file_name the file to be read from
--
-- output file_line a line of text from the file
procedure define_instruction(variable inst_set: inout inst_def_ptr;
constant inst: in string;
constant args: in integer);
 
--------------------------------------------------------------------------------
-- index_variable
-- inputs:
-- index: the index of the variable being accessed
-- outputs:
-- Variable Value
-- valid is 1 if valid 0 if not
procedure index_variable(variable var_list : in var_field_ptr;
variable index : in integer;
variable value : out integer;
variable valid : out integer);
 
--------------------------------------------------------------------------------
-- update_variable
-- inputs:
-- index: the index of the variable being accessed
-- outputs:
-- Variable Value
-- valid is 1 if valid 0 if not
procedure update_variable(variable var_list : in var_field_ptr;
variable index : in integer;
variable value : in integer;
variable valid : out integer);
 
-------------------------------------------------------------------------------
-- read_instruction_file
-- This procedure reads the instruction file, name passed throught file_name.
-- Pointers to records are passed in and out. A table of variables is created
-- with variable name and value (converted to integer). The instructions are
-- parsesed into the inst_sequ list. Instructions are validated against the
-- inst_set which must have been set up prior to loading the instruction file.
procedure read_instruction_file(constant file_name: string;
variable inst_set: inout inst_def_ptr;
variable var_list: inout var_field_ptr;
variable inst_sequ: inout stim_line_ptr;
variable file_list: inout file_def_ptr);
 
------------------------------------------------------------------------------
-- access_inst_sequ
-- This procedure retreeves an instruction from the sequence of instructions.
-- Based on the line number you pass to it, it returns the instruction with
-- any variables substituted as integers.
procedure access_inst_sequ(variable inst_sequ : in stim_line_ptr;
variable var_list : in var_field_ptr;
variable file_list : in file_def_ptr;
variable sequ_num : in integer;
variable inst : out text_field;
variable p1 : out integer;
variable p2 : out integer;
variable p3 : out integer;
variable p4 : out integer;
variable p5 : out integer;
variable p6 : out integer;
variable txt : out stm_text_ptr;
variable inst_len : out integer;
variable fname : out text_line;
variable file_line : out integer;
variable last_num : inout integer;
variable last_ptr : inout stim_line_ptr
);
------------------------------------------------------------------------
-- tokenize_line
-- This procedure takes a type text_line in and returns up to 6
-- tokens and the count in integer valid, as well if text string
-- is found the pointer to that is returned.
procedure tokenize_line(variable text_line: in text_line;
variable token1: out text_field;
variable token2: out text_field;
variable token3: out text_field;
variable token4: out text_field;
variable token5: out text_field;
variable token6: out text_field;
variable token7: out text_field;
variable txt_ptr: out stm_text_ptr;
variable valid: out integer);
-------------------------------------------------------------------------
-- string convertion
function ew_to_str(int: integer; b: base) return text_field;
function to_str(int: integer) return string;
 
-------------------------------------------------------------------------
-- Procedre print
-- print to stdout string
procedure print(s: in string);
-------------------------------------------------------------------------
-- Procedure print stim txt
procedure txt_print(variable ptr: in stm_text_ptr);
-------------------------------------------------------------------------
-- Procedure print stim txt sub variables found
procedure txt_print_wvar(variable var_list : in var_field_ptr;
variable ptr : in stm_text_ptr;
constant b : in base);
-------------------------------------------------------------------------
-- dump inst_sequ
-- This procedure dumps to the simulation window the current instruction
-- sequence. The whole thing will be dumped, which could be big.
-- ** intended for testbench development debug**
-- procedure dump_inst_sequ(variable inst_sequ : in stim_line_ptr);
end tb_pkg;
-------------------------------------------------------------------------------
-- Copyright 2011 Ken Campbell
-------------------------------------------------------------------------------
-- $Author: sckoarn $
--
-- $Date: $
--
-- $Id: $
--
-- $Source: $
--
-- Description : The the testbench package header file.
-- GNU release 2 Beta.
--
------------------------------------------------------------------------------
--This file is part of The VHDL Test Bench.
--
-- The VHDL Test Bench is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- The VHDL Test Bench is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with The VHDL Test Bench; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------------
library IEEE;
 
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use std.textio.all;
--library ieee_proposed;
--use ieee_proposed.STD_LOGIC_1164_additions.all;
 
package tb_pkg is
 
-- Constants
constant max_str_len : integer := 256;
constant max_field_len : integer := 48;
constant c_stm_text_len : integer := 200;
-- file handles
file stimulus : text; -- file main file
file include_file : text; -- file declaration for includes
 
-- Type Def's
type base is (bin, oct, hex, dec);
-- subtype stack_element is integer range 0 to 8192;
type stack_register is array(7 downto 0) of integer;
type state_register is array(7 downto 0) of boolean;
type int_array is array(1 to 16) of integer;
 
subtype text_line is string(1 to max_str_len);
subtype text_field is string(1 to max_field_len);
subtype stm_text is string(1 to c_stm_text_len);
type stm_text_ptr is access stm_text;
-- define the stimulus line record and access
type stim_line;
type stim_line_ptr is access stim_line; -- Pointer to stim_line record
type stim_line is record
instruction: text_field;
inst_field_1: text_field;
inst_field_2: text_field;
inst_field_3: text_field;
inst_field_4: text_field;
inst_field_5: text_field;
inst_field_6: text_field;
txt: stm_text_ptr;
line_number: integer; -- sequence line
num_of_lines: integer; -- total number of lines
file_line: integer; -- file line number
file_idx: integer;
next_rec: stim_line_ptr;
end record;
-- define the variables field and pointer
type var_field;
type var_field_ptr is access var_field; -- pointer to var_field
type var_field is record
var_name: text_field;
var_index: integer;
var_value: integer;
next_rec: var_field_ptr;
end record;
-- define the instruction structure
type inst_def;
type inst_def_ptr is access inst_def;
type inst_def is record
instruction: text_field;
instruction_l: integer;
params: integer;
next_rec: inst_def_ptr;
end record;
-- define the file handle record
type file_def;
type file_def_ptr is access file_def;
type file_def is record
rec_idx: integer;
file_name: text_line;
next_rec: file_def_ptr;
end record;
 
-- define the stimulus slave control record types
type stm_sctl is record
rst_n : std_logic;
addr : std_logic_vector(31 downto 0);
wdat : std_logic_vector(31 downto 0);
rwn : std_logic;
req_n : std_logic;
end record;
type stm_sack is record
rdat : std_logic_vector(31 downto 0);
ack_n : std_logic;
rdy_n : std_logic;
irq_n : std_logic;
end record;
-- define the stimulus master control record types
type stm_mctl is record
addr : std_logic_vector(31 downto 0);
wdat : std_logic_vector(31 downto 0);
rwn : std_logic;
req_n : std_logic;
breq : std_logic;
end record;
type stm_mack is record
rdat : std_logic_vector(31 downto 0);
slv_rdy : std_logic_vector(15 downto 0);
slv_irq : std_logic_vector(15 downto 0);
ack_n : std_logic;
bgrant : std_logic;
end record;
 
-----
-- stm interface neutral functions
function stm_neut return stm_sctl;
function stm_neut return stm_sack;
--function stm_neut() return stm_mctl;
--function stm_neut() return stm_mack;
 
---*****************************************************************************
-- Function Declaration
-- function str_len(variable line: text_line) return text_field;
-- function fld_len(s : in text_field) integer;
 
function c2std_vec(c: in character) return std_logic_vector;
 
--------------------------------------------------------------------------------
-- Procedure declarations
--------------------------------------------------------------------------
-- define_instruction
-- inputs file_name the file to be read from
--
-- output file_line a line of text from the file
procedure define_instruction(variable inst_set: inout inst_def_ptr;
constant inst: in string;
constant args: in integer);
 
--------------------------------------------------------------------------------
-- index_variable
-- inputs:
-- index: the index of the variable being accessed
-- outputs:
-- Variable Value
-- valid is 1 if valid 0 if not
procedure index_variable(variable var_list : in var_field_ptr;
variable index : in integer;
variable value : out integer;
variable valid : out integer);
 
--------------------------------------------------------------------------------
-- update_variable
-- inputs:
-- index: the index of the variable being accessed
-- outputs:
-- Variable Value
-- valid is 1 if valid 0 if not
procedure update_variable(variable var_list : in var_field_ptr;
variable index : in integer;
variable value : in integer;
variable valid : out integer);
 
-------------------------------------------------------------------------------
-- read_instruction_file
-- This procedure reads the instruction file, name passed throught file_name.
-- Pointers to records are passed in and out. A table of variables is created
-- with variable name and value (converted to integer). The instructions are
-- parsesed into the inst_sequ list. Instructions are validated against the
-- inst_set which must have been set up prior to loading the instruction file.
procedure read_instruction_file(constant file_name: string;
variable inst_set: inout inst_def_ptr;
variable var_list: inout var_field_ptr;
variable inst_sequ: inout stim_line_ptr;
variable file_list: inout file_def_ptr);
 
------------------------------------------------------------------------------
-- access_inst_sequ
-- This procedure retreeves an instruction from the sequence of instructions.
-- Based on the line number you pass to it, it returns the instruction with
-- any variables substituted as integers.
procedure access_inst_sequ(variable inst_sequ : in stim_line_ptr;
variable var_list : in var_field_ptr;
variable file_list : in file_def_ptr;
variable sequ_num : in integer;
variable inst : out text_field;
variable p1 : out integer;
variable p2 : out integer;
variable p3 : out integer;
variable p4 : out integer;
variable p5 : out integer;
variable p6 : out integer;
variable txt : out stm_text_ptr;
variable inst_len : out integer;
variable fname : out text_line;
variable file_line : out integer;
variable last_num : inout integer;
variable last_ptr : inout stim_line_ptr
);
------------------------------------------------------------------------
-- tokenize_line
-- This procedure takes a type text_line in and returns up to 6
-- tokens and the count in integer valid, as well if text string
-- is found the pointer to that is returned.
procedure tokenize_line(variable text_line: in text_line;
variable token1: out text_field;
variable token2: out text_field;
variable token3: out text_field;
variable token4: out text_field;
variable token5: out text_field;
variable token6: out text_field;
variable token7: out text_field;
variable txt_ptr: out stm_text_ptr;
variable valid: out integer);
-------------------------------------------------------------------------
-- string convertion
function ew_to_str(int: integer; b: base) return text_field;
function to_str(int: integer) return string;
 
-------------------------------------------------------------------------
-- Procedre print
-- print to stdout string
procedure print(s: in string);
-------------------------------------------------------------------------
-- Procedure print stim txt
procedure txt_print(variable ptr: in stm_text_ptr);
-------------------------------------------------------------------------
-- Procedure print stim txt sub variables found
procedure txt_print_wvar(variable var_list : in var_field_ptr;
variable ptr : in stm_text_ptr;
constant b : in base);
 
-------------------------------------------------------------------------
-- convert a std_logic_vector to an unsigned integer
function to_uninteger ( constant vect : in std_logic_vector
) return integer;
 
end tb_pkg;
-------------------------------------------------------------------------------
-- new version 1.4
-- Revision History:
-- $Log: not supported by cvs2svn $
-- Revision 1.3 2007/09/02 04:04:04 sckoarn
-- Update of version 1.2 tb_pkg
-- See documentation for details
--
-- Revision 1.2 2007/08/21 02:43:14 sckoarn
-- Fix package definition to match with body
--
-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn
-- Import of the vhld_tb
-------------------------------------------------------------------------------
/trunk/ttb_gen/ttb_gen_plus_2B.tcl
0,0 → 1,1065
#! /usr/bin/env wish
##-------------------------------------------------------------------------------
##-- Copyright 2011 Ken Campbell
##-- All Rights Reserved
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##-------------------------------------------------------------------------------
##-- $Author: $
##--
##-- $Date: $
##--
##-- $Id: $
##--
##-- $Source: $
##--
##-- Description :
##-- This application takes a text file containing the definition of a VHDL
## entity, parses that entity and generates the VHDL Test Bench starting
## file set. It is a rewrite of the previous ttb_gen_gui to include
## view of the file.
## This version has been updated to handle any entity definition
## as well as generating generics found on the target entity.
##--
##------------------------------------------------------------------------------
 
## package requires
package require Iwidgets 4.0
 
## set the current version info
set version "Beta 2.10"
## put up a title on the main window boarder
wm title . "TTB Gen Plus $version"
 
## the location of the template by default
set template "../vhdl/template_tb_bhv.vhd"
 
set use_list 0
 
## Working Directory or vhdl directory
set workd [frame .wdf]
set ent_dir [iwidgets::entryfield $workd.cen1 -labeltext "Working Directory"]
button $workd.br0 -text "Browse" -command {fill_list}
pack $workd.br0 -side right
pack $ent_dir -fill x
pack $workd -fill x -pady 6
 
## Output directory
set tlist [frame .lstf]
set odir [iwidgets::entryfield $tlist.ent1 -labeltext "Output Directory"]
set lbut [button $tlist.br1 -text "Browse" -command {browsed_from_set $odir $odir}]
pack $lbut -side right
pack $odir -fill x
pack $tlist -fill x
 
## Template location
set tdirf [frame .tmpf]
set tdir [iwidgets::entryfield $tdirf.ent2 -width 60 -labeltext "Template Location"]
set tbut [button $tdirf.br2 -text "Browse" -command {browse_set_entry $tdir}]
pack $tbut -side right
pack $tdir -fill x
pack $tdirf -fill x -pady 6
$tdir delete 0 end
$tdir insert end $template
$tdir configure -state readonly
 
## type spec
set tsf [frame .tsfr]
set load_but [button $tsf.bt1 -text "Generate" -command ttb_gen]
set mo_sel [iwidgets::optionmenu $tsf.mode -labeltext "Mode"]
set gbatv 0
set gbat [checkbutton $tsf.chb1 -text "Gen Bat File" -variable gbatv]
set cpakv 0
set cpak [checkbutton $tsf.chb2 -text "Copy Package" -variable cpakv]
##$mo_sel insert end Work Recurse List
$mo_sel insert end "No bhv" "bhv"
set p_view [iwidgets::feedback $tsf.fb1 -labeltext "Generation Status" -barheight 10]
set statsVar ""
##set stat_txt [label $tsf.lb1 -textvariable statsVar]
set stat_txt [label .lb1 -textvariable statsVar]
 
pack $cpak -side left
pack $gbat -side left
pack $mo_sel -side left
pack $load_but -side left -padx 20
pack $p_view -side left
pack $tsf
pack $stat_txt -fill x
 
## create paned window
set win [iwidgets::panedwindow .pw -width 200 -height 300 ]
$win add top -margin 4 -minimum 100
$win add middle -margin 4 -minimum 100
$win configure -orient vertical
$win fraction 80 20
$win paneconfigure 1 -minimum 60
## create two locations for objects
set wtop [$win childsite 0]
set wbot [$win childsite 1]
pack $win -fill both -expand yes
## create two object boxes
set list_win [iwidgets::selectionbox $wtop.sb -margin 2 -itemscommand load_ent_file \
-itemslabel "VHDL Files" -selectionlabel "Selected VHDL File"]
set view_win [iwidgets::scrolledtext $wbot.rts -borderwidth 2 -wrap none]
pack $list_win -fill both -expand yes
pack $view_win -fill both -expand yes
 
## some tags for the view window
##$view_win tag configure highlite -background #a0b7ce
$view_win tag configure highlite -background grey80
 
###########################################################################
## some debug and help procs
## Message Error, terminate
proc msg_error { msg } {
tk_messageBox -message $msg -type ok
exit
}
###########################################################################
## Message, continue
proc dbg_msg { msg } {
tk_messageBox -message $msg -type ok
}
#########################################################################
## browse and get directory
## Using extfileselectiondialog get a directory and update the
## field passed to it
proc browsed_from_set { src dest } {
set wdir [$src get]
if {$wdir == ""} {
iwidgets::extfileselectiondialog .dsb -modality application -fileson false
} else {
iwidgets::extfileselectiondialog .dsb -modality application -fileson false \
-directory $wdir
}
 
if {[.dsb activate]} {
set dchoice [.dsb get]
$dest configure -state normal
$dest delete 0 end
$dest insert 0 "$dchoice"
$dest configure -state readonly
}
destroy .dsb
}
#########################################################################
## browse and get file name
## Using extfileselectiondialog get a directory and update the
## field passed to it
proc browse_set_entry { dest } {
iwidgets::extfileselectiondialog .dsb -modality application
 
if {[.dsb activate]} {
set dchoice [.dsb get]
$dest configure -state normal
$dest delete 0 end
$dest insert 0 "$dchoice"
$dest configure -state readonly
}
destroy .dsb
}
##########################################################################
## proc pars_pindef
proc pars_pindef { pins } {
 
set pdef {}
 
foreach l $pins {
set mps {}
 
set pdirection ""
set spin [split $l ":"]
## if multi pin def
if {[string first "," [lindex $spin 0]] > 0} {
set mpins [split [lindex $spin 0] ","]
foreach p $mpins {
lappend mps [string trim $p]
}
} else {
set mps [string trim [lindex $spin 0]]
}
 
#puts $mps
set ptype_str {}
 
set pdirection_str [string trim [lindex $spin 1]]
#puts $pdirection_str
set p_valid 1
## parce out the direction, supporting only 3
if {[string first "inout" $pdirection_str] == 0} {
set pdirection "inout"
set ptype_str [string trim [string range $pdirection_str 5 end]]
#puts $ptype_str
} elseif {[string first "in" $pdirection_str] == 0} {
set pdirection "in"
set ptype_str [string trim [string range $pdirection_str 2 end]]
#puts $ptype_str
} elseif {[string first "out" $pdirection_str] == 0} {
set pdirection "out"
set ptype_str [string trim [string range $pdirection_str 3 end]]
#puts $ptype_str
} elseif {$pdirection == ""} {
set p_valid 0
set ptype_str {}
#puts $l
#dbg_msg "Unsuported Pin direction found. \n Suported are IN OUT and INOUT."
}
## check for and remove extra )'s
set len [string length $ptype_str]
#puts $len
set len [expr $len - 2]
#puts $len
set tb [string first "(" $ptype_str]
if {$tb >= 0} {
set tb [string first "))" $ptype_str]
if {$tb >= 0} {
set tmp_str [string range $ptype_str 0 $len]
set ptype_str $tmp_str
}
} else {
set tb [string first ")" $ptype_str]
if {$tb >= 0} {
set tmp_str [string range $ptype_str 0 $len]
set ptype_str $tmp_str
}
}
## if we have a valid pin def add one or more
if {$p_valid == 1} {
foreach p $mps {
set def {}
lappend def $p $pdirection $ptype_str
lappend pdef $def
}
}
}
#puts $pdef
# lappend pdef $pname $pdirection $ptype
return $pdef
}
## end pars_pindef
 
##########################################################################
## proc pars_gendef
proc pars_gendef { gens } {
 
set gdef {}
foreach l $gens {
set mgs {}
set sgen [split $l ":"]
## if multi gen def
if {[string first "," [lindex $sgen 0]] > 0} {
set mgens [split [lindex $sgen 0] ","]
foreach p $mgens {
lappend mgs [string trim $p]
}
} else {
set mgs [string trim [lindex $sgen 0]]
}
#puts $mgs
set gtype_str [string trim [lindex $sgen 1]]
foreach p $mgs {
set def {}
lappend def $p $gtype_str
lappend gdef $def
}
}
#puts $gdef
return $gdef
}
## end pars_gendef
 
##--------------------------------------------------------------------------------
## Write header to file passed
proc write_header { handle } {
global version
##global scan_date
set raw_date [clock scan now]
set scan_date [clock format $raw_date -format "%d %b %Y %T"]
 
## so CVS will not modify selections, they have to be chopped up
set auth "-- \$Auth"
append auth "or: \$"
set cvs_date "-- \$dat"
append cvs_date "e: \$"
set cvs_name "-- \$Nam"
append cvs_name "e: \$"
set cvs_id "-- \$I"
append cvs_id "d: \$"
set cvs_source "-- \$Sour"
append cvs_source "ce: \$"
set cvs_log "-- \$Lo"
append cvs_log "g: \$"
 
puts $handle "-------------------------------------------------------------------------------"
puts $handle "-- Copyright -----------------------------------"
puts $handle "-- All Rights Reserved"
puts $handle "-------------------------------------------------------------------------------"
puts $handle "$auth"
puts $handle "--"
puts $handle "$cvs_date"
puts $handle "--"
puts $handle "$cvs_id"
puts $handle "--"
puts $handle "$cvs_source"
puts $handle "--"
puts $handle "-- Description :"
puts $handle "-- This file was generated by TTB Gen Plus $version"
puts $handle "-- on $scan_date"
puts $handle "------------------------------------------------------------------------------"
puts $handle "-- This software contains concepts confidential to ----------------"
puts $handle "-- ---------. and is only made available within the terms of a written"
puts $handle "-- agreement."
puts $handle "-------------------------------------------------------------------------------"
puts $handle "-- Revision History:"
puts $handle "$cvs_log"
puts $handle "--"
puts $handle "-------------------------------------------------------------------------------"
puts $handle ""
}
 
##########################################################################
## write Library and use statements
proc write_lib_statements { handle } {
puts $handle "library IEEE;"
puts $handle "--library tb_pkg;"
puts $handle "--possible users libs;"
puts $handle "use IEEE.STD_LOGIC_1164.all;"
puts $handle "use IEEE.STD_LOGIC_ARITH.all;"
puts $handle "use std.textio.all;"
puts $handle "use work.tb_pkg.all;"
puts $handle "--possible users use statement;"
puts $handle "--library synthworks;"
puts $handle "-- use SynthWorks.RandomBasePkg.all; "
puts $handle "-- use SynthWorks.RandomPkg.all;"
puts $handle ""
}
 
#####################################################################
## A directory has been selected now fill the list win with VHDL files
proc fill_list {} {
global ent_dir odir
global tlist_ent use_list list_win ts_ent statsVar
global view_win mo_sel
 
## get the user selection
browsed_from_set $ent_dir $ent_dir
## as a default make output dir = input dir
set tmp_dir [$ent_dir get]
$odir delete 0 end
$odir insert end $tmp_dir
$odir configure -state readonly
 
## clear the list window and selection
$list_win clear items
$list_win clear selection
$view_win clear
## get the working directory
set dir [$ent_dir get]
## get the list of VHDL files in working directory
set ftype ".vhd*"
set file_lst ""
set file_lst [glob -directory $dir *$ftype]
 
##puts $file_lst
 
## for each of the files in the file_lst
foreach l $file_lst {
## creat string that is just the file name: no path
set testt $l
set nstart [string last "/" $l]
incr nstart
set name_str [string range $l $nstart end]
## insert item on list
$list_win insert items 1 $name_str
}
}
 
######################################################################
## load the vhdl file that has just been selected from list_win
proc load_ent_file {} {
global ent_dir list_win view_win statsVar
 
## update selection with selected item
$list_win selectitem
set sel_dx [$list_win curselection]
if {$sel_dx == ""} {
return
}
## recover the selected item
set ln [$list_win get]
## Get the working directory
#puts $ln
set lp [$ent_dir get]
## append the file name
append lp "/" $ln
## if the file does not exist return
set fexist [file exist $lp]
if {$fexist == 0} {
return
}
set ent_file [open $lp r]
## clear the view_win
$view_win clear
set file_list {}
## load file to memory
while {![eof $ent_file]} {
## Get a line
set rline [gets $ent_file]
lappend file_list $rline
}
close $ent_file
## put file in text window and highlite the entity part
set ent_found 0
set in_ent 0
set statsVar ""
foreach l $file_list {
if {$in_ent == 0} {
set ent_def [string first entity $l]
set ent_is [string first is $l]
if {$ent_def >= 0 && $ent_is >= 0} {
set ent_name [lindex $l 1]
set statsVar "Entity $ent_name found"
set ent_found 1
set in_ent 1
$view_win insert end "$l\n" highlite
} else {
$view_win insert end "$l\n"
}
} else {
set ent_def [string first "end $ent_name" $l]
set ent2_def [string first "end\;" $l]
if {$ent_def >= 0 || $ent2_def >= 0} {
set end_name [lindex $l 1]
set end_found 1
set in_ent 0
$view_win insert end "$l\n" highlite
} elseif {[string first "end entity $ent_name" $l] >= 0} {
set end_name [lindex $l 1]
set end_found 1
set in_ent 0
$view_win insert end "$l\n" highlite
} else {
$view_win insert end "$l\n" highlite
}
}
}
if {$ent_found == 0} {
set statsVar "No Entity found!!"
}
##$view_win import $lp
##$view_win yview moveto 1
##puts $lp
}
 
#########################################################################
proc ttb_gen {} {
global mo_sel template ent_dir list_win odir p_view tdir
global cpakv gbatv
 
set template [$tdir get]
 
$p_view configure -steps 7
$p_view reset
## recover the selected item
set ln [$list_win get]
## Get the working directory
#puts $ln
set lp [$ent_dir get]
## append the file name
append lp "/" $ln
 
set path_text $lp
set destin_text [$odir get]
set infile [open $path_text r]
set file_list list
 
set tmpcnt 0
 
##################################################################
## Read in the file and strip comments as we do
while {![eof $infile]} {
## Get a line
set rline [gets $infile]
## get rid of white space
set rline [string trim $rline]
## Find comment if there
set cindex [string first -- $rline]
## if a comment was found at the start of the line
if {$cindex == 0 || $rline == ""} {
set rline [string range $rline 0 [expr $cindex - 1]]
##dbg_msg $rline
if {[llength $rline] > 0} {
lappend file_list [string tolower $rline]
}
## else was not found so put line in list
} else {
if {$cindex > 0} {
# get rid of trailing comments and trim off spaces
set rline [string trim [string range $rline 0 $cindex-1]]
##puts $rline
}
lappend file_list [string tolower $rline]
}
incr tmpcnt
}
$p_view step
## collect the library statements
foreach l $file_list {
set libpos [string first library $l]
if {$libpos >= 0} {
lappend libs_list $l
}
}
## collect the use statements
foreach l $file_list {
set usepos [string first use $l]
if {$usepos >= 0} {
lappend use_list $l
}
}
## check for the entity def
set ent_found 0
foreach l $file_list {
set ent_def [string first entity $l]
if {$ent_def >= 0} {
set ent_name [lindex $l 1]
break
}
}
## if no ent die
if {$ent_def < 0} {
dbg_msg "An entity definition was not found in the file provided."
## exit
}
$p_view step
## check for end entity
foreach l $file_list {
lappend ent_list $l
set end_def [string first end $l]
if {$end_def >= 0} {
set end_ent [string first "end $ent_name" $l]
if {$end_ent >= 0} {
break
}
set end_ent [string first "end\;" $l]
if {$end_ent >= 0} {
break
}
set end_ent [string first "end entity $ent_name" $l]
if {$end_ent >= 0} {
break
}
}
}
## if no end die
if {$end_def < 0} {
dbg_msg "no end statement found for this entity"
## exit
}
 
####
## collect the generic if there is one.
set generic_list {}
set generic_found 0
foreach l $ent_list {
if {$generic_found == 0} {
set gfound [string first generic $l]
if {$gfound >= 0} {
set generic_found 1
set line_test [split $l "("]
if {[llength $line_test] > 1} {
set generic_list [lindex $line_test 1]
}
}
} elseif {[string first ");" $l]} {
set line_test [split $l ")"]
if {[llength $line_test] > 1} {
append generic_list [lindex $line_test 0]
}
break
} else {
append generic_list $l
}
}
## split into a list
if {$generic_found == 1} {
set generic_list [split $generic_list ";"]
}
##puts $generic_list
set gen_lst [pars_gendef $generic_list]
 
set port_found 0
####################################################################
## a few checks have been done, and non-relevant stuff stripped off.
## now create an arrry of just the pin names and related info
set port_list {}
foreach l $ent_list {
## look for the port statement
# get rid of comments and trim off spaces
##set cs [split $l "--"]
##set l [string trim [lindex $cs 0]]
if {$port_found == 0} {
set pfound [string first port $l]
## found one now check if there is a pin def in the same line
if {$pfound >= 0} {
set port_found 1
set efound [string first : $l]
if {$efound >= 0} {
set line_test [split $l "("]
if {[llength $line_test] > 1} {
## first port so set
set port_list [lindex $line_test 1]
}
}
}
} else {
append port_list $l
}
}
##puts $port_list
set port_list [split $port_list ";"]
##puts $port_list
## Change the port list into a pin info list
set split_pin [pars_pindef $port_list]
 
# dbg_msg $split_pin
## calculate the longest pin name in characters
set name_length 0
foreach l $split_pin {
set temp_length [string length [lindex $l 0]]
if {$temp_length > $name_length} {
set name_length $temp_length
}
}
#dbg_msg $name_length
## Make the name length one bigger
incr name_length
 
$p_view step
#########################################################################
## Generate the test bench entity.
## Create the file name
set file_type "_tb_ent.vhd"
set ent_file_name $destin_text
append ent_file_name "/" $ent_name $file_type
# dbg_msg $ent_file_name
## Create the tb entity name
set tb_ent_name $ent_name
set tb_sufix "_tb"
append tb_ent_name $tb_sufix
 
## open and write the header
set ent_file [open $ent_file_name w+]
write_header $ent_file
 
## write out Library and use statements
write_lib_statements $ent_file
 
puts $ent_file "entity $tb_ent_name is"
puts $ent_file " generic ("
puts $ent_file " stimulus_file: in string"
puts $ent_file " )\;"
puts $ent_file " port ("
 
##-----------------------------------------
# for each pin in the list output the TB ent pin
set plist_size [llength $split_pin]
#dbg_msg $plist_size
set i 1
foreach l $split_pin {
set pdirection [lindex $l 1]
# puts $pdirection
## switch on the source pin direction
switch -exact $pdirection {
"in" {set tb_ptype "buffer"}
"out" {set tb_ptype "in"}
"inout" {set tb_ptype "inout"}
default {
msg_error "Should have not got here .. pin direction in entity creation!!"
}
}
## creat some formats for appending
set new_pname [format " %-${name_length}s" [lindex $l 0]]
set new_ptype [format ": %-8s" $tb_ptype]
if {$i != $plist_size} {
append new_pname $new_ptype [lindex $l 2] ";"
} else {
append new_pname $new_ptype [lindex $l 2]
}
puts $ent_file $new_pname
incr i
}
 
puts $ent_file " )\;"
puts $ent_file "end $tb_ent_name;"
close $ent_file
 
$p_view step
##################################################################
## Generate the top level test bench entity
## Create the file name
set file_type "_ttb_ent.vhd"
set ent_file_name $destin_text
append ent_file_name "/" $ent_name $file_type
# dbg_msg $ent_file_name
## Create the tb entity name
set ttb_ent_name $ent_name
set ttb_sufix "_ttb"
append ttb_ent_name $ttb_sufix
 
## open and write the header
set ttb_ent_file [open $ent_file_name w+]
write_header $ttb_ent_file
 
puts $ttb_ent_file "library IEEE;"
puts $ttb_ent_file "--library dut_lib;"
puts $ttb_ent_file "use IEEE.STD_LOGIC_1164.all;"
puts $ttb_ent_file "--use dut_lib.all;"
puts $ttb_ent_file ""
puts $ttb_ent_file "entity $ttb_ent_name is"
puts $ttb_ent_file " generic ("
puts $ttb_ent_file " stimulus_file: string := \"stm/stimulus_file.stm\""
puts $ttb_ent_file " )\;"
puts $ttb_ent_file "end $ttb_ent_name\;"
 
close $ttb_ent_file
 
$p_view step
#################################################################
## Generate the top level structure
## Create the file name
set file_type "_ttb_str.vhd"
set str_file_name $destin_text
append str_file_name "/" $ent_name $file_type
# dbg_msg $ent_file_name
## Create the tb entity name
set ttb_ent_name $ent_name
set ttb_sufix "_ttb"
append ttb_ent_name $ttb_sufix
 
## open and write the header
set ttb_str_file [open $str_file_name w+]
write_header $ttb_str_file
 
puts $ttb_str_file ""
puts $ttb_str_file "architecture struct of $ttb_ent_name is"
puts $ttb_str_file ""
puts $ttb_str_file "component $ent_name"
## if there is generic parts to entity
if {$generic_found == 1} {
set len [llength $gen_lst]
set cnt 0
puts $ttb_str_file "-- generic ("
foreach g $gen_lst {
incr cnt
set gline "-- "
append gline [lindex $g 0] " : " [lindex $g 1]
if {$cnt != $len} {
append gline "\;"
}
puts $ttb_str_file $gline
}
puts $ttb_str_file "-- )\;"
}
 
puts $ttb_str_file " port ("
## put out the dut component def
###################################################
# for each pin in the list output the TB ent pin
set i 1
foreach l $split_pin {
## creat some formats for appending
set new_pname [format " %-${name_length}s" [lindex $l 0]]
set new_ptype [format ": %-8s" [lindex $l 1]]
if {$i != $plist_size} {
append new_pname $new_ptype [lindex $l 2] ";"
} else {
append new_pname $new_ptype [lindex $l 2]
}
puts $ttb_str_file $new_pname
incr i
}
puts $ttb_str_file " )\;"
puts $ttb_str_file "end component\;"
 
puts $ttb_str_file ""
puts $ttb_str_file "component $tb_ent_name"
puts $ttb_str_file " generic ("
puts $ttb_str_file " stimulus_file: in string"
puts $ttb_str_file " )\;"
puts $ttb_str_file " port ("
## put out the tb component def
####################################################
# for each pin in the list output the TB ent pin
set i 1
foreach l $split_pin {
set pdirection [lindex $l 1]
# dbg_msg $pdirection
## switch on the source pin direction
switch -exact $pdirection {
"in" {set tb_ptype "buffer"}
"out" {set tb_ptype "in"}
"inout" {set tb_ptype "inout"}
default {
msg_error "Should have not got here .. pin direction in entity creation!!"
}
}
## creat some formats for appending
set new_pname [format " %-${name_length}s" [lindex $l 0]]
set new_ptype [format ": %-8s" $tb_ptype]
if {$i != $plist_size} {
append new_pname $new_ptype [lindex $l 2] ";"
} else {
append new_pname $new_ptype [lindex $l 2]
}
puts $ttb_str_file $new_pname
incr i
}
puts $ttb_str_file " )\;"
puts $ttb_str_file "end component\;"
puts $ttb_str_file ""
 
puts $ttb_str_file "--for all: $ent_name use entity dut_lib.$ent_name\(str)\;"
puts $ttb_str_file "for all: $tb_ent_name use entity work.$tb_ent_name\(bhv)\;"
 
puts $ttb_str_file ""
#####################################################
# for each pin in the list output the TB ent pin
# generate a signal name
foreach l $split_pin {
## creat some formats for appending
set new_pname [format " signal temp_%-${name_length}s" [lindex $l 0]]
append new_pname ": " [lindex $l 2] ";"
puts $ttb_str_file $new_pname
}
 
puts $ttb_str_file ""
puts $ttb_str_file "begin"
puts $ttb_str_file ""
puts $ttb_str_file "dut: $ent_name"
## if there is generic parts to entity
if {$generic_found == 1} {
set len [llength $gen_lst]
set cnt 0
puts $ttb_str_file "-- generic map("
foreach g $gen_lst {
incr cnt
set gline "-- "
append gline [lindex $g 0] " => "
puts $ttb_str_file $gline
}
puts $ttb_str_file "-- )"
dbg_msg "A generic map was generated for\nthe DUT, but commented out \
\nThe user will have to complete\nthis section of the code in the\n \
ttb_str file."
}
 
puts $ttb_str_file " port map("
##-----------------------------------------
# for each pin in the list output the TB ent pin
# Generate port map for DUT
set i 1
foreach l $split_pin {
## creat some formats for appending
set new_pname [format " %-${name_length}s" [lindex $l 0]]
if {$i != $plist_size} {
append new_pname "=> temp_" [lindex $l 0] ","
} else {
append new_pname "=> temp_" [lindex $l 0]
}
puts $ttb_str_file $new_pname
incr i
}
 
puts $ttb_str_file " )\;"
puts $ttb_str_file ""
puts $ttb_str_file "tb: $tb_ent_name"
puts $ttb_str_file " generic map("
puts $ttb_str_file " stimulus_file => stimulus_file"
puts $ttb_str_file " )"
puts $ttb_str_file " port map("
##-----------------------------------------
# for each pin in the list output the TB ent pin
# Generate port map for DUT
set i 1
foreach l $split_pin {
## creat some formats for appending
set new_pname [format " %-${name_length}s" [lindex $l 0]]
if {$i != $plist_size} {
append new_pname "=> temp_" [lindex $l 0] ","
} else {
append new_pname "=> temp_" [lindex $l 0]
}
puts $ttb_str_file $new_pname
incr i
}
 
puts $ttb_str_file " )\;"
puts $ttb_str_file ""
puts $ttb_str_file "end struct\;"
close $ttb_str_file
 
######################################################################
## Now generate the bhv file from template
 
if {[$mo_sel get] == "bhv"} {
 
$p_view step
set infile [open "$template" r]
 
while {![eof $infile]} {
## Get a line
set rline [gets $infile]
lappend temp_file_list $rline
}
close $infile
 
## strip off the header
set end_header 0
foreach l $temp_file_list {
set comment [string first -- $l]
if {$comment < 0} {
set end_header 1
}
## if we found the end of the header
if {$end_header == 1} {
lappend template_list $l
}
}
 
## split the file into two peices, to the point of input initialization
set i 1
foreach l $template_list {
## check for parsing point
set mid_point [string first parse_tb1 $l]
if {$mid_point >= 0} {
break
}
 
if {$i > 2} {
lappend top_half $l
}
incr i
}
 
set found 0
foreach l $template_list {
if {$found == 1} {
lappend bottom_half $l
}
## check for parsing point
set mid_point [string first parse_tb1 $l]
if {$mid_point >= 0} {
set found 1
}
}
 
## Create the file name
set file_type "_tb_bhv.vhd"
set bhv_file_name $destin_text
append bhv_file_name "/" $ent_name $file_type
# dbg_msg $ent_file_name
 
## open and write the header
set bhv_file [open $bhv_file_name w+]
write_header $bhv_file
 
puts $bhv_file ""
puts $bhv_file "architecture bhv of $tb_ent_name is"
puts $bhv_file ""
foreach l $top_half {
puts $bhv_file $l
}
 
puts $bhv_file ""
## now generate and write out input initialization
foreach l $split_pin {
set temp_def [lindex $l 1]
set input_def [string first in $temp_def]
if {$input_def >= 0} {
set vector [string first vector $l]
set init_def [format " %-${name_length}s" [lindex $l 0]]
if {$vector >= 0} {
append init_def "<= (others => '0')\;"
} else {
append init_def "<= '0'\;"
}
puts $bhv_file $init_def
}
}
puts $bhv_file ""
## now write out the bottem half and termination
foreach l $bottom_half {
puts $bhv_file $l
}
 
close $bhv_file
}
## generate the
if {$gbatv == 1} {
set fn $destin_text
append fn "\\build_tb.bat"
set batf [open $fn w+]
 
puts $batf "ECHO OFF"
puts $batf ""
puts $batf "vlib work"
puts $batf "vcom -quiet tb_pkg_header.vhd tb_pkg_body.vhd"
set str {}
append str "vcom -2008 -quiet " $ent_name "_tb_ent.vhd " $ent_name "_tb_bhv.vhd"
puts $batf $str
set str {}
append str "vcom -quiet " $ent_name "_ttb_ent.vhd " $ent_name "_ttb_str.vhd"
puts $batf $str
puts $batf ""
 
close $batf
}
 
## put out a terminating message for the user
dbg_msg "Test bench files were generated in directory:\n $destin_text"
$p_view step
 
if {$cpakv == 1} {
## set avail [file exists "../vhdl/tb_pkg_header.vhd"]
set avail [file exists "../vhdl/tb_pkg_header.vhd"]
if {$avail < 1} {
dbg_msg "The package files are not located in the\n expected location. \nThey were not copied."
}
 
set dest $destin_text
append dest "/tb_pkg_header.vhd"
if {[file exists $dest] == 0} {
file copy "../vhdl/tb_pkg_header.vhd" $dest
}
set dest $destin_text
append dest "/tb_pkg_body.vhd"
if {[file exists $dest] == 0} {
file copy "../vhdl/tb_pkg_body.vhd" $dest
}
}
}
## end ttb_gen
## enable pop up console for debug
bind . <F12> {catch {console show}}
##catch {console show}
##-------------------------------------------------------------------------------
##-- Revision History:
##-- $Log: not supported by cvs2svn $
##--
##-- Jul 23 2011
##-- Fix trailing inline comments error.
##-- version now 2.02
##----------------------------------------------------------------------------
/trunk/Doc/VHDLtbusers.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
trunk/Doc/VHDLtbusers.pdf Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: trunk/Doc/VHDLtbusers.odt =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/Doc/VHDLtbusers.odt =================================================================== --- trunk/Doc/VHDLtbusers.odt (nonexistent) +++ trunk/Doc/VHDLtbusers.odt (revision 19)
trunk/Doc/VHDLtbusers.odt Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/examples/packet_gen/data.dat =================================================================== --- trunk/examples/packet_gen/data.dat (nonexistent) +++ trunk/examples/packet_gen/data.dat (revision 19) @@ -0,0 +1,243 @@ +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +1a +1b +1c +1d +1e +1f +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +2a +2b +2c +2d +2e +2f +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +3a +3b +3c +3d +3e +3f +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +44 +4b +4c +4d +4e +4f +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +5a +5b +5c +5d +5e +5f +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +6a +6b +6c +6d +6e +6f +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +7a +7b +7c +7d +7e +7f +12 +23 +34 +45 +56 +67 +78 +89 +ab +cd +ef +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +8a +8b +8c +8d +8e +8f Index: trunk/examples/packet_gen/stm/stimulus_file.stm =================================================================== --- trunk/examples/packet_gen/stm/stimulus_file.stm (nonexistent) +++ trunk/examples/packet_gen/stm/stimulus_file.stm (revision 19) @@ -0,0 +1,55 @@ + +DEFINE_VAR ADDR x01000 +DEFINE_VAR DATA 0 +DEFINE_VAR CONTROL 0 +DEFINE_VAR CONFIG 1 +DEFINE_VAR ENABLE 1 +DEFINE_VAR OPEN_FILE_TRIGGER 3 +DEFINE_VAR RANDOM 1 +DEFINE_VAR LOAD_FROM_FILE 2 +DEFINE_VAR USER 3 + + +RESET_SYS + +WRITE_STM $CONTROL $ENABLE + +REQUEST +WRITE_STM $CONFIG $RANDOM + +REQUEST +SET_FN "data.dat +WRITE_STM $CONTROL $OPEN_FILE_TRIGGER + +WRITE_STM $CONFIG $LOAD_FROM_FILE + +REQUEST + +REQUEST + +LOOP 128 + WRITE_STM $ADDR $DATA + ADD_VAR DATA x011 + ADD_VAR ADDR 1 +END_LOOP + +WRITE_STM $ADDR $DATA -- out of bounds write + +WRITE_STM $CONFIG $USER + +REQUEST + + +TEST_INST $DATA +TEST_INST $DATA $DATA +TEST_INST $DATA $DATA $DATA +TEST_INST $DATA $DATA $DATA $DATA +TEST_INST $DATA $DATA $DATA $DATA $DATA +TEST_INST $DATA $DATA $DATA $DATA $DATA $DATA +TEST_INST +TEST_INST $DATA +TEST_INST $DATA $DATA $DATA $DATA $DATA $DATA $DATA + + + +FINISH Index: trunk/examples/packet_gen/vsim.wlf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/examples/packet_gen/vsim.wlf =================================================================== --- trunk/examples/packet_gen/vsim.wlf (nonexistent) +++ trunk/examples/packet_gen/vsim.wlf (revision 19)
trunk/examples/packet_gen/vsim.wlf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/examples/packet_gen/modelsim.ini =================================================================== --- trunk/examples/packet_gen/modelsim.ini (nonexistent) +++ trunk/examples/packet_gen/modelsim.ini (revision 19) @@ -0,0 +1,1614 @@ +; Copyright 1991-2011 Mentor Graphics Corporation +; +; All Rights Reserved. +; +; THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS THE PROPERTY OF +; MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS SUBJECT TO LICENSE TERMS. +; + +[Library] +ieee_proposed = work +tb_pkg = work +std = $MODEL_TECH/../std +ieee = $MODEL_TECH/../ieee +vital2000 = $MODEL_TECH/../vital2000 +; +; VITAL concerns: +; +; The library ieee contains (among other packages) the packages of the +; VITAL 2000 standard. When a design uses VITAL 2000 exclusively, it should use +; the physical library ieee (recommended), or use the physical library +; vital2000, but not both. The design can use logical library ieee and/or +; vital2000 as long as each of these maps to the same physical library, either +; ieee or vital2000. +; +; A design using the 1995 version of the VITAL packages, whether or not +; it also uses the 2000 version of the VITAL packages, must have logical library +; name ieee mapped to physical library vital1995. (A design cannot use library +; vital1995 directly because some packages in this library use logical name ieee +; when referring to the other packages in the library.) The design source +; should use logical name ieee when referring to any packages there except the +; VITAL 2000 packages. Any VITAL 2000 present in the design must use logical +; name vital2000 (mapped to physical library vital2000) to refer to those +; packages. +; ieee = $MODEL_TECH/../vital1995 +; +; For compatiblity with previous releases, logical library name vital2000 maps +; to library vital2000 (a different library than library ieee, containing the +; same packages). +; A design should not reference VITAL from both the ieee library and the +; vital2000 library because the vital packages are effectively different. +; A design that references both the ieee and vital2000 libraries must have +; both logical names ieee and vital2000 mapped to the same library, either of +; these: +; $MODEL_TECH/../ieee +; $MODEL_TECH/../vital2000 +; +verilog = $MODEL_TECH/../verilog +std_developerskit = $MODEL_TECH/../std_developerskit +synopsys = $MODEL_TECH/../synopsys +modelsim_lib = $MODEL_TECH/../modelsim_lib +sv_std = $MODEL_TECH/../sv_std +mtiAvm = $MODEL_TECH/../avm +mtiOvm = $MODEL_TECH/../ovm-2.1.1 +mtiUvm = $MODEL_TECH/../uvm-1.0 +mtiUPF = $MODEL_TECH/../upf_lib +mtiPA = $MODEL_TECH/../pa_lib +floatfixlib = $MODEL_TECH/../floatfixlib +mc2_lib = $MODEL_TECH/../mc2_lib +;vhdl_psl_checkers = $MODEL_TECH/../vhdl_psl_checkers // Source files only for this release +;verilog_psl_checkers = $MODEL_TECH/../verilog_psl_checkers // Source files only for this release +;mvc_lib = $MODEL_TECH/../mvc_lib + +[vcom] +; VHDL93 variable selects language version as the default. +; Default is VHDL-2002. +; Value of 0 or 1987 for VHDL-1987. +; Value of 1 or 1993 for VHDL-1993. +; Default or value of 2 or 2002 for VHDL-2002. +; Value of 3 or 2008 for VHDL-2008 +VHDL93 = 2002 + +; Ignore VHDL-2008 declaration of REAL_VECTOR in package STANDARD. Default is off. +; ignoreStandardRealVector = 1 + +; Show source line containing error. Default is off. +; Show_source = 1 + +; Turn off unbound-component warnings. Default is on. +; Show_Warning1 = 0 + +; Turn off process-without-a-wait-statement warnings. Default is on. +; Show_Warning2 = 0 + +; Turn off null-range warnings. Default is on. +; Show_Warning3 = 0 + +; Turn off no-space-in-time-literal warnings. Default is on. +; Show_Warning4 = 0 + +; Turn off multiple-drivers-on-unresolved-signal warnings. Default is on. +; Show_Warning5 = 0 + +; Turn off optimization for IEEE std_logic_1164 package. Default is on. +; Optimize_1164 = 0 + +; Turn on resolving of ambiguous function overloading in favor of the +; "explicit" function declaration (not the one automatically created by +; the compiler for each type declaration). Default is off. +; The .ini file has Explicit enabled so that std_logic_signed/unsigned +; will match the behavior of synthesis tools. +Explicit = 1 + +; Turn off acceleration of the VITAL packages. Default is to accelerate. +; NoVital = 1 + +; Turn off VITAL compliance checking. Default is checking on. +; NoVitalCheck = 1 + +; Ignore VITAL compliance checking errors. Default is to not ignore. +; IgnoreVitalErrors = 1 + +; Turn off VITAL compliance checking warnings. Default is to show warnings. +; Show_VitalChecksWarnings = 0 + +; Turn off PSL assertion warning messages. Default is to show warnings. +; Show_PslChecksWarnings = 0 + +; Enable parsing of embedded PSL assertions. Default is enabled. +; EmbeddedPsl = 0 + +; Keep silent about case statement static warnings. +; Default is to give a warning. +; NoCaseStaticError = 1 + +; Keep silent about warnings caused by aggregates that are not locally static. +; Default is to give a warning. +; NoOthersStaticError = 1 + +; Treat as errors: +; case statement static warnings +; warnings caused by aggregates that are not locally static +; Overrides NoCaseStaticError, NoOthersStaticError settings. +; PedanticErrors = 1 + +; Turn off inclusion of debugging info within design units. +; Default is to include debugging info. +; NoDebug = 1 + +; Turn off "Loading..." messages. Default is messages on. +; Quiet = 1 + +; Turn on some limited synthesis rule compliance checking. Checks only: +; -- signals used (read) by a process must be in the sensitivity list +; CheckSynthesis = 1 + +; Activate optimizations on expressions that do not involve signals, +; waits, or function/procedure/task invocations. Default is off. +; ScalarOpts = 1 + +; Turns on lint-style checking. +; Show_Lint = 1 + +; Require the user to specify a configuration for all bindings, +; and do not generate a compile time default binding for the +; component. This will result in an elaboration error of +; 'component not bound' if the user fails to do so. Avoids the rare +; issue of a false dependency upon the unused default binding. +; RequireConfigForAllDefaultBinding = 1 + +; Perform default binding at compile time. +; Default is to do default binding at load time. +; BindAtCompile = 1; + +; Inhibit range checking on subscripts of arrays. Range checking on +; scalars defined with subtypes is inhibited by default. +; NoIndexCheck = 1 + +; Inhibit range checks on all (implicit and explicit) assignments to +; scalar objects defined with subtypes. +; NoRangeCheck = 1 + +; Run the 0-in compiler on the VHDL source files +; Default is off. +; ZeroIn = 1 + +; Set the options to be passed to the 0-in compiler. +; Default is "". +; ZeroInOptions = "" + +; Set the synthesis prefix to be honored for synthesis pragma recognition. +; Default is "". +; SynthPrefix = "" + +; Turn on code coverage in VHDL design units. Default is off. +; Coverage = sbceft + +; Turn off code coverage in VHDL subprograms. Default is on. +; CoverageSub = 0 + +; Automatically exclude VHDL case statement OTHERS choice branches. +; This includes OTHERS choices in selected signal assigment statements. +; Default is to not exclude. +; CoverExcludeDefault = 1 + +; Control compiler and VOPT optimizations that are allowed when +; code coverage is on. Refer to the comment for this in the [vlog] area. +; CoverOpt = 3 + +; Inform code coverage optimizations to respect VHDL 'H' and 'L' +; values on signals in conditions and expressions, and to not automatically +; convert them to '1' and '0'. Default is to not convert. +; CoverRespectHandL = 0 + +; Increase or decrease the maximum number of rows allowed in a UDP table +; implementing a VHDL condition coverage or expression coverage expression. +; More rows leads to a longer compile time, but more expressions covered. +; CoverMaxUDPRows = 192 + +; Increase or decrease the maximum number of input patterns that are present +; in FEC table. This leads to a longer compile time with more expressions +; covered with FEC metric. +; CoverMaxFECRows = 192 + +; Enable or disable Focused Expression Coverage analysis for conditions and +; expressions. Focused Expression Coverage data is provided by default when +; expression and/or condition coverage is active. +; CoverFEC = 0 + +; Enable or disable UDP Coverage analysis for conditions and expressions. +; UDP Coverage data is provided by default when expression and/or condition +; coverage is active. +; CoverUDP = 0 + +; Enable or disable short circuit evaluation of conditions and expressions when +; condition or expression coverage is active. Short circuit evaluation is enabled +; by default. +; CoverShortCircuit = 0 + +; Enable code coverage reporting of code that has been optimized away. +; The default is not to report. +; CoverReportCancelled = 1 + +; Use this directory for compiler temporary files instead of "work/_temp" +; CompilerTempDir = /tmp + +; Set this to cause the compilers to force data to be committed to disk +; when the files are closed. +; SyncCompilerFiles = 1 + +; Add VHDL-AMS declarations to package STANDARD +; Default is not to add +; AmsStandard = 1 + +; Range and length checking will be performed on array indices and discrete +; ranges, and when violations are found within subprograms, errors will be +; reported. Default is to issue warnings for violations, because subprograms +; may not be invoked. +; NoDeferSubpgmCheck = 0 + +; Turn ON detection of FSMs having single bit current state variable. +; FsmSingle = 1 + +; Turn off reset state transitions in FSM. +; FsmResetTrans = 0 + +; Turn ON detection of FSM Implicit Transitions. +; FsmImplicitTrans = 1 + +; Controls whether or not to show immediate assertions with constant expressions +; in GUI/report/UCDB etc. By default, immediate assertions with constant +; expressions are shown in GUI/report/UCDB etc. This does not affect +; evaluation of immediate assertions. +; ShowConstantImmediateAsserts = 0 + +; Controls how VHDL basic identifiers are stored with the design unit. +; Does not make the language case-sensitive, effects only how declarations +; declared with basic identifiers have their names stored and printed +; (examine, etc.). +; Default is to preserve the case as originally depicted in the VHDL source. +; Value of 0 indicates to change basic identifiers to lower case. +; PreserveCase = 0 + +; For Configuration Declarations, controls the effect that USE clauses have +; on visibility inside the configuration items being configured. If 1 +; (the default), then use pre-10.0 behavior. If 0, then for stricter LRM-compliance +; extend the visibility of objects made visible through USE clauses into nested +; component configurations. +; OldVHDLConfigurationVisibility = 0 + +[vlog] +; Turn off inclusion of debugging info within design units. +; Default is to include debugging info. +; NoDebug = 1 + +; Turn on `protect compiler directive processing. +; Default is to ignore `protect directives. +; Protect = 1 + +; Turn off "Loading..." messages. Default is messages on. +; Quiet = 1 + +; Turn on Verilog hazard checking (order-dependent accessing of global vars). +; Default is off. +; Hazard = 1 + +; Turn on converting regular Verilog identifiers to uppercase. Allows case +; insensitivity for module names. Default is no conversion. +; UpCase = 1 + +; Activate optimizations on expressions that do not involve signals, +; waits, or function/procedure/task invocations. Default is off. +; ScalarOpts = 1 + +; Turns on lint-style checking. +; Show_Lint = 1 + +; Show source line containing error. Default is off. +; Show_source = 1 + +; Turn on bad option warning. Default is off. +; Show_BadOptionWarning = 1 + +; Revert back to IEEE 1364-1995 syntax, default is 0 (off). +; vlog95compat = 1 + +; Turn off PSL warning messages. Default is to show warnings. +; Show_PslChecksWarnings = 0 + +; Enable parsing of embedded PSL assertions. Default is enabled. +; EmbeddedPsl = 0 + +; Set the threshold for automatically identifying sparse Verilog memories. +; A memory with depth equal to or more than the sparse memory threshold gets +; marked as sparse automatically, unless specified otherwise in source code +; or by +nosparse commandline option of vlog or vopt. +; The default is 1M. (i.e. memories with depth equal +; to or greater than 1M are marked as sparse) +; SparseMemThreshold = 1048576 + +; Run the 0-in compiler on the Verilog source files +; Default is off. +; ZeroIn = 1 + +; Set the options to be passed to the 0-in compiler. +; Default is "". +; ZeroInOptions = "" + +; Set the synthesis prefix to be honored for synthesis pragma recognition. +; Default is "". +; SynthPrefix = "" + +; Set the option to treat all files specified in a vlog invocation as a +; single compilation unit. The default value is set to 0 which will treat +; each file as a separate compilation unit as specified in the P1800 draft standard. +; MultiFileCompilationUnit = 1 + +; Turn on code coverage in Verilog design units. Default is off. +; Coverage = sbceft + +; Automatically exclude Verilog case statement default branches. +; Default is to not automatically exclude defaults. +; CoverExcludeDefault = 1 + +; Increase or decrease the maximum number of rows allowed in a UDP table +; implementing a Verilog condition coverage or expression coverage expression. +; More rows leads to a longer compile time, but more expressions covered. +; CoverMaxUDPRows = 192 + +; Increase or decrease the maximum number of input patterns that are present +; in FEC table. This leads to a longer compile time with more expressions +; covered with FEC metric. +; CoverMaxFECRows = 192 + +; Enable or disable Focused Expression Coverage analysis for conditions and +; expressions. Focused Expression Coverage data is provided by default when +; expression and/or condition coverage is active. +; CoverFEC = 0 + +; Enable or disable UDP Coverage analysis for conditions and expressions. +; UDP Coverage data is provided by default when expression and/or condition +; coverage is active. +; CoverUDP = 0 + +; Enable or disable short circuit evaluation of conditions and expressions when +; condition or expression coverage is active. Short circuit evaluation is enabled +; by default. +; CoverShortCircuit = 0 + + +; Turn on code coverage in VLOG `celldefine modules and modules included +; using vlog -v and -y. Default is off. +; CoverCells = 1 + +; Enable code coverage reporting of code that has been optimized away. +; The default is not to report. +; CoverReportCancelled = 1 + +; Control compiler and VOPT optimizations that are allowed when +; code coverage is on. This is a number from 1 to 4, with the following +; meanings (the default is 3): +; 1 -- Turn off all optimizations that affect coverage reports. +; 2 -- Allow optimizations that allow large performance improvements +; by invoking sequential processes only when the data changes. +; This may make major reductions in coverage counts. +; 3 -- In addition, allow optimizations that may change expressions or +; remove some statements. Allow constant propagation. Allow VHDL +; subprogram inlining and VHDL FF recognition. +; 4 -- In addition, allow optimizations that may remove major regions of +; code by changing assignments to built-ins or removing unused +; signals. Change Verilog gates to continuous assignments. +; CoverOpt = 3 + +; Specify the override for the default value of "cross_num_print_missing" +; option for the Cross in Covergroups. If not specified then LRM default +; value of 0 (zero) is used. This is a compile time option. +; SVCrossNumPrintMissingDefault = 0 + +; Setting following to 1 would cause creation of variables which +; would represent the value of Coverpoint expressions. This is used +; in conjunction with "SVCoverpointExprVariablePrefix" option +; in the modelsim.ini +; EnableSVCoverpointExprVariable = 0 + +; Specify the override for the prefix used in forming the variable names +; which represent the Coverpoint expressions. This is used in conjunction with +; "EnableSVCoverpointExprVariable" option of the modelsim.ini +; The default prefix is "expr". +; The variable name is +; variable name => _ +; SVCoverpointExprVariablePrefix = expr + +; Override for the default value of the SystemVerilog covergroup, +; coverpoint, and cross option.goal (defined to be 100 in the LRM). +; NOTE: It does not override specific assignments in SystemVerilog +; source code. NOTE: The modelsim.ini variable "SVCovergroupGoal" +; in the [vsim] section can override this value. +; SVCovergroupGoalDefault = 100 + +; Override for the default value of the SystemVerilog covergroup, +; coverpoint, and cross type_option.goal (defined to be 100 in the LRM) +; NOTE: It does not override specific assignments in SystemVerilog +; source code. NOTE: The modelsim.ini variable "SVCovergroupTypeGoal" +; in the [vsim] section can override this value. +; SVCovergroupTypeGoalDefault = 100 + +; Specify the override for the default value of "strobe" option for the +; Covergroup Type. This is a compile time option which forces "strobe" to +; a user specified default value and supersedes SystemVerilog specified +; default value of '0'(zero). NOTE: This can be overriden by a runtime +; modelsim.ini variable "SVCovergroupStrobe" in the [vsim] section. +; SVCovergroupStrobeDefault = 0 + +; Specify the override for the default value of "merge_instances" option for +; the Covergroup Type. This is a compile time option which forces +; "merge_instances" to a user specified default value and supersedes +; SystemVerilog specified default value of '0'(zero). +; SVCovergroupMergeInstancesDefault = 0 + +; Specify the override for the default value of "per_instance" option for the +; Covergroup variables. This is a compile time option which forces "per_instance" +; to a user specified default value and supersedes SystemVerilog specified +; default value of '0'(zero). +; SVCovergroupPerInstanceDefault = 0 + +; Specify the override for the default value of "get_inst_coverage" option for the +; Covergroup variables. This is a compile time option which forces +; "get_inst_coverage" to a user specified default value and supersedes +; SystemVerilog specified default value of '0'(zero). +; SVCovergroupGetInstCoverageDefault = 0 + +; +; A space separated list of resource libraries that contain precompiled +; packages. The behavior is identical to using the "-L" switch. +; +; LibrarySearchPath = [ ...] +LibrarySearchPath = mtiAvm mtiOvm mtiUvm mtiUPF + +; The behavior is identical to the "-mixedansiports" switch. Default is off. +; MixedAnsiPorts = 1 + +; Enable SystemVerilog 3.1a $typeof() function. Default is off. +; EnableTypeOf = 1 + +; Only allow lower case pragmas. Default is disabled. +; AcceptLowerCasePragmaOnly = 1 + +; Set the maximum depth permitted for a recursive include file nesting. +; IncludeRecursionDepthMax = 5 + +; Turn ON detection of FSMs having single bit current state variable. +; FsmSingle = 1 + +; Turn off reset state transitions in FSM. +; FsmResetTrans = 0 + +; Turn off detections of FSMs having x-assignment. +; FsmXAssign = 0 + +; Turn ON detection of FSM Implicit Transitions. +; FsmImplicitTrans = 1 + +; List of file suffixes which will be read as SystemVerilog. White space +; in extensions can be specified with a back-slash: "\ ". Back-slashes +; can be specified with two consecutive back-slashes: "\\"; +; SVFileExtensions = sv svp svh + +; This setting is the same as the vlog -sv command line switch. +; Enables SystemVerilog features and keywords when true (1). +; When false (0), the rules of IEEE Std 1364-2001 are followed and +; SystemVerilog keywords are ignored. +; Svlog = 0 + +; Prints attribute placed upon SV packages during package import +; when true (1). The attribute will be ignored when this +; entry is false (0). The attribute name is "package_load_message". +; The value of this attribute is a string literal. +; Default is true (1). +; PrintSVPackageLoadingAttribute = 1 + +; Do not show immediate assertions with constant expressions in +; GUI/reports/UCDB etc. By default immediate assertions with constant +; expressions are shown in GUI/reports/UCDB etc. This does not affect +; evaluation of immediate assertions. +; ShowConstantImmediateAsserts = 0 + +; Controls if untyped parameters that are initialized with values greater +; than 2147483647 are mapped to generics of type INTEGER or ignored. +; If mapped to VHDL Integers, values greater than 2147483647 +; are mapped to negative values. +; Default is to map these parameter to generic of type INTEGER +; ForceUnsignedToVHDLInteger = 1 + +; Enable AMS wreal (wired real) extensions. Default is 0. +; WrealType = 1 + +[sccom] +; Enable use of SCV include files and library. Default is off. +; UseScv = 1 + +; Add C++ compiler options to the sccom command line by using this variable. +; CppOptions = -g + +; Use custom C++ compiler located at this path rather than the default path. +; The path should point directly at a compiler executable. +; CppPath = /usr/bin/g++ + +; Enable verbose messages from sccom. Default is off. +; SccomVerbose = 1 + +; sccom logfile. Default is no logfile. +; SccomLogfile = sccom.log + +; Enable use of SC_MS include files and library. Default is off. +; UseScMs = 1 + +[vopt] +; Turn on code coverage in vopt. Default is off. +; Coverage = sbceft + +; Control compiler optimizations that are allowed when +; code coverage is on. Refer to the comment for this in the [vlog] area. +; CoverOpt = 3 + +; Increase or decrease the maximum number of rows allowed in a UDP table +; implementing a vopt condition coverage or expression coverage expression. +; More rows leads to a longer compile time, but more expressions covered. +; CoverMaxUDPRows = 192 + +; Increase or decrease the maximum number of input patterns that are present +; in FEC table. This leads to a longer compile time with more expressions +; covered with FEC metric. +; CoverMaxFECRows = 192 + +; Enable code coverage reporting of code that has been optimized away. +; The default is not to report. +; CoverReportCancelled = 1 + +; Do not show immediate assertions with constant expressions in +; GUI/reports/UCDB etc. By default immediate assertions with constant +; expressions are shown in GUI/reports/UCDB etc. This does not affect +; evaluation of immediate assertions. +; ShowConstantImmediateAsserts = 0 + +; Set the maximum number of iterations permitted for a generate loop. +; Restricting this permits the implementation to recognize infinite +; generate loops. +; GenerateLoopIterationMax = 100000 + +; Set the maximum depth permitted for a recursive generate instantiation. +; Restricting this permits the implementation to recognize infinite +; recursions. +; GenerateRecursionDepthMax = 200 + + +[vsim] +; vopt flow +; Set to turn on automatic optimization of a design. +; Default is on +VoptFlow = 1 + +; Simulator resolution +; Set to fs, ps, ns, us, ms, or sec with optional prefix of 1, 10, or 100. +Resolution = ps + +; Disable certain code coverage exclusions automatically. +; Assertions and FSM are exluded from the code coverage by default +; Set AutoExclusionsDisable = fsm to enable code coverage for fsm +; Set AutoExclusionsDisable = assertions to enable code coverage for assertions +; Set AutoExclusionsDisable = all to enable code coverage for all the automatic exclusions +; Or specify comma or space separated list +;AutoExclusionsDisable = fsm,assertions + +; User time unit for run commands +; Set to default, fs, ps, ns, us, ms, or sec. The default is to use the +; unit specified for Resolution. For example, if Resolution is 100ps, +; then UserTimeUnit defaults to ps. +; Should generally be set to default. +UserTimeUnit = default + +; Default run length +RunLength = 100 + +; Maximum iterations that can be run without advancing simulation time +IterationLimit = 5000 + +; Control PSL and Verilog Assume directives during simulation +; Set SimulateAssumeDirectives = 0 to disable assume being simulated as asserts +; Set SimulateAssumeDirectives = 1 to enable assume simulation as asserts +; SimulateAssumeDirectives = 1 + +; Control the simulation of PSL and SVA +; These switches can be overridden by the vsim command line switches: +; -psl, -nopsl, -sva, -nosva. +; Set SimulatePSL = 0 to disable PSL simulation +; Set SimulatePSL = 1 to enable PSL simulation (default) +; SimulatePSL = 1 +; Set SimulateSVA = 0 to disable SVA simulation +; Set SimulateSVA = 1 to enable concurrent SVA simulation (default) +; SimulateSVA = 1 + +; Directives to license manager can be set either as single value or as +; space separated multi-values: +; vhdl Immediately reserve a VHDL license +; vlog Immediately reserve a Verilog license +; plus Immediately reserve a VHDL and Verilog license +; noqueue Do not wait in the license queue when a license is not available +; viewsim Try for viewer license but accept simulator license(s) instead +; of queuing for viewer license (PE ONLY) +; noviewer Disable checkout of msimviewer and vsim-viewer license +; features (PE ONLY) +; noslvhdl Disable checkout of qhsimvh and vsim license features +; noslvlog Disable checkout of qhsimvl and vsimvlog license features +; nomix Disable checkout of msimhdlmix and hdlmix license features +; nolnl Disable checkout of msimhdlsim and hdlsim license features +; mixedonly Disable checkout of qhsimvh,qhsimvl,vsim,vsimvlog license +; features +; lnlonly Disable checkout of qhsimvh,qhsimvl,vsim,vsimvlog,msimhdlmix, +; hdlmix license features +; Single value: +; License = plus +; Multi-value: +; License = noqueue plus + +; Severity level of a VHDL assertion message or of a SystemVerilog immediate assertion +; which will cause a running simulation to stop. +; VHDL assertions and SystemVerilog immediate assertions that occur with the +; given severity or higher will cause a running simulation to stop. +; This value is ignored during elaboration. +; 0 = Note 1 = Warning 2 = Error 3 = Failure 4 = Fatal +BreakOnAssertion = 3 + +; Message Format conversion specifications: +; %S - Severity Level of message/assertion +; %R - Text of message +; %T - Time of message +; %D - Delta value (iteration number) of Time +; %K - Kind of path: Instance/Region/Signal/Process/Foreign Process/Unknown/Protected +; %i - Instance/Region/Signal pathname with Process name (if available) +; %I - shorthand for one of these: +; " %K: %i" +; " %K: %i File: %F" (when path is not Process or Signal) +; except that the %i in this case does not report the Process name +; %O - Process name +; %P - Instance/Region path without leaf process +; %F - File name +; %L - Line number; if assertion message, then line number of assertion or, if +; assertion is in a subprogram, line from which the call is made +; %u - Design unit name in form library.primary +; %U - Design unit name in form library.primary(secondary) +; %% - The '%' character itself +; +; If specific format for Severity Level is defined, use that format. +; Else, for a message that occurs during elaboration: +; -- Failure/Fatal message in VHDL region that is not a Process, and in +; certain non-VHDL regions, uses MessageFormatBreakLine; +; -- Failure/Fatal message otherwise uses MessageFormatBreak; +; -- Note/Warning/Error message uses MessageFormat. +; Else, for a message that occurs during runtime and triggers a breakpoint because +; of the BreakOnAssertion setting: +; -- if in a VHDL region that is not a Process, uses MessageFormatBreakLine; +; -- otherwise uses MessageFormatBreak. +; Else (a runtime message that does not trigger a breakpoint) uses MessageFormat. +; +; MessageFormatNote = "** %S: %R\n Time: %T Iteration: %D%I\n" +; MessageFormatWarning = "** %S: %R\n Time: %T Iteration: %D%I\n" +; MessageFormatError = "** %S: %R\n Time: %T Iteration: %D %K: %i File: %F\n" +; MessageFormatFail = "** %S: %R\n Time: %T Iteration: %D %K: %i File: %F\n" +; MessageFormatFatal = "** %S: %R\n Time: %T Iteration: %D %K: %i File: %F\n" +; MessageFormatBreakLine = "** %S: %R\n Time: %T Iteration: %D %K: %i File: %F Line: %L\n" +; MessageFormatBreak = "** %S: %R\n Time: %T Iteration: %D %K: %i File: %F\n" +; MessageFormat = "** %S: %R\n Time: %T Iteration: %D%I\n" + +; Error File - alternate file for storing error messages +; ErrorFile = error.log + +; Simulation Breakpoint messages +; This flag controls the display of function names when reporting the location +; where the simulator stops because of a breakpoint or fatal error. +; Example with function name: # Break in Process ctr at counter.vhd line 44 +; Example without function name: # Break at counter.vhd line 44 +; Default value is 1. +ShowFunctions = 1 + +; Default radix for all windows and commands. +; Set to symbolic, ascii, binary, octal, decimal, hex, unsigned +DefaultRadix = hex + +; VSIM Startup command +; Startup = do startup.do + +; VSIM Shutdown file +; Filename to save u/i formats and configurations. +; ShutdownFile = restart.do +; To explicitly disable auto save: +; ShutdownFile = --disable-auto-save + +; File for saving command transcript +TranscriptFile = transcript + +; File for saving command history +; CommandHistory = cmdhist.log + +; Specify whether paths in simulator commands should be described +; in VHDL or Verilog format. +; For VHDL, PathSeparator = / +; For Verilog, PathSeparator = . +; Must not be the same character as DatasetSeparator. +PathSeparator = / + +; Specify the dataset separator for fully rooted contexts. +; The default is ':'. For example: sim:/top +; Must not be the same character as PathSeparator. +DatasetSeparator = : + +; Specify a unique path separator for the Signal Spy set of functions. +; The default will be to use the PathSeparator variable. +; Must not be the same character as DatasetSeparator. +; SignalSpyPathSeparator = / + +; Used to control parsing of HDL identifiers input to the tool. +; This includes CLI commands, vsim/vopt/vlog/vcom options, +; string arguments to FLI/VPI/DPI calls, etc. +; If set to 1, accept either Verilog escaped Id syntax or +; VHDL extended id syntax, regardless of source language. +; If set to 0, the syntax of the source language must be used. +; Each identifier in a hierarchical name may need different syntax, +; e.g. "/top/\vhdl*ext*id\/middle/\vlog*ext*id /bottom" or +; "top.\vhdl*ext*id\.middle.\vlog*ext*id .bottom" +; GenerousIdentifierParsing = 1 + +; Disable VHDL assertion messages +; IgnoreNote = 1 +; IgnoreWarning = 1 +; IgnoreError = 1 +; IgnoreFailure = 1 + +; Disable SystemVerilog assertion messages +; IgnoreSVAInfo = 1 +; IgnoreSVAWarning = 1 +; IgnoreSVAError = 1 +; IgnoreSVAFatal = 1 + +; Do not print any additional information from Severity System tasks. +; Only the message provided by the user is printed along with severity +; information. +; SVAPrintOnlyUserMessage = 1; + +; Default force kind. May be freeze, drive, deposit, or default +; or in other terms, fixed, wired, or charged. +; A value of "default" will use the signal kind to determine the +; force kind, drive for resolved signals, freeze for unresolved signals +; DefaultForceKind = freeze + +; Control the iteration of events when a VHDL signal is forced to a value +; This flag can be set to honour the signal update event in next iteration, +; the default is to update and propagate in the same iteration. +; ForceSigNextIter = 1 + + +; If zero, open files when elaborated; otherwise, open files on +; first read or write. Default is 0. +; DelayFileOpen = 1 + +; Control VHDL files opened for write. +; 0 = Buffered, 1 = Unbuffered +UnbufferedOutput = 0 + +; Control the number of VHDL files open concurrently. +; This number should always be less than the current ulimit +; setting for max file descriptors. +; 0 = unlimited +ConcurrentFileLimit = 40 + +; Control the number of hierarchical regions displayed as +; part of a signal name shown in the Wave window. +; A value of zero tells VSIM to display the full name. +; The default is 0. +; WaveSignalNameWidth = 0 + +; Turn off warnings when changing VHDL constants and generics +; Default is 1 to generate warning messages +; WarnConstantChange = 0 + +; Turn off warnings from accelerated versions of the std_logic_arith, +; std_logic_unsigned, and std_logic_signed packages. +; StdArithNoWarnings = 1 + +; Turn off warnings from accelerated versions of the IEEE numeric_std +; and numeric_bit packages. +; NumericStdNoWarnings = 1 + +; Use old-style (pre-6.6) VHDL FOR generate statement iteration names +; in the design hierarchy. +; This style is controlled by the value of the GenerateFormat +; value described next. Default is to use new-style names, which +; comprise the generate statement label, '(', the value of the generate +; parameter, and a closing ')'. +; Uncomment this to use old-style names. +; OldVhdlForGenNames = 1 + +; Enable changes in VHDL elaboration to allow for Variable Logging +; This trades off simulation performance for the ability to log variables +; efficiently. By default this is disable for maximum simulation performance +; VhdlVariableLogging = 1 + +; Control the format of the old-style VHDL FOR generate statement region +; name for each iteration. Do not quote it. +; The format string here must contain the conversion codes %s and %d, +; in that order, and no other conversion codes. The %s represents +; the generate statement label; the %d represents the generate parameter value +; at a particular iteration (this is the position number if the generate parameter +; is of an enumeration type). Embedded whitespace is allowed (but discouraged); +; leading and trailing whitespace is ignored. +; Application of the format must result in a unique region name over all +; loop iterations for a particular immediately enclosing scope so that name +; lookup can function properly. The default is %s__%d. +; GenerateFormat = %s__%d + +; Specify whether checkpoint files should be compressed. +; The default is 1 (compressed). +; CheckpointCompressMode = 0 + +; Specify gcc compiler used in the compilation of automatically generated DPI exportwrapper. +; Use custom gcc compiler located at this path rather than the default path. +; The path should point directly at a compiler executable. +; DpiCppPath = /bin/gcc + +; Specify whether to enable SystemVerilog DPI "out-of-the-blue" calls. +; The term "out-of-the-blue" refers to SystemVerilog export function calls +; made from C functions that don't have the proper context setup +; (as is the case when running under "DPI-C" import functions). +; When this is enabled, one can call a DPI export function +; (but not task) from any C code. +; the setting of this variable can be one of the following values: +; 0 : dpioutoftheblue call is disabled (default) +; 1 : dpioutoftheblue call is enabled, but export call debug support is not available. +; 2 : dpioutoftheblue call is enabled, and limited export call debug support is available. +; DpiOutOfTheBlue = 1 + +; Specify whether continuous assignments are run before other normal priority +; processes scheduled in the same iteration. This event ordering minimizes race +; differences between optimized and non-optimized designs, and is the default +; behavior beginning with the 6.5 release. For pre-6.5 event ordering, set +; ImmediateContinuousAssign to 0. +; The default is 1 (enabled). +; ImmediateContinuousAssign = 0 + +; List of dynamically loaded objects for Verilog PLI applications +; Veriuser = veriuser.sl + +; Which default VPI object model should the tool conform to? +; The 1364 modes are Verilog-only, for backwards compatibility with older +; libraries, and SystemVerilog objects are not available in these modes. +; +; In the absence of a user-specified default, the tool default is the +; latest available LRM behavior. +; Options for PliCompatDefault are: +; VPI_COMPATIBILITY_VERSION_1364v1995 +; VPI_COMPATIBILITY_VERSION_1364v2001 +; VPI_COMPATIBILITY_VERSION_1364v2005 +; VPI_COMPATIBILITY_VERSION_1800v2005 +; VPI_COMPATIBILITY_VERSION_1800v2008 +; +; Synonyms for each string are also recognized: +; VPI_COMPATIBILITY_VERSION_1364v1995 (1995, 95, 1364v1995, 1364V1995, VL1995) +; VPI_COMPATIBILITY_VERSION_1364v2001 (2001, 01, 1364v2001, 1364V2001, VL2001) +; VPI_COMPATIBILITY_VERSION_1364v2005 (1364v2005, 1364V2005, VL2005) +; VPI_COMPATIBILITY_VERSION_1800v2005 (2005, 05, 1800v2005, 1800V2005, SV2005) +; VPI_COMPATIBILITY_VERSION_1800v2008 (2008, 08, 1800v2008, 1800V2008, SV2008) + + +; PliCompatDefault = VPI_COMPATIBILITY_VERSION_1800v2005 + +; Specify default options for the restart command. Options can be one +; or more of: -force -nobreakpoint -nolist -nolog -nowave -noassertions +; DefaultRestartOptions = -force + +; Turn on (1) or off (0) WLF file compression. +; The default is 1 (compress WLF file). +; WLFCompress = 0 + +; Specify whether to save all design hierarchy (1) in the WLF file +; or only regions containing logged signals (0). +; The default is 0 (save only regions with logged signals). +; WLFSaveAllRegions = 1 + +; WLF file time limit. Limit WLF file by time, as closely as possible, +; to the specified amount of simulation time. When the limit is exceeded +; the earliest times get truncated from the file. +; If both time and size limits are specified the most restrictive is used. +; UserTimeUnits are used if time units are not specified. +; The default is 0 (no limit). Example: WLFTimeLimit = {100 ms} +; WLFTimeLimit = 0 + +; WLF file size limit. Limit WLF file size, as closely as possible, +; to the specified number of megabytes. If both time and size limits +; are specified then the most restrictive is used. +; The default is 0 (no limit). +; WLFSizeLimit = 1000 + +; Specify whether or not a WLF file should be deleted when the +; simulation ends. A value of 1 will cause the WLF file to be deleted. +; The default is 0 (do not delete WLF file when simulation ends). +; WLFDeleteOnQuit = 1 + +; Specify whether or not a WLF file should be optimized during +; simulation. If set to 0, the WLF file will not be optimized. +; The default is 1, optimize the WLF file. +; WLFOptimize = 0 + +; Specify the name of the WLF file. +; The default is vsim.wlf +; WLFFilename = vsim.wlf + +; Specify whether to lock the WLF file. +; Locking the file prevents other invocations of ModelSim/Questa tools from +; inadvertently overwriting the WLF file. +; The default is 1, lock the WLF file. +; WLFFileLock = 0 + +; Specify the WLF reader cache size limit for each open WLF file. +; The size is giving in megabytes. A value of 0 turns off the +; WLF cache. +; WLFSimCacheSize allows a different cache size to be set for +; simulation WLF file independent of post-simulation WLF file +; viewing. If WLFSimCacheSize is not set it defaults to the +; WLFCacheSize setting. +; The default WLFCacheSize setting is enabled to 256M per open WLF file. +; WLFCacheSize = 2000 +; WLFSimCacheSize = 500 + +; Specify the WLF file event collapse mode. +; 0 = Preserve all events and event order. (same as -wlfnocollapse) +; 1 = Only record values of logged objects at the end of a simulator iteration. +; (same as -wlfcollapsedelta) +; 2 = Only record values of logged objects at the end of a simulator time step. +; (same as -wlfcollapsetime) +; The default is 1. +; WLFCollapseMode = 0 + +; Specify whether WLF file logging can use threads on multi-processor machines +; if 0, no threads will be used, if 1, threads will be used if the system has +; more than one processor +; WLFUseThreads = 1 + +; Turn on/off undebuggable SystemC type warnings. Default is on. +; ShowUndebuggableScTypeWarning = 0 + +; Turn on/off unassociated SystemC name warnings. Default is off. +; ShowUnassociatedScNameWarning = 1 + +; Turn on/off SystemC IEEE 1666 deprecation warnings. Default is off. +; ScShowIeeeDeprecationWarnings = 1 + +; Turn on/off the check for multiple drivers on a SystemC sc_signal. Default is off. +; ScEnableScSignalWriteCheck = 1 + +; Set SystemC default time unit. +; Set to fs, ps, ns, us, ms, or sec with optional +; prefix of 1, 10, or 100. The default is 1 ns. +; The ScTimeUnit value is honored if it is coarser than Resolution. +; If ScTimeUnit is finer than Resolution, it is set to the value +; of Resolution. For example, if Resolution is 100ps and ScTimeUnit is ns, +; then the default time unit will be 1 ns. However if Resolution +; is 10 ns and ScTimeUnit is ns, then the default time unit will be 10 ns. +ScTimeUnit = ns + +; Set SystemC sc_main stack size. The stack size is set as an integer +; number followed by the unit which can be Kb(Kilo-byte), Mb(Mega-byte) or +; Gb(Giga-byte). Default is 10 Mb. The stack size for sc_main depends +; on the amount of data on the sc_main() stack and the memory required +; to succesfully execute the longest function call chain of sc_main(). +ScMainStackSize = 10 Mb + +; Turn on/off execution of remainder of sc_main upon quitting the current +; simulation session. If the cumulative length of sc_main() in terms of +; simulation time units is less than the length of the current simulation +; run upon quit or restart, sc_main() will be in the middle of execution. +; This switch gives the option to execute the remainder of sc_main upon +; quitting simulation. The drawback of not running sc_main till the end +; is memory leaks for objects created by sc_main. If on, the remainder of +; sc_main will be executed ignoring all delays. This may cause the simulator +; to crash if the code in sc_main is dependent on some simulation state. +; Default is on. +ScMainFinishOnQuit = 1 + +; Set the SCV relationship name that will be used to identify phase +; relations. If the name given to a transactor relation matches this +; name, the transactions involved will be treated as phase transactions +ScvPhaseRelationName = mti_phase + +; Customize the vsim kernel shutdown behavior at the end of the simulation. +; Some common causes of the end of simulation are $finish (implicit or explicit), +; sc_stop(), tf_dofinish(), and assertion failures. +; This should be set to "ask", "exit", or "stop". The default is "ask". +; "ask" -- In batch mode, the vsim kernel will abruptly exit. +; In GUI mode, a dialog box will pop up and ask for user confirmation +; whether or not to quit the simulation. +; "stop" -- Cause the simulation to stay loaded in memory. This can make some +; post-simulation tasks easier. +; "exit" -- The simulation will abruptly exit without asking for any confirmation. +; "final" -- Run SystemVerilog final blocks then behave as "stop". +; Note: This variable can be overridden with the vsim "-onfinish" command line switch. +OnFinish = ask + +; Print pending deferred assertion messages. +; Deferred assertion messages may be scheduled after the $finish in the same +; time step. Deferred assertions scheduled to print after the $finish are +; printed before exiting with severity level NOTE since it's not known whether +; the assertion is still valid due to being printed in the active region +; instead of the reactive region where they are normally printed. +; OnFinishPendingAssert = 1; + +; Print "simstats" result +; 0 == do not print simstats +; 1 == print at end of simulation +; 2 == print at end of run +; 3 == print at end of run and end of simulation +; default == 0 +; PrintSimStats = 1 + + +; Assertion File - alternate file for storing VHDL/PSL/Verilog assertion messages +; AssertFile = assert.log + +; Enable assertion counts. Default is off. +; AssertionCover = 1 + +; Run simulator in assertion debug mode. Default is off. +; AssertionDebug = 1 + +; Turn on/off PSL/SVA/VHDL assertion enable. Default is on. +; AssertionEnable = 0 + +; Set PSL/SVA/VHDL concurrent assertion fail limit. Default is -1. +; Any positive integer, -1 for infinity. +; AssertionLimit = 1 + +; Turn on/off concurrent assertion pass log. Default is off. +; Assertion pass logging is only enabled when assertion is browseable +; and assertion debug is enabled. +; AssertionPassLog = 1 + +; Turn on/off PSL concurrent assertion fail log. Default is on. +; The flag does not affect SVA +; AssertionFailLog = 0 + +; Turn on/off SVA concurrent assertion local var printing in -assertdebug mode. Default is on. +; AssertionFailLocalVarLog = 0 + +; Set action type for PSL/SVA concurrent assertion fail action. Default is continue. +; 0 = Continue 1 = Break 2 = Exit +; AssertionFailAction = 1 + +; Enable the active thread monitor in the waveform display when assertion debug is enabled. +; AssertionActiveThreadMonitor = 1 + +; Control how many waveform rows will be used for displaying the active threads. Default is 5. +; AssertionActiveThreadMonitorLimit = 5 + +; Assertion thread limit after which assertion would be killed/switched off. +; The default is -1 (unlimited). If the number of threads for an assertion go +; beyond this limit, the assertion would be either switched off or killed. This +; limit applies to only assert directives. +;AssertionThreadLimit = -1 + +; Action to be taken once the assertion thread limit is reached. Default +; is kill. It can have a value of off or kill. In case of kill, all the existing +; threads are terminated and no new attempts are started. In case of off, the +; existing attempts keep on evaluating but no new attempts are started. This +; variable applies to only assert directives. +;AssertionThreadLimitAction = kill + +; Cover thread limit after which cover would be killed/switched off. +; The default is -1 (unlimited). If the number of threads for a cover go +; beyond this limit, the cover would be either switched off or killed. This +; limit applies to only cover directives. +;CoverThreadLimit = -1 + +; Action to be taken once the cover thread limit is reached. Default +; is kill. It can have a value of off or kill. In case of kill, all the existing +; threads are terminated and no new attempts are started. In case of off, the +; existing attempts keep on evaluating but no new attempts are started. This +; variable applies to only cover directives. +;CoverThreadLimitAction = kill + + +; By default immediate assertions do not participate in Assertion Coverage calculations +; unless they are executed. This switch causes all immediate assertions in the design +; to participate in Assertion Coverage calculations, whether attempted or not. +; UnattemptedImmediateAssertions = 0 + +; By default immediate covers participate in Coverage calculations +; whether they are attempted or not. This switch causes all unattempted +; immediate covers in the design to stop participating in Coverage +; calculations. +; UnattemptedImmediateCovers = 0 + +; By default pass action block is not executed for assertions on vacuous +; success. The following variable is provided to enable execution of +; pass action block on vacuous success. The following variable is only effective +; if the user does not disable pass action block execution by using either +; system tasks or CLI. Also there is a performance penalty for enabling +; the following variable. +;AssertionEnableVacuousPassActionBlock = 1 + +; As per strict 1850-2005 PSL LRM, an always property can either pass +; or fail. However, by default, Questa reports multiple passes and +; multiple fails on top always/never property (always/never operator +; is the top operator under Verification Directive). The reason +; being that Questa reports passes and fails on per attempt of the +; top always/never property. Use the following flag to instruct +; Questa to strictly follow LRM. With this flag, all assert/never +; directives will start an attempt once at start of simulation. +; The attempt can either fail, match or match vacuously. +; For e.g. if always is the top operator under assert, the always will +; keep on checking the property at every clock. If the property under +; always fails, the directive will be considered failed and no more +; checking will be done for that directive. A top always property, +; if it does not fail, will show a pass at end of simulation. +; The default value is '0' (i.e. zero is off). For example: +; PslOneAttempt = 1 + +; Specify the number of clock ticks to represent infinite clock ticks. +; This affects eventually!, until! and until_!. If at End of Simulation +; (EOS) an active strong-property has not clocked this number of +; clock ticks then neither pass or fail (vacuous match) is returned +; else respective fail/pass is returned. The default value is '0' (zero) +; which effectively does not check for clock tick condition. For example: +; PslInfinityThreshold = 5000 + +; Control how many thread start times will be preserved for ATV viewing for a given assertion +; instance. Default is -1 (ALL). +; ATVStartTimeKeepCount = -1 + +; Turn on/off code coverage +; CodeCoverage = 0 + +; Count all code coverage condition and expression truth table rows that match. +; CoverCountAll = 1 + +; Turn off automatic inclusion of VHDL integers in toggle coverage. Default +; is to include them. +; ToggleNoIntegers = 1 + +; Set the maximum number of values that are collected for toggle coverage of +; VHDL integers. Default is 100; +; ToggleMaxIntValues = 100 + +; Set the maximum number of values that are collected for toggle coverage of +; Verilog real. Default is 100; +; ToggleMaxRealValues = 100 + +; Turn on automatic inclusion of Verilog integers in toggle coverage, except +; for enumeration types. Default is to include them. +; ToggleVlogIntegers = 0 + +; Turn on automatic inclusion of Verilog real type in toggle coverage, except +; for shortreal types. Default is to not include them. +; ToggleVlogReal = 1 + +; Turn on automatic inclusion of Verilog fixed-size unpacked arrays, VHDL multi-d arrays +; and VHDL arrays-of-arrays in toggle coverage. +; Default is to not include them. +; ToggleFixedSizeArray = 1 + +; Increase or decrease the maximum size of Verilog unpacked fixed-size arrays, +; VHDL multi-d arrays and VHDL arrays-of-arrays that are included for toggle coverage. +; This leads to a longer simulation time with bigger arrays covered with toggle coverage. +; Default is 1024. +; ToggleMaxFixedSizeArray = 1024 + +; Treat Verilog multi-dimensional packed vectors and packed structures as equivalently sized +; one-dimensional packed vectors for toggle coverage. Default is 0. +; TogglePackedAsVec = 0 + +; Treat Verilog enumerated types as equivalently sized one-dimensional packed vectors for +; toggle coverage. Default is 0. +; ToggleVlogEnumBits = 0 + +; Limit the widths of registers automatically tracked for toggle coverage. Default is 128. +; For unlimited width, set to 0. +; ToggleWidthLimit = 128 + +; Limit the counts that are tracked for toggle coverage. When all edges for a bit have +; reached this count, further activity on the bit is ignored. Default is 1. +; For unlimited counts, set to 0. +; ToggleCountLimit = 1 + +; Change the mode of extended toggle coverage. Default is 3. Valid modes are 1, 2 and 3. +; Following is the toggle coverage calculation criteria based on extended toggle mode: +; Mode 1: 0L->1H & 1H->0L & any one 'Z' transition (to/from 'Z'). +; Mode 2: 0L->1H & 1H->0L & one transition to 'Z' & one transition from 'Z'. +; Mode 3: 0L->1H & 1H->0L & all 'Z' transitions. +; ExtendedToggleMode = 3 + +; Enable toggle statistics collection only for ports. Default is 0. +; TogglePortsOnly = 1 + +; Turn on/off all PSL/SVA cover directive enables. Default is on. +; CoverEnable = 0 + +; Turn on/off PSL/SVA cover log. Default is off "0". +; CoverLog = 1 + +; Set "at_least" value for all PSL/SVA cover directives. Default is 1. +; CoverAtLeast = 2 + +; Set "limit" value for all PSL/SVA cover directives. Default is -1. +; Any positive integer, -1 for infinity. +; CoverLimit = 1 + +; Specify the coverage database filename. +; Default is "" (i.e. database is NOT automatically saved on close). +; UCDBFilename = vsim.ucdb + +; Specify the maximum limit for the number of Cross (bin) products reported +; in XML and UCDB report against a Cross. A warning is issued if the limit +; is crossed. Default is zero. vsim switch -cvgmaxrptrhscross can override this +; setting. +; MaxReportRhsSVCrossProducts = 1000 + +; Specify the override for the "auto_bin_max" option for the Covergroups. +; If not specified then value from Covergroup "option" is used. +; SVCoverpointAutoBinMax = 64 + +; Specify the override for the value of "cross_num_print_missing" +; option for the Cross in Covergroups. If not specified then value +; specified in the "option.cross_num_print_missing" is used. This +; is a runtime option. NOTE: This overrides any "cross_num_print_missing" +; value specified by user in source file and any SVCrossNumPrintMissingDefault +; specified in modelsim.ini. +; SVCrossNumPrintMissing = 0 + +; Specify whether to use the value of "cross_num_print_missing" +; option in report and GUI for the Cross in Covergroups. If not specified then +; cross_num_print_missing is ignored for creating reports and displaying +; covergroups in GUI. Default is 0, which means ignore "cross_num_print_missing". +; UseSVCrossNumPrintMissing = 0 + +; Specify the override for the value of "strobe" option for the +; Covergroup Type. If not specified then value in "type_option.strobe" +; will be used. This is runtime option which forces "strobe" to +; user specified value and supersedes user specified values in the +; SystemVerilog Code. NOTE: This also overrides the compile time +; default value override specified using "SVCovergroupStrobeDefault" +; SVCovergroupStrobe = 0 + +; Override for explicit assignments in source code to "option.goal" of +; SystemVerilog covergroup, coverpoint, and cross. It also overrides the +; default value of "option.goal" (defined to be 100 in the SystemVerilog +; LRM) and the value of modelsim.ini variable "SVCovergroupGoalDefault". +; SVCovergroupGoal = 100 + +; Override for explicit assignments in source code to "type_option.goal" of +; SystemVerilog covergroup, coverpoint, and cross. It also overrides the +; default value of "type_option.goal" (defined to be 100 in the SystemVerilog +; LRM) and the value of modelsim.ini variable "SVCovergroupTypeGoalDefault". +; SVCovergroupTypeGoal = 100 + +; Enforce the 6.3 behavior of covergroup get_coverage() and get_inst_coverage() +; builtin functions, and report. This setting changes the default values of +; option.get_inst_coverage and type_option.merge_instances to ensure the 6.3 +; behavior if explicit assignments are not made on option.get_inst_coverage and +; type_option.merge_instances by the user. There are two vsim command line +; options, -cvg63 and -nocvg63 to override this setting from vsim command line. +; The default value of this variable from release 6.6 onwards is 0. This default +; drives compliance with the clarified behavior in the IEEE 1800-2009 standard. +; SVCovergroup63Compatibility = 0 + +; Enforce the 6.5 default behavior of covergroup get_coverage() builtin +; functions, GUI, and report. This setting changes the default values of +; type_option.merge_instances to ensure the 6.5 default behavior if explicit +; assignments are not made on type_option.merge_instances by the user. +; There are two vsim command line options, -cvgmergeinstances and +; -nocvgmergeinstances to override this setting from vsim command line. +; The default value of this variable from release 6.6 onwards is 0. This default +; drives compliance with the clarified behavior in the IEEE 1800-2009 standard. +; SvCovergroupMergeInstancesDefault = 1 + +; Enable or disable generation of more detailed information about the sampling +; of covergroup, cross, and coverpoints. It provides the details of the number +; of times the covergroup instance and type were sampled, as well as details +; about why covergroup, cross and coverpoint were not covered. A non-zero value +; is to enable this feature. 0 is to disable this feature. Default is 0 +; SVCovergroupSampleInfo = 0 + +; Specify the maximum number of Coverpoint bins in whole design for +; all Covergroups. +; MaxSVCoverpointBinsDesign = 2147483648 + +; Specify maximum number of Coverpoint bins in any instance of a Covergroup +; MaxSVCoverpointBinsInst = 2147483648 + +; Specify the maximum number of Cross bins in whole design for +; all Covergroups. +; MaxSVCrossBinsDesign = 2147483648 + +; Specify maximum number of Cross bins in any instance of a Covergroup +; MaxSVCrossBinsInst = 2147483648 + +; Specify a space delimited list of double quoted TCL style +; regular expressions which will be matched against the text of all messages. +; If any regular expression is found to be contained within any message, the +; status for that message will not be propagated to the UCDB TESTSTATUS. +; If no match is detected, then the status will be propagated to the +; UCDB TESTSTATUS. More than one such regular expression text is allowed, +; and each message text is compared for each regular expression in the list. +; UCDBTestStatusMessageFilter = "Done with Test Bench" "Ignore .* message" + +; Set weight for all PSL/SVA cover directives. Default is 1. +; CoverWeight = 2 + +; Check vsim plusargs. Default is 0 (off). +; 0 = Don't check plusargs +; 1 = Warning on unrecognized plusarg +; 2 = Error and exit on unrecognized plusarg +; CheckPlusargs = 1 + +; Load the specified shared objects with the RTLD_GLOBAL flag. +; This gives global visibility to all symbols in the shared objects, +; meaning that subsequently loaded shared objects can bind to symbols +; in the global shared objects. The list of shared objects should +; be whitespace delimited. This option is not supported on the +; Windows or AIX platforms. +; GlobalSharedObjectList = example1.so example2.so example3.so + +; Run the 0in tools from within the simulator. +; Default is off. +; ZeroIn = 1 + +; Set the options to be passed to the 0in runtime tool. +; Default value set to "". +; ZeroInOptions = "" + +; Initial seed for the random number generator of the root thread (SystemVerilog). +; NOTE: This variable can be overridden with the vsim "-sv_seed" command line switch. +; The default value is 0. +; Sv_Seed = 0 + +; Specify the solver "engine" that vsim will select for constrained random +; generation. +; Valid values are: +; "auto" - automatically select the best engine for the current +; constraint scenario +; "bdd" - evaluate all constraint scenarios using the BDD solver engine +; "act" - evaluate all constraint scenarios using the ACT solver engine +; While the BDD solver engine is generally efficient with constraint scenarios +; involving bitwise logical relationships, the ACT solver engine can exhibit +; superior performance with constraint scenarios involving large numbers of +; random variables related via arithmetic operators (+, *, etc). +; NOTE: This variable can be overridden with the vsim "-solveengine" command +; line switch. +; The default value is "auto". +; SolveEngine = auto + +; Specify if the solver should attempt to ignore overflow/underflow semantics +; for arithmetic constraints (multiply, addition, subtraction) in order to +; improve performance. The "solveignoreoverflow" attribute can be specified on +; a per-call basis to randomize() to override this setting. +; The default value is 0 (overflow/underflow is not ignored). Set to 1 to +; ignore overflow/underflow. +; SolveIgnoreOverflow = 0 + +; Specifies the maximum size that a dynamic array may be resized to by the +; solver. If the solver attempts to resize a dynamic array to a size greater +; than the specified limit, the solver will abort with an error. +; The default value is 2000. A value of 0 indicates no limit. +; SolveArrayResizeMax = 2000 + +; Error message severity when randomize() failure is detected (SystemVerilog). +; 0 = No error 1 = Warning 2 = Error 3 = Failure 4 = Fatal +; The default is 0 (no error). +; SolveFailSeverity = 0 + +; Enable/disable debug information for randomize() failures. +; NOTE: This variable can be overridden with the vsim "-solvefaildbug" command +; line switch. +; The default is 0 (disabled). Set to 1 to enable. +; SolveFailDebug = 0 + +; Specify the maximum size of the solution graph generated by the BDD solver. +; This value can be used to force the BDD solver to abort the evaluation of a +; complex constraint scenario that cannot be evaluated with finite memory. +; This value is specified in 1000s of nodes. +; The default value is 10000. A value of 0 indicates no limit. +; SolveGraphMaxSize = 10000 + +; Specify the maximum number of evaluations that may be performed on the +; solution graph by the BDD solver. This value can be used to force the BDD +; solver to abort the evaluation of a complex constraint scenario that cannot +; be evaluated in finite time. This value is specified in 10000s of evaluations. +; The default value is 10000. A value of 0 indicates no limit. +; SolveGraphMaxEval = 10000 + +; Specify the maximum number of tests that the ACT solver may evaluate before +; abandoning an attempt to solve a particular constraint scenario. +; The default value is 20000000. A value of 0 indicates no limit. +; SolveACTMaxTests = 20000000 + +; Specify the maximum number of operations that the ACT solver may perform +; before abandoning an attempt to solve a particular constraint scenario. The +; value is specified in 1000000s of operations. The default value is 1000. A +; value of 0 indicates no limit. +; SolveACTMaxOps = 1000 + +; Specify the number of times the ACT solver will retry to evaluate a constraint +; scenario that fails due to the SolveACTMaxTests threshold. +; The default value is 0 (no retry). +; SolveACTRetryCount = 0 + +; SolveSpeculateLevel controls whether or not the solver performs speculation +; during the evaluation of a constraint scenario. +; Speculation is an attempt to partition complex constraint scenarios by +; choosing a 'speculation' subset of the variables and constraints. This +; 'speculation' set is solved independently of the remaining constraints. +; The solver then attempts to solve the remaining variables and constraints +; (the 'dependent' set). If this attempt fails, the solver backs up and +; re-solves the 'speculation' set, then retries the 'dependent' set. +; Valid values are: +; 0 - no speculation +; 1 - enable speculation that maintains LRM specified distribution +; 2 - enable other speculation - may yield non-LRM distribution +; Currently, distribution constraints and solve-before constraints are +; used in selecting the 'speculation' sets for speculation level 1. Non-LRM +; compliant speculation includes random variables in condition expressions. +; The default value is 0. +; SolveSpeculateLevel = 0 + +; By default, when speculation is enabled, the solver first tries to solve a +; constraint scenario *without* speculation. If the solver fails to evaluate +; the constraint scenario (due to time/memory limits) then the solver will +; re-evaluate the constraint scenario with speculation. If SolveSpeculateFirst +; is set to 1, the solver will skip the initial non-speculative attempt to +; evaluate the constraint scenario. (Only applies when SolveSpeculateLevel is +; non-zero) +; The default value is 0. +; SolveSpeculateFirst = 0 + +; Specify the maximum bit width of a variable in a conditional expression that +; may be considered as the basis for "conditional" speculation. (Only applies +; when SolveSpeculateLevel=2) +; The default value is 6. +; SolveSpeculateMaxCondWidth = 6 + +; Specify the maximum number of attempts to solve a speculative set of random +; variables and constraints. Exceeding this limit will cause the solver to +; abandon the current speculative set. (Only applies when SolveSpeculateLevel +; is non-zero) +; The default value is 100. +; SolveSpeculateMaxIterations = 100 + +; Specifies whether to attempt speculation on solve-before constraints or +; distribution constraints first. A value of 0 specifies that solve-before +; constraints are attempted first as the basis for speculative randomization. +; A value of 1 specifies that distribution constraints are attempted first +; as the basis for speculative randomization. +; The default value is 0. +; SolveSpeculateDistFirst = 0 + +; If the non-speculative BDD solver fails to evaluate a constraint scenario +; (due to time/memory limits) then the solver can be instructed to automatically +; re-evaluate the constraint scenario with the ACT solver engine. Set +; SolveACTbeforeSpeculate to 1 to enable this feature. +; The default value is 0 (do not re-evaluate with the ACT solver). +; SolveACTbeforeSpeculate = 0 + +; Use SolveFlags to specify options that will guide the behavior of the +; constraint solver. These options may improve the performance of the +; constraint solver for some testcases, and decrease the performance of the +; constraint solver for others. +; Valid flags are: +; i = disable bit interleaving for >, >=, <, <= constraints (BDD engine) +; n = disable bit interleaving for all constraints (BDD engine) +; r = reverse bit interleaving (BDD engine) +; The default value is "" (no options). +; SolveFlags = + +; Specify random sequence compatiblity with a prior letter release. This +; option is used to get the same random sequences during simulation as +; as a prior letter release. Only prior letter releases (of the current +; number release) are allowed. +; NOTE: Only those random sequence changes due to solver optimizations are +; reverted by this variable. Random sequence changes due to solver bugfixes +; cannot be un-done. +; NOTE: This variable can be overridden with the vsim "-solverev" command +; line switch. +; Default value set to "" (no compatibility). +; SolveRev = + +; Environment variable expansion of command line arguments has been depricated +; in favor shell level expansion. Universal environment variable expansion +; inside -f files is support and continued support for MGC Location Maps provide +; alternative methods for handling flexible pathnames. +; The following line may be uncommented and the value set to 1 to re-enable this +; deprecated behavior. The default value is 0. +; DeprecatedEnvironmentVariableExpansion = 0 + +; Turn on/off collapsing of bus ports in VCD dumpports output +DumpportsCollapse = 1 + +; Location of Multi-Level Verification Component (MVC) installation. +; The default location is the product installation directory. +; MvcHome = $MODEL_TECH/... + +; Initialize SystemVerilog enums using the base type's default value +; instead of the leftmost value. +; EnumBaseInit = 1 + +[lmc] +; The simulator's interface to Logic Modeling's SmartModel SWIFT software +libsm = $MODEL_TECH/libsm.sl +; The simulator's interface to Logic Modeling's SmartModel SWIFT software (Windows NT) +; libsm = $MODEL_TECH/libsm.dll +; Logic Modeling's SmartModel SWIFT software (HP 9000 Series 700) +; libswift = $LMC_HOME/lib/hp700.lib/libswift.sl +; Logic Modeling's SmartModel SWIFT software (IBM RISC System/6000) +; libswift = $LMC_HOME/lib/ibmrs.lib/swift.o +; Logic Modeling's SmartModel SWIFT software (Sun4 Solaris) +; libswift = $LMC_HOME/lib/sun4Solaris.lib/libswift.so +; Logic Modeling's SmartModel SWIFT software (Windows NT) +; libswift = $LMC_HOME/lib/pcnt.lib/libswift.dll +; Logic Modeling's SmartModel SWIFT software (non-Enterprise versions of Linux) +; libswift = $LMC_HOME/lib/x86_linux.lib/libswift.so +; Logic Modeling's SmartModel SWIFT software (Enterprise versions of Linux) +; libswift = $LMC_HOME/lib/linux.lib/libswift.so + +; The simulator's interface to Logic Modeling's hardware modeler SFI software +libhm = $MODEL_TECH/libhm.sl +; The simulator's interface to Logic Modeling's hardware modeler SFI software (Windows NT) +; libhm = $MODEL_TECH/libhm.dll +; Logic Modeling's hardware modeler SFI software (HP 9000 Series 700) +; libsfi = /lib/hp700/libsfi.sl +; Logic Modeling's hardware modeler SFI software (IBM RISC System/6000) +; libsfi = /lib/rs6000/libsfi.a +; Logic Modeling's hardware modeler SFI software (Sun4 Solaris) +; libsfi = /lib/sun4.solaris/libsfi.so +; Logic Modeling's hardware modeler SFI software (Windows NT) +; libsfi = /lib/pcnt/lm_sfi.dll +; Logic Modeling's hardware modeler SFI software (Linux) +; libsfi = /lib/linux/libsfi.so + +[msg_system] +; Change a message severity or suppress a message. +; The format is: = [,...] +; suppress can be used to achieve +nowarn functionality +; The format is: suppress = ,,[,,...] +; Examples: +; note = 3009 +; warning = 3033 +; error = 3010,3016 +; fatal = 3016,3033 +; suppress = 3009,3016,3043 +; suppress = 3009,CNNODP,3043,TFMPC +; suppress = 8683,8684 +; The command verror can be used to get the complete +; description of a message. + +; Control transcripting of Verilog display system task messages and +; PLI/FLI print function call messages. The system tasks include +; $display[bho], $strobe[bho], Smonitor{bho], and $write[bho]. They +; also include the analogous file I/O tasks that write to STDOUT +; (i.e. $fwrite or $fdisplay). The PLI/FLI calls include io_printf, +; vpi_printf, mti_PrintMessage, and mti_PrintFormatted. The default +; is to have messages appear only in the transcript. The other +; settings are to send messages to the wlf file only (messages that +; are recorded in the wlf file can be viewed in the MsgViewer) or +; to both the transcript and the wlf file. The valid values are +; tran {transcript only (default)} +; wlf {wlf file only} +; both {transcript and wlf file} +; displaymsgmode = tran + +; Control transcripting of elaboration/runtime messages not +; addressed by the displaymsgmode setting. The default is to +; have messages appear in the transcript and recorded in the wlf +; file (messages that are recorded in the wlf file can be viewed +; in the MsgViewer). The other settings are to send messages +; only to the transcript or only to the wlf file. The valid +; values are +; both {default} +; tran {transcript only} +; wlf {wlf file only} +; msgmode = both Index: trunk/examples/packet_gen/transcript =================================================================== --- trunk/examples/packet_gen/transcript (nonexistent) +++ trunk/examples/packet_gen/transcript (revision 19) @@ -0,0 +1,52 @@ +vsim work.packet_gen_ttb +# // ModelSim PE Student Edition 10.0a Feb 20 2011 +# // +# // Copyright 1991-2011 Mentor Graphics Corporation +# // All Rights Reserved. +# // +# // THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION +# // WHICH IS THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS +# // LICENSORS AND IS SUBJECT TO LICENSE TERMS. +# // +# // +# // NOT FOR CORPORATE OR PRODUCTION USE. +# // THE ModelSim PE Student Edition IS NOT A SUPPORTED PRODUCT. +# // FOR HIGHER EDUCATION PURPOSES ONLY +# // +# vsim work.packet_gen_ttb +# Loading std.standard +# Loading std.textio(body) +# Loading ieee.std_logic_1164(body) +# Loading ieee.std_logic_arith(body) +# Loading work.tb_pkg(body) +# Loading work.pgen +# Loading work.packet_gen_ttb(struct) +# Loading ieee.math_real(body) +# Loading synthworks.randombasepkg(body) +# Loading ieee.numeric_std(body) +# Loading ieee.std_logic_textio(body) +# Loading synthworks.sortlistpkg_int(body) +# Loading synthworks.randompkg(body) +# Loading work.packet_gen(bhv) +# Loading work.packet_gen_tb(bhv) +run -sll +# Unknown option: sll +# ** Error: (vsim-4005) Invalid argument '-sll'. +# Usage: run [ []] | -all | -continue | -next | -step | -over | -out | -init | -final +run -all +# data.dat +# ** Note: Out of bounds write attempt in packet_gen 0, noting done. +# +# Time: 220513 ps Iteration: 2 Instance: /packet_gen_ttb/dut +# TEST_INST had 1 parameters passed. +# TEST_INST had 2 parameters passed. +# TEST_INST had 3 parameters passed. +# TEST_INST had 4 parameters passed. +# TEST_INST had 5 parameters passed. +# TEST_INST had 6 parameters passed. +# TEST_INST had 0 parameters passed. +# TEST_INST had 1 parameters passed. +# TEST_INST had 6 parameters passed. +# ** Failure: Test Finished with NO errors!! +# Time: 260 ns Iteration: 1 Process: /packet_gen_ttb/tb/Read_file File: c:/work/projects/tb_2011beta2.0/examples/packet_gen/vhdl/packet_gen_tb_bhv.vhd +# Break in Process Read_file at c:/work/projects/tb_2011beta2.0/examples/packet_gen/vhdl/packet_gen_tb_bhv.vhd line 207 Index: trunk/examples/packet_gen/build_tb.bat =================================================================== --- trunk/examples/packet_gen/build_tb.bat (nonexistent) +++ trunk/examples/packet_gen/build_tb.bat (revision 19) @@ -0,0 +1,15 @@ +ECHO OFF + +vlib work +vlib synthworks + +vcom -work synthworks -2008 C:\work\vhdl2008c\RandomPkg_2_0\SortListPkg_int.vhd +vcom -work synthworks -2008 C:\work\vhdl2008c\RandomPkg_2_0\RandomBasePkg.vhd +vcom -work synthworks -2008 C:\work\vhdl2008c\RandomPkg_2_0\RandomPkg.vhd + +vcom vhdl/tb_pkg_header.vhd vhdl/tb_pkg_body.vhd + +vcom -quiet -2008 vhdl/packet_gen.vhd + +vcom -2008 -quiet vhdl/packet_gen_tb_ent.vhd vhdl/packet_gen_tb_bhv.vhd +vcom -quiet vhdl/packet_gen_ttb_ent.vhd vhdl/packet_gen_ttb_str.vhd Index: trunk/examples/packet_gen/vhdl/packet_gen_ttb_ent.vhd =================================================================== --- trunk/examples/packet_gen/vhdl/packet_gen_ttb_ent.vhd (nonexistent) +++ trunk/examples/packet_gen/vhdl/packet_gen_ttb_ent.vhd (revision 19) @@ -0,0 +1,37 @@ +------------------------------------------------------------------------------- +-- Copyright ----------------------------------- +-- All Rights Reserved +------------------------------------------------------------------------------- +-- $Author: $ +-- +-- $date: $ +-- +-- $Id: $ +-- +-- $Source: $ +-- +-- Description : +-- This file was generated by TTB Gen Plus Beta 2.0 +-- on 01 May 2011 21:23:14 +------------------------------------------------------------------------------ +-- This software contains concepts confidential to ---------------- +-- ---------. and is only made available within the terms of a written +-- agreement. +------------------------------------------------------------------------------- +-- Revision History: +-- $Log: $ +-- +------------------------------------------------------------------------------- + +library IEEE; +--library dut_lib; +use IEEE.STD_LOGIC_1164.all; +use work.tb_pkg.all; +use work.pgen.all; +--use dut_lib.all; + +entity packet_gen_ttb is + generic ( + stimulus_file: string := "stm/stimulus_file.stm" + ); +end packet_gen_ttb; Index: trunk/examples/packet_gen/vhdl/packet_gen.vhd =================================================================== --- trunk/examples/packet_gen/vhdl/packet_gen.vhd (nonexistent) +++ trunk/examples/packet_gen/vhdl/packet_gen.vhd (revision 19) @@ -0,0 +1,331 @@ +---------------- +-- simple packet generator +-- +------------------------------------------------------------------------------ +-- First we start of with the definition of the packet array type +-- and the pack_out record for pins on the entity and comp. +-- The size of the whole system can be changed by changing the +-- array and record types. +library IEEE; +use IEEE.STD_LOGIC_1164.all; + +package pgen is + + type arr128x8 is array(0 to 127) of std_logic_vector(7 downto 0); + + type pack_out is record + dout : arr128x8; + drdy : std_logic; + end record; +end package pgen; + +------------------------------------------------------------------------------ +-- this is an example packet generator for BFM's +-- for details of the full functionality, see the accomaning documentation +-- +-- the packet_gen implementation demonstrates: +-- self generating data, incrementing and random +-- data loading from a file and file opening +-- setting a text entity from the stimulus file, i.e. the file name +-- direct setting of text data from the stimulus file. +-- use of the new stimulus port definition. +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use std.textio.all; +use work.tb_pkg.all; +library synthworks; + use SynthWorks.RandomBasePkg.all; + use SynthWorks.RandomPkg.all; +use work.pgen.all; + +entity packet_gen is + generic ( + pgen_id : integer := 0 + ); + port ( + packet_out : out pack_out; + request : in std_logic; + fname : in stm_text; + -- env access port + STM_IN : in stm_sctl; + STM_OUT : out stm_sack + ); +end packet_gen; + +architecture bhv of packet_gen is + + -- create the file handle for loading data from file. + file load_file : text; + + ----------------------------------------------------------------------------- + -- driven by STIM_access + signal stim_addr: std_logic_vector(31 downto 0); + signal stim_write_dat: std_logic_vector(31 downto 0); + signal rd_req: std_logic := '0'; + signal wr_req: std_logic := '0'; + ----------------------------------------------------------------------------- + -- driven by REG_access + signal stim_read_dat: std_logic_vector(31 downto 0); + signal req_ack: std_logic := '0'; + signal open_lfile : std_logic := '0'; + -- the addressable register set + signal cnt_reg: std_logic_vector(31 downto 0); + signal seed_reg: std_logic_vector(31 downto 0) := "00010001000111000011000010000100"; + signal config_reg: std_logic_vector(31 downto 0); + signal errors_reg: std_logic_vector(31 downto 0); + signal stm_idx : integer; + signal stm_wdata : std_logic_vector(7 downto 0); + signal stm_w : std_logic; + + signal clear_trig: std_logic := '0'; + signal ready : std_logic; + + +begin + +output_drive: + process (STM_IN.rst_n, seed_reg, request, open_lfile, stm_w) + variable v_dat_array : arr128x8; --<< array type from pgen package + variable v_tmp_dat : unsigned(7 downto 0); + variable v_randv : RandomPType; + variable v_tmp_int : integer; + variable v_stat : file_open_status; + variable rline : line; + variable j : integer; + variable incp : std_logic; + variable v_fisopen : boolean := false; + begin + -- if we get a request and are enabled + if((STM_IN.rst_n'event and STM_IN.rst_n = '0') or seed_reg'event) then + v_tmp_int := to_uninteger(seed_reg); + v_randv.InitSeed(v_tmp_int); + packet_out.dout <= (others => (others => '0')); + packet_out.drdy <= '0'; + incp := '0'; + if(v_fisopen = true) then + file_close(load_file); + v_fisopen := false; + end if; + elsif(request'event and request = '1' and cnt_reg(0) = '1') then + case config_reg(3 downto 0) is + -- inc pattern + when "0000" => + if(incp = '0') then + v_tmp_dat := (others => '0'); + for i in 0 to v_dat_array'length-1 loop + v_dat_array(i) := std_logic_vector(v_tmp_dat); + v_tmp_dat := v_tmp_dat + 1; + end loop; + incp := '1'; + end if; + -- random pattern + when "0001" => + v_tmp_dat := (others => '0'); + for i in 0 to v_dat_array'length-1 loop +-- v_tmp_int := v_randv.RandInt(0, 255); + v_dat_array(i) := std_logic_vector(conv_unsigned(v_randv.RandInt(0, 255),8)); + end loop; + incp := '0'; + -- file load + when "0010" => + j := 0; + while(not endfile(load_file) and j < v_dat_array'length-1) loop + readline(load_file, rline); + v_dat_array(j)(7 downto 4) := c2std_vec(rline(1)); + v_dat_array(j)(3 downto 0) := c2std_vec(rline(2)); + j := j + 1; + end loop; + incp := '0'; + -- user input mode, do not generate as user filled through stimulus + when "0011" => + null; + incp := '0'; + when others => + -- do an assert here + assert(false) + report "Invalid control mode for Patern Generator, nothing done." & LF + severity note; + end case; + packet_out.dout <= v_dat_array; + -- if there was an open file event + elsif(open_lfile'event and open_lfile = '1') then + -- if a file is open, close it first + if(v_fisopen = true) then + file_close(load_file); + end if; + -- open the file + file_open(v_stat, load_file, fname, read_mode); + assert(v_stat = open_ok) + report LF & "Error: Unable to open data file " & fname + severity failure; + v_fisopen := true; + -- if there was a stumuls write, write the array index + elsif(stm_w'event and stm_w = '1') then + v_dat_array(stm_idx) := stm_wdata; + end if; +end process output_drive; + +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +-- STIM Reg Access process +REG_access: + process + + variable v_temp_int: integer; + variable v_reload: integer := 0; + variable v_tmp_int: integer; + + begin + -- reset from stimulus system + if(STM_IN.rst_n'event and STM_IN.rst_n = '0') then + v_reload := 0; + stm_w <= '0'; + -- standard registers + stim_read_dat <= (others => '0'); + req_ack <= '0'; + cnt_reg <= (others => '0'); + config_reg <= (others => '0'); + errors_reg <= (others => '0'); + + -- if is a write access + elsif(wr_req' event and wr_req = '1') then + -- create index 0 to 63 + v_temp_int := conv_integer(unsigned(stim_addr(6 downto 0))); + -- create first level of addressing + case stim_addr(31 downto 12) is + -- first level decode + when "00000000000000000000" => + -- create register access level of addressing + -- seconde level of decode + case stim_addr(11 downto 0) is + when "000000000000" => + cnt_reg <= stim_write_dat; + open_lfile <= stim_write_dat(1); + when "000000000001" => + config_reg <= stim_write_dat; + when "000000000010" => + assert(false) + report ">>>> ERROR: The errors register is read only!!" & LF + severity note; +-- errors_reg <= stim_write_dat; + when "000000000011" => + seed_reg <= stim_write_dat; + +-- when "000000000100" => +-- access0_word <= stim_write_dat; +-- action_trig <= '1'; +-- when "000000000101" => +-- access1_word <= stim_write_dat; + + when others => + assert(false) + report "Out of bounds write attempt in packet_gen " & integer'image(pgen_id) & + ", noting done." & LF + severity note; + end case; + -- array addressing + when "00000000000000000001" => + if(stim_addr(11 downto 7) /= "00000") then + assert(false) + report "Out of bounds write attempt in packet_gen " & integer'image(pgen_id) & + ", noting done." & LF + severity note; + else + stm_idx <= v_temp_int; + stm_wdata <= stim_write_dat(7 downto 0); + stm_w <= '1'; + end if; + when others => + assert(false) + report "Out of bounds write attempt in packet_gen " & integer'image(pgen_id) & + ", noting done." & LF + severity note; + end case; + -- acknowlage the request + req_ack <= '1'; + wait until wr_req'event and wr_req = '0'; + req_ack <= '0'; + + -- if is a read + elsif (rd_req' event and rd_req = '1') then + -- create first level of addressing + case stim_addr(31 downto 12) is + -- first level decode + when "00000000000000000000" => + -- create register access level of addressing + -- seconde level of decode + case stim_addr(11 downto 0) is + when "000000000010" => + stim_read_dat <= errors_reg; + errors_reg <= (others => '0'); + when "000000000011" => + stim_read_dat <= seed_reg; + + when others => + assert(false) + report "Read Location access ERROR: packet_gen" & integer'image(pgen_id) & + ", noting done." & LF + severity note; + end case; + when others => + assert(false) + report "Read Location access ERROR: packet_gen" & integer'image(pgen_id) & + ", noting done." & LF + severity note; + end case; + -- acknowlage the request + req_ack <= '1'; + wait until rd_req'event and rd_req = '0'; + req_ack <= '0'; + + end if; + -- clear the trigger signals + cnt_reg(1) <= '0'; + open_lfile <= '0'; + stm_w <= '0'; + + wait on rd_req, wr_req, STM_IN.rst_n, clear_trig; + end process REG_access; + +------------------------------------------------------------------------------- +-- STIM Access port processes +-- +STIM_access: + process + begin + if(STM_IN.rst_n' event and STM_IN.rst_n = '0') then + STM_OUT <= stm_neut; + -- if read cycle + elsif(STM_IN.req_n' event and STM_IN.req_n = '0' and STM_IN.rwn = '1') then + stim_addr <= STM_IN.addr; + rd_req <= '1'; + wait until req_ack' event and req_ack = '1'; + STM_OUT.rdat <= stim_read_dat; + rd_req <= '0'; + wait for 1 ps; + STM_OUT.ack_n <= '0'; + wait until STM_IN.req_n' event and STM_IN.req_n = '1'; + wait for 1 ps; + STM_OUT <= stm_neut; + + -- if Write + elsif(STM_IN.req_n' event and STM_IN.req_n = '0' and STM_IN.rwn = '0') then + stim_addr <= STM_IN.addr; + stim_write_dat <= STM_IN.wdat; + wr_req <= '1'; + wait until req_ack' event and req_ack = '1'; + wait for 1 ps; + wr_req <= '0'; + wait for 1 ps; + STM_OUT.ack_n <= '0'; + wait until STM_IN.req_n' event and STM_IN.req_n = '1'; + wait for 1 ps; + STM_OUT <= stm_neut; + end if; + + STM_OUT.rdy_n <= ready; + wait on STM_IN.req_n, STM_IN.rst_n, ready; + end process STIM_access; + +end bhv; \ No newline at end of file Index: trunk/examples/packet_gen/vhdl/packet_gen_ttb_str.vhd =================================================================== --- trunk/examples/packet_gen/vhdl/packet_gen_ttb_str.vhd (nonexistent) +++ trunk/examples/packet_gen/vhdl/packet_gen_ttb_str.vhd (revision 19) @@ -0,0 +1,84 @@ +------------------------------------------------------------------------------- +-- Copyright ----------------------------------- +-- All Rights Reserved +------------------------------------------------------------------------------- +-- $Author: $ +-- +-- $date: $ +-- +-- $Id: $ +-- +-- $Source: $ +-- +-- Description : +-- This file was generated by TTB Gen Plus Beta 2.0 +-- on 01 May 2011 21:23:14 +------------------------------------------------------------------------------ +-- This software contains concepts confidential to ---------------- +-- ---------. and is only made available within the terms of a written +-- agreement. +------------------------------------------------------------------------------- +-- Revision History: +-- $Log: $ +-- +------------------------------------------------------------------------------- + + +architecture struct of packet_gen_ttb is + +component packet_gen + port ( + packet_out : out pack_out; + request : in std_logic; + fname : in stm_text; + stm_in : in stm_sctl; + stm_out : out stm_sack + ); +end component; + +component packet_gen_tb + generic ( + stimulus_file: in string + ); + port ( + packet_out : in pack_out; + request : buffer std_logic; + fname : buffer stm_text; + stm_in : buffer stm_sctl; + stm_out : in stm_sack + ); +end component; + +--for all: packet_gen use entity dut_lib.packet_gen(str); +for all: packet_gen_tb use entity work.packet_gen_tb(bhv); + + signal temp_packet_out : pack_out; + signal temp_request : std_logic; + signal temp_file_name : stm_text; + signal temp_stm_in : stm_sctl; + signal temp_stm_out : stm_sack; + +begin + +dut: packet_gen + port map( + packet_out => temp_packet_out, + request => temp_request, + fname => temp_file_name, + stm_in => temp_stm_in, + stm_out => temp_stm_out + ); + +tb: packet_gen_tb + generic map( + stimulus_file => stimulus_file + ) + port map( + packet_out => temp_packet_out, + request => temp_request, + fname => temp_file_name, + stm_in => temp_stm_in, + stm_out => temp_stm_out + ); + +end struct; Index: trunk/examples/packet_gen/vhdl/tb_pkg_body.vhd =================================================================== --- trunk/examples/packet_gen/vhdl/tb_pkg_body.vhd (nonexistent) +++ trunk/examples/packet_gen/vhdl/tb_pkg_body.vhd (revision 19) @@ -0,0 +1,1836 @@ +------------------------------------------------------------------------------- +-- Copyright 2011 Ken Campbell +------------------------------------------------------------------------------- +-- $Author: sckoarn $ +-- +-- $Date: $ +-- +-- $Id: $ +-- +-- $Source: $ +-- +-- Description : The the testbench package body file. +-- GNU release 2 Beta. +-- +------------------------------------------------------------------------------ +--This file is part of The VHDL Test Bench. +-- +-- The VHDL Test Bench is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- The VHDL Test Bench is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with The VHDL Test Bench; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +------------------------------------------------------------------------------- + +package body tb_pkg is + +------------------------------------------------------------------------------- +-- FUNCTION Defs +------------------------------------------------------------------------------- +-- is_digit + function is_digit(constant c: in character) return boolean is + variable rtn : boolean; + begin + if (c >= '0' and c <= '9') then + rtn := true; + else + rtn := false; + end if; + return rtn; + end is_digit; +-------------------------------------- +-- is_space + function is_space(constant c: in character) return boolean is + variable rtn : boolean; + begin + if(c = ' ' or c = ht) then + rtn := true; + else + rtn := false; + end if; + return rtn; + end is_space; +------------------------------------------------------------------------------ +-- to_char + function ew_to_char(int: integer) return character is + variable c: character; + begin + c := nul; + case int is + when 0 => c := '0'; + when 1 => c := '1'; + when 2 => c := '2'; + when 3 => c := '3'; + when 4 => c := '4'; + when 5 => c := '5'; + when 6 => c := '6'; + when 7 => c := '7'; + when 8 => c := '8'; + when 9 => c := '9'; + when 10 => c := 'A'; + when 11 => c := 'B'; + when 12 => c := 'C'; + when 13 => c := 'D'; + when 14 => c := 'E'; + when 15 => c := 'F'; + when others => + assert(false) + report LF & "Error: ew_to_char was given a non Number didgit." + severity failure; + end case; + + return c; + end ew_to_char; + +------------------------------------------------------------------------------- +-- ew_str_cat + function ew_str_cat(s1: stm_text; + s2: text_field) return stm_text is + + variable i: integer; + variable j: integer; + variable sc: stm_text; + + begin + sc := s1; + i := 1; + while(sc(i) /= nul) loop + i := i + 1; + end loop; + j := 1; + while(s2(j) /= nul) loop + sc(i) := s2(j); + i := i + 1; + j := j + 1; + end loop; + + return sc; + end ew_str_cat; + +------------------------------------------------------------------------------- +-- fld_len field length +-- inputs : string of type text_field +-- return : integer number of non 'nul' chars +function fld_len(s : in text_field) return integer is + variable i: integer := 1; + begin + while(s(i) /= nul) loop + i := i + 1; + end loop; + return (i - 1); + end fld_len; +------------------------------------------------------------------------------ +-- c2int convert character to integer +function c2int(c: in character) return integer is + variable i: integer; +begin + i := -1; + case c is + when '0' => i := 0; + when '1' => i := 1; + when '2' => i := 2; + when '3' => i := 3; + when '4' => i := 4; + when '5' => i := 5; + when '6' => i := 6; + when '7' => i := 7; + when '8' => i := 8; + when '9' => i := 9; + when others => + assert(false) + report LF & "Error: c2int was given a non Number didgit." + severity failure; + end case; + return i; +end c2int; +------------------------------------------------------------------------------- +-- str2integer Convert a string to integer number. +-- inputs : string +-- output : int value +function str2integer(str: in string) return integer is + variable l: integer; + variable j: integer := 1; + variable rtn: integer := 0; +begin + l := fld_len(str); + + for i in l downto 1 loop + rtn := rtn + (c2int(str(j)) *(10**(i - 1))); + j := j + 1; + end loop; + + return rtn; +end str2integer; +------------------------------------------------------------------------------- +-- hex2integer convert hex Stimulus field to integer +-- inputs : string of type text_field containing only Hex numbers +-- return : integer value +function hex2integer(hex_number: in text_field; + file_name: in text_line; + line: in integer) return integer is + variable len: integer; + variable temp_field: text_field; + variable temp_int: integer; + variable power: integer; + variable int_number: integer; + begin + len := fld_len(hex_number); + power := 0; + temp_int := 0; + for i in len downto 1 loop + case hex_number(i) is + when '0' => + int_number := 0; + when '1' => + int_number := 1; + when '2' => + int_number := 2; + when '3' => + int_number := 3; + when '4' => + int_number := 4; + when '5' => + int_number := 5; + when '6' => + int_number := 6; + when '7' => + int_number := 7; + when '8' => + int_number := 8; + when '9' => + int_number := 9; + when 'a' | 'A'=> + int_number := 10; + when 'b' | 'B'=> + int_number := 11; + when 'c' | 'C'=> + int_number := 12; + when 'd' | 'D'=> + int_number := 13; + when 'e' | 'E'=> + int_number := 14; + when 'f' | 'F'=> + int_number := 15; + when others => + assert(false) + report LF & "Error: hex2integer found non Hex didgit on line " + & (integer'image(line)) & " of file " & file_name + severity failure; + end case; + + temp_int := temp_int + (int_number *(16 ** power)); + power := power + 1; + end loop; + + return temp_int; + end hex2integer; +------------------------------------------------------------------------------- +-- convert character to 4 bit vector +-- input character +-- output std_logic_vector 4 bits +function c2std_vec(c: in character) return std_logic_vector is +begin + case c is + when '0' => return "0000"; + when '1' => return "0001"; + when '2' => return "0010"; + when '3' => return "0011"; + when '4' => return "0100"; + when '5' => return "0101"; + when '6' => return "0110"; + when '7' => return "0111"; + when '8' => return "1000"; + when '9' => return "1001"; + when 'a' | 'A' => return "1010"; + when 'b' | 'B' => return "1011"; + when 'c' | 'C' => return "1100"; + when 'd' | 'D' => return "1101"; + when 'e' | 'E' => return "1110"; + when 'f' | 'F' => return "1111"; + when others => + assert(false) + report LF & "Error: c2std_vec found non Hex didgit on file line " + severity failure; + return "XXXX"; + end case; +end c2std_vec; +------------------------------------------------------------------------------- +-- std_vec2c convert 4 bit std_vector to a character +-- input std_logic_vector 4 bits +-- output character +function std_vec2c(vec: in std_logic_vector(3 downto 0)) return character is +begin + case vec is + when "0000" => return '0'; + when "0001" => return '1'; + when "0010" => return '2'; + when "0011" => return '3'; + when "0100" => return '4'; + when "0101" => return '5'; + when "0110" => return '6'; + when "0111" => return '7'; + when "1000" => return '8'; + when "1001" => return '9'; + when "1010" => return 'A'; + when "1011" => return 'B'; + when "1100" => return 'C'; + when "1101" => return 'D'; + when "1110" => return 'E'; + when "1111" => return 'F'; + when others => + assert(false) + report LF & "Error: std_vec2c found non-binary didgit in vec " + severity failure; + return 'X'; + end case; +end std_vec2c; +------------------------------------------------------------------------------- +-- bin2integer convert bin Stimulus field to integer +-- inputs : string of type text_field containing only binary numbers +-- return : integer value +function bin2integer(bin_number: in text_field; + file_name: in text_line; + line: in integer) return integer is + variable len: integer; + variable temp_field: text_field; + variable temp_int: integer; + variable power: integer; + variable int_number: integer; + begin + len := fld_len(bin_number); + power := 0; + temp_int := 0; + for i in len downto 1 loop + case bin_number(i) is + when '0' => + int_number := 0; + when '1' => + int_number := 1; + when others => + assert(false) + report LF & "Error: bin2integer found non Binary didgit on line " + & (integer'image(line)) & " of file " & file_name + severity failure; + end case; + + if (int_number = 1) then + temp_int := temp_int + (int_number *(2 ** power)); + end if; + power := power + 1; + end loop; + + return temp_int; + end bin2integer; +------------------------------------------------------------------------------- +-- stim_to_integer convert Stimulus field to integer +-- inputs : string of type text_field "stimulus format of number" +-- return : integer value +function stim_to_integer(field: in text_field; + file_name: in text_line; + line: in integer) return integer is + variable len: integer; + variable value: integer := 1; + variable temp_str : string(1 to 48); + begin + len := fld_len(field); + + case field(1) is + when 'x' | 'h' => + value := 2; + while(field(value) /= nul) loop + temp_str(value - 1) := field(value); + value := value + 1; + end loop; + value := hex2integer(temp_str,file_name,line); + when 'b' => + value := 2; + while(field(value) /= nul) loop + temp_str(value - 1) := field(value); + value := value + 1; + end loop; + value := bin2integer(temp_str,file_name,line); + when others => +-- value := from_string(field(1 to len)); + value := str2integer(field); + end case; + return value; + end stim_to_integer; + +------------------------------------------------------------------------------- +-- to_str function with base parameter +-- Convert integer to number base + function tb_to_str(int: integer; b: base) return text_field is + + variable temp : text_field ; + variable temp1 : text_field ; + variable radix : integer := 0; + variable num : integer := 0; + variable power : integer := 1; + variable len : integer := 1; + variable pre : string(1 to 2); + variable i : integer; + variable j : integer; + variable vec : std_logic_vector(31 downto 0); + + begin + + num := int; + temp := (others => nul); + case b is + when bin => + radix := 2; -- depending on what + pre := "0b"; + when oct => + radix := 8; -- base the number is + pre := "0o"; + when hex => + radix := 16; -- to be displayed as + pre := "0x"; + when dec => + radix := 10; -- choose a radix range + pre := (others => nul); + end case ; + -- Now jump through Hoops because of sign + if(num < 0 and b = hex) then + vec := std_logic_vector(conv_unsigned(int, 32)); + temp(1) := std_vec2c(vec(31 downto 28)); + temp(2) := std_vec2c(vec(27 downto 24)); + temp(3) := std_vec2c(vec(23 downto 20)); + temp(4) := std_vec2c(vec(19 downto 16)); + temp(5) := std_vec2c(vec(15 downto 12)); + temp(6) := std_vec2c(vec(11 downto 8)); + temp(7) := std_vec2c(vec(7 downto 4)); + temp(8) := std_vec2c(vec(3 downto 0)); + else + while num >= radix loop -- determine how many + len := len + 1; -- characters required + num := num / radix; -- to represent the + end loop ; -- number. + for i in len downto 1 loop -- convert the number to + temp(i) := ew_to_char(int/power mod radix); -- a string starting + power := power * radix; -- with the right hand + end loop ; -- side. + end if; + -- add prefix if is one + if(pre(1) /= nul) then + temp1 := temp; + i := 1; + j := 3; + temp(1 to 2) := pre; + while(temp1(i) /= nul) loop + temp(j) := temp1(i); + i := i + 1; + j := j + 1; + end loop; + end if; + + return temp; + + end tb_to_str; + +--------------------------------------------------------------------------------------- +-- convert std_logic_vector to an unsigned integer + function to_uninteger ( constant vect : in std_logic_vector + ) return integer is + variable result : integer := 0; + variable len : integer := vect'length; + variable idx : integer; + variable tmp_str : text_field; + variable file_name: text_line; + begin + -- point to start of string + idx := 1; + -- convert std_logic_vector to text_field + for i in len - 1 downto 0 loop + if(vect(i) = '1') then + tmp_str(idx) := '1'; + elsif(vect(i) = '0') then + tmp_str(idx) := '0'; + else + assert(false) + report LF & "ERROR: Non 0/1 value found in std_logic_vector passed to to_uninteger function!!" & LF & + "Returning 0." + severity note; + return result; + end if; + idx := idx + 1; + end loop; + -- call bin txt to int fuction with dummy fn and sequ idx + result := bin2integer(tmp_str, file_name, idx); + return result; + + end to_uninteger; + + +-------------------- +-- stm neut overloaded function to set any stimulus bus into neutral state + function stm_neut return stm_sctl is + variable tmp : stm_sctl; + begin + tmp.rst_n := '1'; + tmp.addr := (others => 'Z'); + tmp.wdat := (others => 'Z'); + tmp.rwn := 'Z'; + tmp.req_n := 'Z'; + return tmp; + end stm_neut; + + function stm_neut return stm_sack is + variable tmp : stm_sack; + begin + tmp.rdat := (others => 'Z'); + tmp.ack_n := '1'; + tmp.rdy_n := '1'; + tmp.irq_n := '1'; + return tmp; + end stm_neut; +-------------------------------------------------------------------------------- +-- access_variable +-- inputs: +-- Text field containing variable +-- outputs: +-- value $VAR returns Value of VAR +-- value VAR returns index of VAR +-- +-- valid is 1 if valid 0 if not + procedure access_variable(variable var_list : in var_field_ptr; + variable var : in text_field; + variable value : out integer; + variable valid : out integer) is + variable l : integer; + variable l_2 : integer; + variable var_ptr : var_field_ptr; + variable temp_field : text_field; + variable ptr : integer := 0; -- 0 is index, 1 is pointer + begin + l := fld_len(var); + valid := 0; + -- if the variable is a special + if(var(1) = '=') then + value := 0; + valid := 1; + elsif(var(1 to 2) = ">=") then + value := 4; + valid := 1; + elsif(var(1 to 2) = "<=") then + value := 5; + valid := 1; + elsif(var(1) = '>') then + value := 1; + valid := 1; + elsif(var(1) = '<') then + value := 2; + valid := 1; + elsif(var(1 to 2) = "!=") then + value := 3; + valid := 1; + + else + if(var(1) = '$') then + ptr := 1; -- this is a pointer + for i in 2 to l loop + temp_field(i-1) := var(i); + end loop; + else + temp_field := var; + end if; + + var_ptr := var_list; + while(var_ptr.next_rec /= null) loop + -- if we have a match + if(temp_field = var_ptr.var_name) then + if(ptr = 1) then + value := var_ptr.var_value; + valid := 1; + else + value := var_ptr.var_index; + valid := 1; + end if; + exit; + end if; + var_ptr := var_ptr.next_rec; + end loop; + + -- if we have a match and was the last record + if(var_ptr.next_rec = null and temp_field = var_ptr.var_name) then + if(ptr = 1) then + value := var_ptr.var_value; + valid := 1; + else + value := var_ptr.var_index; + valid := 1; + end if; + end if; + end if; + end access_variable; +-------------------------------------------------------------------------------- +-- index_variable +-- inputs: +-- index: the index of the variable being accessed +-- outputs: +-- Variable Value +-- valid is 1 if valid 0 if not + procedure index_variable(variable var_list : in var_field_ptr; + variable index : in integer; + variable value : out integer; + variable valid : out integer) is + variable ptr: var_field_ptr; + begin + ptr := var_list; + valid := 0; + while(ptr.next_rec /= null) loop + if(ptr.var_index = index) then + value := ptr.var_value; + valid := 1; + exit; + end if; + ptr := ptr.next_rec; + end loop; + if(ptr.var_index = index) then + value := ptr.var_value; + valid := 1; + end if; + end index_variable; + +-------------------------------------------------------------------------------- +-- update_variable +-- inputs: +-- index: the index of the variable being updated +-- outputs: +-- valid is 1 if valid 0 if not + procedure update_variable(variable var_list : in var_field_ptr; + variable index : in integer; + variable value : in integer; + variable valid : out integer) is + variable ptr: var_field_ptr; + begin + ptr := var_list; + valid := 0; + while(ptr.next_rec /= null) loop + if(ptr.var_index = index) then + ptr.var_value := value; + valid := 1; + exit; + end if; + ptr := ptr.next_rec; + end loop; + -- check the current one + if(ptr.var_index = index) then + ptr.var_value := value; + valid := 1; + end if; + end update_variable; + +------------------------------------------------------------------------------- +-- Read a line from a file +-- inputs : file of type text +-- outputs : The line of type text_line + procedure file_read_line(file file_name: text; + variable file_line: out text_line + ) is + variable index: integer; -- index into string + variable rline: line; + + begin + + index := 1; -- set index to begin of string + file_line := (others => nul); + if(not endfile(file_name)) then + readline(file_name,rline); + + while(rline'right /= (index - 1) and rline'length /= 0) loop + file_line(index) := rline(index); + index := index + 1; + end loop; + end if; + end file_read_line; + + ------------------------------------------------------------------------------ + -- procedure to break a line down in to text fields + procedure tokenize_line(variable text_line: in text_line; + variable token1: out text_field; + variable token2: out text_field; + variable token3: out text_field; + variable token4: out text_field; + variable token5: out text_field; + variable token6: out text_field; + variable token7: out text_field; + variable txt_ptr: out stm_text_ptr; + variable valid: out integer) is + variable token_index: integer := 0; + variable current_token: text_field; + variable token_number: integer := 0; + variable c: string(1 to 2); + variable comment_found: integer := 0; + variable txt_found: integer := 0; + variable j: integer; + + begin + -- null outputs + token1 := (others => nul); + token2 := (others => nul); + token3 := (others => nul); + token4 := (others => nul); + token5 := (others => nul); + token6 := (others => nul); + token7 := (others => nul); + txt_ptr := null; + valid := 0; + txt_found := 0; + j := 1; + + -- loop for max number of char + for i in 1 to text_line'high loop + -- collect for comment test ** assumed no line will be max 256 + c(1) := text_line(i); + c(2) := text_line(i + 1); -- or this line will blow up + if(c = "--") then + comment_found := 1; + exit; + end if; + -- if is begin text char '"' + if(c(1) = '"') then --" <-- this double quote is just to fix highlighting. + txt_found := 1; + txt_ptr := new stm_text; + next; + end if; + + -- if we have found a txt string + if (txt_found = 1 and text_line(i) /= nul) then + -- if string too long, prevent tool hang, truncate and notify + if(j > c_stm_text_len) then + print("tokenize_line: truncated txt line, it was larger than c_stm_text_len"); + exit; + end if; + txt_ptr(j) := text_line(i); + j := j + 1; + -- if is a character store in the right token + elsif(is_space(text_line(i)) = false and text_line(i) /= nul) then + token_index := token_index + 1; + current_token(token_index) := text_line(i); + -- else is a space, deal with pointers + elsif(is_space(text_line(i + 1)) = false and text_line(i + 1) /= nul) then + case token_number is + when 0 => + if(token_index /= 0) then + token1 := current_token; + current_token := (others => nul); + token_number := 1; + valid := 1; + token_index := 0; + end if; + when 1 => + token2 := current_token; + current_token := (others => nul); + token_number := 2; + valid := 2; + token_index := 0; + when 2 => + token3 := current_token; + current_token := (others => nul); + token_number := 3; + valid := 3; + token_index := 0; + when 3 => + token4 := current_token; + current_token := (others => nul); + token_number := 4; + valid := 4; + token_index := 0; + when 4 => + token5 := current_token; + current_token := (others => nul); + token_number := 5; + valid := 5; + token_index := 0; + when 5 => + token6 := current_token; + current_token := (others => nul); + token_number := 6; + valid := 6; + token_index := 0; + when 6 => + token7 := current_token; + current_token := (others => nul); + token_number := 7; + valid := 7; + token_index := 0; + when 7 => + when others => + null; + end case; + end if; + -- break from loop if is null + if(text_line(i) = nul) then + if(token_index /= 0) then + case token_number is + when 0 => + token1 := current_token; + valid := 1; + when 1 => + token2 := current_token; + valid := 2; + when 2 => + token3 := current_token; + valid := 3; + when 3 => + token4 := current_token; + valid := 4; + when 4 => + token5 := current_token; + valid := 5; + when 5 => + token6 := current_token; + valid := 6; + when 6 => + token7 := current_token; + valid := 7; + when others => + null; + end case; + end if; + exit; + end if; + end loop; + -- did we find a comment and there is a token + if(comment_found = 1) then + if(token_index /= 0) then + case token_number is + when 0 => + token1 := current_token; + valid := 1; + when 1 => + token2 := current_token; + valid := 2; + when 2 => + token3 := current_token; + valid := 3; + when 3 => + token4 := current_token; + valid := 4; + when 4 => + token5 := current_token; + valid := 5; + when 5 => + token6 := current_token; + valid := 6; + when 6 => + token7 := current_token; + valid := 7; + when others => + null; + end case; + end if; + end if; + end tokenize_line; +------------------------------------------------------------------------------- +-- Add a new instruction to the instruction list +-- inputs : the linked list of instructions +-- the instruction +-- the number of args +-- outputs : Updated instruction set linked list + procedure define_instruction(variable inst_set: inout inst_def_ptr; + constant inst: in string; + constant args: in integer) is + variable v_inst_ptr: inst_def_ptr; + variable v_prev_ptr: inst_def_ptr; + variable v_new_ptr: inst_def_ptr; + variable v_temp_inst: inst_def_ptr; + variable v_length: integer; + variable v_list_size: integer; + variable v_dup_error: boolean; + + begin + assert(inst'high <= max_field_len) + report LF & "Error: Creation of Instruction of length greater than Max_field_len attemped!!" & + LF & "This Max is currently set to " & (integer'image(max_field_len)) + severity failure; + -- get to the last element and test is not exsiting + v_temp_inst := inst_set; + v_inst_ptr := inst_set; + -- zero the size + v_list_size := 0; + while(v_inst_ptr /= null) loop + -- if there is a chance of a duplicate command + if(v_inst_ptr.instruction_l = inst'high) then + v_dup_error := true; + for i in 1 to inst'high loop + if(v_inst_ptr.instruction(i) /= inst(i)) then + v_dup_error := false; + end if; + end loop; + -- if we find a duplicate, die + assert(v_dup_error = false) + report LF & "Error: Duplicate instruction definition attempted!" + severity failure; + end if; + v_prev_ptr := v_inst_ptr; -- store for pointer updates + v_inst_ptr := v_inst_ptr.next_rec; + v_list_size := v_list_size + 1; + end loop; + + -- add the new instruction + v_new_ptr := new inst_def; + -- if this is the first command return new pointer + if(v_list_size = 0) then + v_temp_inst := v_new_ptr; + -- else write new pointer to next_rec + else + v_prev_ptr.next_rec := v_new_ptr; + end if; + v_new_ptr.instruction_l := inst'high; + v_new_ptr.params := args; + -- copy the instruction text into field + for i in 1 to v_new_ptr.instruction_l loop + v_new_ptr.instruction(i) := inst(i); + end loop; + -- return the pointer + inst_set := v_temp_inst; + + end define_instruction; + +-------------------------------------------------------------------------------- +-- Check for valid instruction in the list of instructions +procedure check_valid_inst(variable inst : in text_field; + variable inst_set : in inst_def_ptr; + variable token_num: in integer; + variable line_num : in integer; + variable name : in text_line) is + variable l : integer := 0; + variable seti: inst_def_ptr; + variable match: integer := 0; + variable ilv: integer := 0; -- inline variable + begin + -- create useable pointer + seti := inst_set; + -- count up the characters in inst + l := fld_len(inst); + -- if this is a referance variable -- handle in add variable Proc + if(inst(l) = ':') then + match := 1; + ilv := 1; + else + -- process list till null next + while (seti.next_rec /= null) loop + if(seti.instruction_l = l) then + match := 1; + for j in 1 to l loop + if(seti.instruction(j) /= inst(j)) then + match := 0; + end if; + end loop; + end if; + if(match = 0) then + seti := seti.next_rec; + else + exit; + end if; + end loop; + -- check current one + if(seti.instruction_l = l and match = 0) then + match := 1; + for j in 1 to l loop + if(seti.instruction(j) /= inst(j)) then + match := 0; + end if; + end loop; + end if; + end if; + + -- if instruction was not found, die + assert(match = 1) + report LF & "Error: Undefined Instruction on line " & (integer'image(line_num)) & + " found in input file " & name & LF + severity failure; + + -- if the definition of the number of parameters is > 6 skip testing + -- this is how the variable number of parameters is implemented + -- just skip testing for specified number + if(seti.params > 6) then + return; + end if; + -- if we had a match, check the number of paramiters + if(match = 1 and ilv = 0) then + assert(seti.params = (token_num - 1)) + report LF & "Error: Undefined Instruction was found, incorrect number of fields passed!" & LF & + "This is found on line " & (integer'image(line_num)) & " in file " & name & LF + severity failure; + end if; + end check_valid_inst; + +-------------------------------------------------------------------------------- +-- add_variable +-- This procedure adds a variable to the variable list. This is localy +-- available at this time. +procedure add_variable(variable var_list : inout var_field_ptr; + variable p1 : in text_field; -- should be var name + variable p2 : in text_field; -- should be value + variable token_num : in integer; + variable sequ_num : in integer; + variable line_num : in integer; + variable name : in text_line; + variable length : in integer) is + + variable temp_var: var_field_ptr; + variable current_ptr: var_field_ptr; + variable index: integer := 1; + variable len: integer := 0; + + begin + -- if this is NOT the first one + if(var_list /= null) then + current_ptr := var_list; + index := index + 1; + if(p1(length) /= ':') then -- is not an inline variable + while(current_ptr.next_rec /= null) loop + -- if we have defined the current before then die + assert(current_ptr.var_name /= p1) + report LF & "Error: Attemping to add a duplicate Variable definition " + & " on line " & (integer'image(line_num)) & " of file " & name + severity failure; + + current_ptr := current_ptr.next_rec; + index := index + 1; + end loop; + -- if we have defined the current before then die. This checks the last one + assert(current_ptr.var_name /= p1) + report LF & "Error: Attemping to add a duplicate Variable definition " + & " on line " & (integer'image(line_num)) & " of file " & name + severity failure; + + temp_var := new var_field; + temp_var.var_name := p1; -- direct write of text_field + temp_var.var_value := stim_to_integer(p2,name,line_num); -- convert text_field to integer + temp_var.var_index := index; + current_ptr.next_rec := temp_var; + else -- this is an inline variable + while(current_ptr.next_rec /= null) loop + -- if we have defined the current before then die + len := fld_len(current_ptr.var_name); + assert(current_ptr.var_name(1 to len) /= p1(1 to (length - 1))) + report LF & "Error: Attemping to add a duplicate Inline Variable definition " + & " on line " & (integer'image(line_num)) & " of file " & name + severity failure; + + current_ptr := current_ptr.next_rec; + index := index + 1; + end loop; + -- if we have defined the current before then die. This checks the last one + len := fld_len(current_ptr.var_name); + assert(current_ptr.var_name(1 to len) /= p1(1 to (length - 1))) + report LF & "Error: Attemping to add a duplicate Inline Variable definition " + & " on line " & (integer'image(line_num)) & " of file " & name + severity failure; + + temp_var := new var_field; + temp_var.var_name(1 to (length - 1)) := p1(1 to (length - 1)); + temp_var.var_value := sequ_num; + temp_var.var_index := index; + current_ptr.next_rec := temp_var; + end if; + -- this is the first one + else + if(p1(length) /= ':') then -- is not an inline variable + temp_var := new var_field; + temp_var.var_name := p1; -- direct write of text_field + temp_var.var_index := index; + temp_var.var_value := stim_to_integer(p2,name,line_num); -- convert text_field to integer + var_list := temp_var; + else + temp_var := new var_field; + temp_var.var_name(1 to (length - 1)) := p1(1 to (length - 1)); + temp_var.var_value := sequ_num; + temp_var.var_index := index; + var_list := temp_var; + end if; + end if; + end add_variable; +-------------------------------------------------------------------------------- +-- add_instruction +-- This is the procedure that adds the instruction to the linked list of +-- instructions. Also Variable addition are called and or handled. +-- the instruction sequence Link list. +-- inputs: +-- stim_line_ptr is the pointer to the instruction List +-- inst is the instruction token +-- p1 paramitor one, corrisponds to field one of stimulus +-- p2 paramitor one, corrisponds to field two of stimulus +-- p3 paramitor one, corrisponds to field three of stimulus +-- p4 paramitor one, corrisponds to field four of stimulus +-- p5 paramitor one, corrisponds to field three of stimulus +-- p6 paramitor one, corrisponds to field four of stimulus +-- str_ptr pointer to string for print instruction +-- token_num the number of tokens, including instruction +-- sequ_num is the stimulus file line referance ie program line number +-- line_num Line number in the text file +-- outputs: +-- none. Error will terminate sim + procedure add_instruction(variable inst_list : inout stim_line_ptr; + variable var_list : inout var_field_ptr; + variable inst : in text_field; + variable p1 : in text_field; + variable p2 : in text_field; + variable p3 : in text_field; + variable p4 : in text_field; + variable p5 : in text_field; + variable p6 : in text_field; + variable str_ptr : in stm_text_ptr; + variable token_num : in integer; + variable sequ_num : inout integer; + variable line_num : in integer; + variable file_name : in text_line; + variable file_idx : in integer) is + variable temp_stim_line: stim_line_ptr; + variable temp_current: stim_line_ptr; + variable valid: integer; + variable l: integer; + begin + valid := 1; + l := fld_len(inst); + temp_current := inst_list; + -- take care of special cases + if(inst(1 to l) = "DEFINE_VAR") then + l := fld_len(p1); + -- Add the variable to the Variable pool, not considered an instruction + add_variable(var_list,p1,p2,token_num,sequ_num,line_num,file_name,l); + valid := 0; --Removes this from the instruction list + elsif(inst(l) = ':') then + add_variable(var_list,inst,p1,token_num,sequ_num,line_num,file_name,l); + valid := 0; + end if; + + if(valid = 1) then + -- prepare the new record + temp_stim_line := new stim_line; + temp_stim_line.instruction := inst; + temp_stim_line.inst_field_1 := p1; + temp_stim_line.inst_field_2 := p2; + temp_stim_line.inst_field_3 := p3; + temp_stim_line.inst_field_4 := p4; + temp_stim_line.inst_field_5 := p5; + temp_stim_line.inst_field_6 := p6; + temp_stim_line.txt := str_ptr; + temp_stim_line.line_number := sequ_num; + temp_stim_line.file_idx := file_idx; + temp_stim_line.file_line := line_num; + + -- if is not the first instruction + if(inst_list /= null) then + while(temp_current.next_rec /= null) loop + temp_current := temp_current.next_rec; + end loop; + temp_current.next_rec := temp_stim_line; + inst_list.num_of_lines := inst_list.num_of_lines + 1; + -- other wise is first instruction to be added + else + inst_list := temp_stim_line; + inst_list.num_of_lines := 1; + end if; + sequ_num := sequ_num + 1; +-- print_inst(temp_stim_line); -- for debug + end if; + + end add_instruction; +------------------------------------------------------------------------------ +-- test_inst_sequ +-- This procedure accesses the full instruction sequence and checks for valid +-- variables. This is prior to the simulation run start. + procedure test_inst_sequ(variable inst_sequ : in stim_line_ptr; + variable file_list : in file_def_ptr; + variable var_list : in var_field_ptr + ) is + variable temp_text_field: text_field; + variable temp_var: text_field; + variable inst_ptr: stim_line_ptr; + variable valid: integer; + variable line: integer; -- value of the file_line + variable file_name: text_line; + variable v_p: integer; + variable inst : text_field; + variable txt : stm_text_ptr; + variable inst_len : integer; + variable fname : text_line; + variable file_line : integer; + variable temp_fn_prt: file_def_ptr; + variable tmp_int : integer; + + begin + inst_ptr := inst_sequ; + -- go through all the instructions + while(inst_ptr.next_rec /= null) loop + inst := inst_ptr.instruction; + inst_len := fld_len(inst_ptr.instruction); + file_line := inst_ptr.file_line; + line := inst_ptr.file_line; + -- recover the file name this line came from + temp_fn_prt := file_list; + tmp_int := inst_ptr.file_idx; + while (temp_fn_prt.next_rec /= null) loop + if(temp_fn_prt.rec_idx = tmp_int) then + exit; + end if; + temp_fn_prt := temp_fn_prt.next_rec; + end loop; + for i in 1 to fname'high loop + file_name(i) := temp_fn_prt.file_name(i); + end loop; + + txt := inst_ptr.txt; + -- load parameter one + temp_text_field := inst_ptr.inst_field_1; + if(temp_text_field(1) /= nul) then + -- if this is a numaric do nothing + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then + null; + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,v_p,valid); + assert(valid = 1) + report LF & "Error: First variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter two + temp_text_field := inst_ptr.inst_field_2; + if(temp_text_field(1) /= nul) then + -- if this is a numaric do nothing + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then + null; + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,v_p,valid); + assert(valid = 1) + report LF & "Error: Second variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter three + temp_text_field := inst_ptr.inst_field_3; + if(temp_text_field(1) /= nul) then + -- if this is a numaric do nothing + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then + null; + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,v_p,valid); + assert(valid = 1) + report LF & "Error: Third variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter four + temp_text_field := inst_ptr.inst_field_4; + if(temp_text_field(1) /= nul) then + -- if this is a numaric do nothing + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b'or is_digit(temp_text_field(1)) = true) then + null; + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,v_p,valid); + assert(valid = 1) + report LF & "Error: Forth variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter five + temp_text_field := inst_ptr.inst_field_5; + if(temp_text_field(1) /= nul) then + -- if this is a numaric do nothing + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then + null; + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,v_p,valid); + assert(valid = 1) + report LF & "Error: Fifth variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter six + temp_text_field := inst_ptr.inst_field_6; + if(temp_text_field(1) /= nul) then + -- if this is a numaric field convert to integer + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then + null; + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,v_p,valid); + assert(valid = 1) + report LF & "Error: Sixth variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- point to next record + inst_ptr := inst_ptr.next_rec; + end loop; + + end test_inst_sequ; +-------------------------------------------------------------------------------- +-- The read include file procedure +-- This is the main procedure for reading, parcing, checking and returning +-- the instruction sequence Link list. + procedure read_include_file(variable name: text_line; + variable sequ_numb: inout integer; + variable file_list: inout file_def_ptr; + variable inst_set: inout inst_def_ptr; + variable var_list: inout var_field_ptr; + variable inst_sequ: inout stim_line_ptr; + variable status: inout integer) is + variable l: text_line; -- the line + variable l_num: integer; -- line number file + variable sequ_line: integer; -- line number program + variable t1: text_field; + variable t2: text_field; + variable t3: text_field; + variable t4: text_field; + variable t5: text_field; + variable t6: text_field; + variable t7: text_field; + variable t_txt: stm_text_ptr; + variable valid: integer; + variable v_inst_ptr: inst_def_ptr; + variable v_var_prt: var_field_ptr; + variable v_sequ_ptr: stim_line_ptr; + variable v_len: integer; + variable v_stat: file_open_status; + variable idx: integer; + variable v_tmp: text_line; + + variable v_tmp_fn_ptr: file_def_ptr; + variable v_new_fn: integer; + variable v_tmp_fn: file_def_ptr; + variable v_txt: stm_text; --stm_text_ptr; + + begin + sequ_line := sequ_numb; + v_tmp_fn_ptr := file_list; + -- for linux systems, trailing spaces need to be removed + -- from file names + -- copy text string to temp + for i in 1 to c_stm_text_len loop + if(name(i) = nul) then + v_tmp(i) := name(i); + exit; + else + v_tmp(i) := name(i); + end if; + end loop; + --fix up any trailing white space in txt + idx := 0; + -- get to the end of the string + for i in 1 to c_stm_text_len loop + if(v_tmp(i) /= nul) then + idx := idx + 1; + else + exit; + end if; + end loop; + -- now nul out spaces + for i in idx downto 1 loop + if(is_space(v_tmp(i)) = true) then + v_tmp(i) := nul; + else + exit; + end if; + end loop; + -- open include file + file_open(v_stat, include_file, v_tmp, read_mode); + if(v_stat /= open_ok) then + print("Error: Unable to open include file " & name); + status := 1; + return; + end if; + l_num := 1; -- initialize line number + + -- the file is opened, put it on the file name LL + while (v_tmp_fn_ptr.next_rec /= null) loop + v_tmp_fn_ptr := v_tmp_fn_ptr.next_rec; + end loop; + v_new_fn := v_tmp_fn_ptr.rec_idx + 1; + v_tmp_fn := new file_def; + v_tmp_fn_ptr.next_rec := v_tmp_fn; + v_tmp_fn.rec_idx := v_new_fn; + + -- nul the text line + v_tmp_fn.file_name := (others => nul); + for i in 1 to name'high loop + v_tmp_fn.file_name(i) := name(i); + end loop; + v_tmp_fn.next_rec := null; + + + v_inst_ptr := inst_set; + v_var_prt := var_list; + v_sequ_ptr := inst_sequ; + + -- while not the end of file read it + while(not endfile(include_file)) loop + file_read_line(include_file,l); + -- tokenize the line + tokenize_line(l,t1,t2,t3,t4,t5,t6,t7,t_txt,valid); + v_len := fld_len(t1); + if(t1(1 to v_len) = "INCLUDE") then + print("Nested INCLUDE statement found in " & v_tmp & " on line " & + (integer'image(l_num))); + assert(false) + report LF & "Error: Nested INCLUDE statements are not supported at this time." + severity failure; + + -- if there was valid tokens + elsif(valid /= 0) then + check_valid_inst(t1, v_inst_ptr, valid, l_num, name); + add_instruction(v_sequ_ptr,v_var_prt,t1,t2,t3,t4,t5,t6,t7,t_txt,valid, + sequ_line,l_num,name,v_new_fn); + end if; + l_num := l_num + 1; + end loop; -- end loop read file + file_close(include_file); + sequ_numb := sequ_line; + inst_set := v_inst_ptr; + var_list := v_var_prt; + inst_sequ := v_sequ_ptr; + end read_include_file; + +-------------------------------------------------------------------------------- +-- The read instruction file procedure +-- This is the main procedure for reading, parcing, checking and returning +-- the instruction sequence Link list. + procedure read_instruction_file(constant file_name: string; + variable inst_set: inout inst_def_ptr; + variable var_list: inout var_field_ptr; + variable inst_sequ: inout stim_line_ptr; + variable file_list: inout file_def_ptr) is + variable l: text_line; -- the line + variable l_num: integer; -- line number file + variable sequ_line: integer; -- line number program + variable t1: text_field; + variable t2: text_field; + variable t3: text_field; + variable t4: text_field; + variable t5: text_field; + variable t6: text_field; + variable t7: text_field; + variable t_txt: stm_text_ptr; + variable valid: integer; + variable v_ostat: integer; + variable v_inst_ptr: inst_def_ptr; + variable v_var_prt: var_field_ptr; + variable v_sequ_ptr: stim_line_ptr; + variable v_len: integer; + variable v_stat: file_open_status; + variable v_name: text_line; + variable v_iname: text_line; + variable v_tmp_fn: file_def_ptr; + variable v_fn_idx: integer; + variable v_idx: integer; + + begin + -- open the stimulus_file and check + file_open(v_stat, stimulus, file_name, read_mode); + assert(v_stat = open_ok) + report LF & "Error: Unable to open stimulus_file " & file_name + severity failure; + -- copy file name to type text_line + for i in 1 to file_name'high loop + v_name(i) := file_name(i); + end loop; + -- the first item on the file names link list + file_list := null; + v_tmp_fn := new file_def; + v_tmp_fn.rec_idx := 1; + v_fn_idx := 1; + v_idx := 1; + -- nul the text line + v_tmp_fn.file_name := (others => nul); + for i in 1 to file_name'high loop + v_tmp_fn.file_name(i) := file_name(i); + end loop; + v_tmp_fn.next_rec := null; + + l_num := 1; + sequ_line := 1; + v_ostat := 0; + + v_inst_ptr := inst_set; + v_var_prt := var_list; + v_sequ_ptr := inst_sequ; + + -- while not the end of file read it + while(not endfile(stimulus)) loop + file_read_line(stimulus,l); + -- tokenize the line + tokenize_line(l,t1,t2,t3,t4,t5,t6,t7,t_txt,valid); + v_len := fld_len(t1); + -- if there is an INCLUDE instruction + if(t1(1 to v_len) = "INCLUDE") then + -- if file name is in par2 + if(valid = 2) then + v_iname := (others => nul); + for i in 1 to max_field_len loop + v_iname(i) := t2(i); + end loop; + -- elsif the text string is not null + elsif(t_txt /= null) then + v_iname := (others => nul); + for i in 1 to c_stm_text_len loop + v_iname(i) := t_txt(i); + if(t_txt(i) = nul) then + exit; + end if; + end loop; + else + assert(false) + report LF & "Error: INCLUDE instruction has not file name included. Found on" & LF & + "line " & (integer'image(l_num)) & " in file " & file_name & LF + severity failure; + end if; + print("INCLUDE found: Loading file " & v_iname); + read_include_file(v_iname,sequ_line,v_tmp_fn,v_inst_ptr,v_var_prt,v_sequ_ptr,v_ostat); + -- if include file not found + if(v_ostat = 1) then + exit; + end if; + -- if there was valid tokens + elsif(valid /= 0) then + check_valid_inst(t1, v_inst_ptr, valid, l_num, v_name); + add_instruction(v_sequ_ptr,v_var_prt,t1,t2,t3,t4,t5,t6,t7,t_txt,valid, + sequ_line,l_num,v_name,v_fn_idx); + end if; + l_num := l_num + 1; + end loop; -- end loop read file + + file_close(stimulus); -- close the file when done + + assert(v_ostat = 0) + report LF & "Include file specified on line " & (integer'image(l_num)) & + " in file " & file_name & + " was not found! Test Terminated" & LF + severity failure; + + inst_set := v_inst_ptr; + var_list := v_var_prt; + inst_sequ := v_sequ_ptr; + file_list := v_tmp_fn; + + -- Now that all the stimulus is loaded, test for invalid variables + test_inst_sequ(inst_sequ, v_tmp_fn, var_list); + + end read_instruction_file; + +------------------------------------------------------------------------------ +-- access_inst_sequ +-- This procedure accesses the instruction sequence and returns the parameters +-- as they exsist related to the variables state. +-- INPUTS: inst_sequ link list of instructions from stimulus +-- var_list link list of variables +-- file_list link list of file names +-- sequ_num the sequence number to recover +-- +-- OUTPUTS: inst instruction text +-- p1 paramiter 1 in integer form +-- p2 paramiter 2 in integer form +-- p3 paramiter 3 in integer form +-- p4 paramiter 4 in integer form +-- p5 paramiter 5 in integer form +-- p6 paramiter 6 in integer form +-- txt pointer to any text string of this sequence +-- inst_len the lenth of inst in characters +-- fname file name this sequence came from +-- file_line the line number in fname this sequence came from +-- + procedure access_inst_sequ(variable inst_sequ : in stim_line_ptr; + variable var_list : in var_field_ptr; + variable file_list : in file_def_ptr; + variable sequ_num : in integer; + variable inst : out text_field; + variable p1 : out integer; + variable p2 : out integer; + variable p3 : out integer; + variable p4 : out integer; + variable p5 : out integer; + variable p6 : out integer; + variable txt : out stm_text_ptr; + variable inst_len : out integer; + variable fname : out text_line; + variable file_line : out integer; + variable last_num : inout integer; + variable last_ptr : inout stim_line_ptr + ) is + variable temp_text_field: text_field; + variable temp_var: text_field; + variable inst_ptr: stim_line_ptr; + variable valid: integer; + variable line: integer; -- value of the file_line + variable file_name: text_line; + variable tmp_int: integer; + variable temp_fn_prt: file_def_ptr; + begin + -- get to the instruction indicated by sequ_num + -- check to see if this sequence is before the last + -- so search from start + if(last_num > sequ_num) then + inst_ptr := inst_sequ; + while(inst_ptr.next_rec /= null) loop + if(inst_ptr.line_number = sequ_num) then + exit; + else + inst_ptr := inst_ptr.next_rec; + end if; + end loop; + -- else is equal or greater, so search forward + else + inst_ptr := last_ptr; + while(inst_ptr.next_rec /= null) loop + if(inst_ptr.line_number = sequ_num) then + exit; + else + inst_ptr := inst_ptr.next_rec; + end if; + end loop; + end if; + + -- update the last sequence number and record pointer + last_num := sequ_num; + last_ptr := inst_ptr; + + -- output the instruction and its length + inst := inst_ptr.instruction; + inst_len := fld_len(inst_ptr.instruction); + file_line := inst_ptr.file_line; + line := inst_ptr.file_line; + -- recover the file name this line came from + temp_fn_prt := file_list; + tmp_int := inst_ptr.file_idx; + while (temp_fn_prt.next_rec /= null) loop + if(temp_fn_prt.rec_idx = tmp_int) then + exit; + end if; + temp_fn_prt := temp_fn_prt.next_rec; + end loop; + for i in 1 to fname'high loop --<<<<<<<<<<<<< Fix for file name output Apr 2011. + file_name(i) := temp_fn_prt.file_name(i); + fname(i) := temp_fn_prt.file_name(i); + if(temp_fn_prt.file_name(i) = nul) then + exit; + end if; + end loop; + + txt := inst_ptr.txt; + -- load parameter one + temp_text_field := inst_ptr.inst_field_1; + if(temp_text_field(1) /= nul) then + -- if this is a numaric field convert to integer + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b') then + p1 := stim_to_integer(temp_text_field,file_name,line); + elsif(is_digit(temp_text_field(1)) = true) then + p1 := stim_to_integer(temp_text_field,file_name,line); + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,p1,valid); + assert(valid = 1) + report LF & "Error: First variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter two + temp_text_field := inst_ptr.inst_field_2; + if(temp_text_field(1) /= nul) then + -- if this is a numaric field convert to integer + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b') then + p2 := stim_to_integer(temp_text_field,file_name,line); + elsif(is_digit(temp_text_field(1)) = true) then + p2 := stim_to_integer(temp_text_field,file_name,line); + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,p2,valid); + assert(valid = 1) + report LF & "Error: Second variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter three + temp_text_field := inst_ptr.inst_field_3; + if(temp_text_field(1) /= nul) then + -- if this is a numaric field convert to integer + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b') then + p3 := stim_to_integer(temp_text_field,file_name,line); + elsif(is_digit(temp_text_field(1)) = true) then + p3 := stim_to_integer(temp_text_field,file_name,line); + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,p3,valid); + assert(valid = 1) + report LF & "Error: Third variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter four + temp_text_field := inst_ptr.inst_field_4; + if(temp_text_field(1) /= nul) then + -- if this is a numaric field convert to integer + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b') then + p4 := stim_to_integer(temp_text_field,file_name,line); + elsif(is_digit(temp_text_field(1)) = true) then + p4 := stim_to_integer(temp_text_field,file_name,line); + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,p4,valid); + assert(valid = 1) + report LF & "Error: Forth variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter five + temp_text_field := inst_ptr.inst_field_5; + if(temp_text_field(1) /= nul) then + -- if this is a numaric field convert to integer + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b') then + p5 := stim_to_integer(temp_text_field,file_name,line); + elsif(is_digit(temp_text_field(1)) = true) then + p5 := stim_to_integer(temp_text_field,file_name,line); + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,p5,valid); + assert(valid = 1) + report LF & "Error: Fifth variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + -- load parameter six + temp_text_field := inst_ptr.inst_field_6; + if(temp_text_field(1) /= nul) then + -- if this is a numaric field convert to integer + if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or + temp_text_field(1) = 'b') then + p6 := stim_to_integer(temp_text_field,file_name,line); + elsif(is_digit(temp_text_field(1)) = true) then + p6 := stim_to_integer(temp_text_field,file_name,line); + else -- else is a variable, get the value or halt incase of error + access_variable(var_list,temp_text_field,p6,valid); + assert(valid = 1) + report LF & "Error: Sixth variable on stimulus line " & (integer'image(line)) + & " is not valid!!" & LF & "In file " & file_name + severity failure; + end if; + end if; + end access_inst_sequ; + +------------------------------------------------------------------------------- +-- Procedure to print messages to stdout + procedure print(s: in string) is + variable l: line; + begin + write(l, s); + writeline(output,l); + end print; + +------------------------------------------------------------------------------- +-- procedure to print to the stdout the txt pointer + procedure txt_print(variable ptr: in stm_text_ptr) is + variable txt_str : stm_text; + begin + + if (ptr /= null) then + txt_str := (others => nul); + for i in 1 to c_stm_text_len loop + if (ptr(i) = nul) then + exit; + end if; + txt_str(i) := ptr(i); + end loop; + print(txt_str); + end if; + end txt_print; + +------------------------------------------------------------------------------- +-- procedure to print to the stdout the txt pointer, and +-- sub any variables found + procedure txt_print_wvar(variable var_list : in var_field_ptr; + variable ptr : in stm_text_ptr; + constant b : in base) is + + variable i: integer; + variable j: integer; + variable k: integer; + variable txt_str: stm_text; + variable tmp_str: stm_text; + variable v1: integer; + variable valid: integer; + variable tmp_field: text_field; + variable tmp_i: integer; + + begin + if(ptr /= null) then + i := 1; + j := 1; + txt_str := (others => nul); + while(i <= c_stm_text_len and j <= c_stm_text_len) loop + if(ptr(i) /= '$') then + txt_str(j) := ptr(i); + i := i + 1; + j := j + 1; + else + tmp_field := (others => nul); + tmp_i := 1; + tmp_field(tmp_i) := ptr(i); + i := i + 1; + tmp_i := tmp_i + 1; + -- parse to the next space + while(ptr(i) /= ' ' and ptr(i) /= nul) loop + tmp_field(tmp_i) := ptr(i); + i := i + 1; + tmp_i := tmp_i + 1; + end loop; + access_variable(var_list,tmp_field,v1,valid); + assert(valid = 1) + report LF & "Invalid Variable found in stm_text_ptr: ignoring." + severity warning; + + if(valid = 1) then + + txt_str := ew_str_cat(txt_str, tb_to_str(v1, b)); + k := 1; + while(txt_str(k) /= nul) loop + k := k + 1; + end loop; + j := k; + end if; + end if; + end loop; + -- print the created string + print(txt_str); + end if; + end txt_print_wvar; + +end tb_pkg; + +------------------------------------------------------------------------------- +-- Revision 1.3 +-- Revision History: +-- $Log: not supported by cvs2svn $ +-- Revision 1.2 2007/09/02 04:04:04 sckoarn +-- Update of version 1.2 tb_pkg +-- See documentation for details +-- +-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn +-- Import of the vhld_tb +------------------------------------------------------------------------------- Index: trunk/examples/packet_gen/vhdl/packet_gen_tb_bhv.vhd =================================================================== --- trunk/examples/packet_gen/vhdl/packet_gen_tb_bhv.vhd (nonexistent) +++ trunk/examples/packet_gen/vhdl/packet_gen_tb_bhv.vhd (revision 19) @@ -0,0 +1,589 @@ +------------------------------------------------------------------------------- +-- Copyright ----------------------------------- +-- All Rights Reserved +------------------------------------------------------------------------------- +-- $Author: $ +-- +-- $date: $ +-- +-- $Id: $ +-- +-- $Source: $ +-- +-- Description : +-- This file was generated by TTB Gen Plus Beta 2.0 +-- on 01 May 2011 20:35:06 +------------------------------------------------------------------------------ +-- This software contains concepts confidential to ---------------- +-- ---------. and is only made available within the terms of a written +-- agreement. +------------------------------------------------------------------------------- +-- Revision History: +-- $Log: $ +-- +------------------------------------------------------------------------------- + + +architecture bhv of packet_gen_tb is + + + + signal tb_clk : std_logic; + +------------------------------------------------------------------------- +-- Component defintion + +------------------------------------------------------------------------------- +-- USER Component instantiations +--for all: Arbitor use entity tb_objects.arbitor(bhv); + + + begin + +------------------------------------------------------------------------------- +-- clock driver process +-- the main clock generator +clock_driver: + process + begin + tb_clk <= '0'; + wait for 20 ns; + tb_clk <= '1'; + wait for 20 ns; + end process clock_driver; + + -------------------------------------------------------------------------- + -- Read_file Process: + -- + -- This process is the main process of the testbench. This process reads + -- the stumulus file, parses it, creates lists of records, then uses these + -- lists to exicute user instructions. There are two passes through the + -- script. Pass one reads in the stimulus text file, checks it, creates + -- lists of valid instructions, valid list of variables and finialy a list + -- of user instructions(the sequence). The second pass through the file, + -- records are drawn from the user instruction list, variables are converted + -- to integers and put through the elsif structure for exicution. + -------------------------------------------------------------------------- + Read_file: process + variable current_line : text_line; -- The current input line + variable inst_list : inst_def_ptr; -- the instruction list + variable defined_vars : var_field_ptr; -- defined variables + variable inst_sequ : stim_line_ptr; -- the instruction sequence + variable file_list : file_def_ptr; -- pointer to the list of file names + variable last_sequ_num: integer; + variable last_sequ_ptr: stim_line_ptr; + + variable instruction : text_field; -- instruction field + variable par1 : integer; -- paramiter 1 + variable par2 : integer; -- paramiter 2 + variable par3 : integer; -- paramiter 3 + variable par4 : integer; -- paramiter 4 + variable par5 : integer; -- paramiter 5 + variable par6 : integer; -- paramiter 6 + variable txt : stm_text_ptr; + variable nbase : base; -- the number base to use + variable len : integer; -- length of the instruction field + variable file_line : integer; -- Line number in the stimulus file + variable file_name : text_line; -- the file name the line came from + variable v_line : integer := 0; -- sequence number + variable stack : stack_register; -- Call stack + variable stack_ptr : integer := 0; -- call stack pointer + variable wh_stack : stack_register; -- while stack + variable wh_dpth : integer := 0; -- while depth + variable wh_ptr : integer := 0; -- while pointer + variable loop_num : integer := 0; + variable curr_loop_count : int_array := (others => 0); + variable term_loop_count : int_array := (others => 0); + variable loop_line : int_array := (others => 0); + + variable messages : boolean := TRUE; + variable if_state : boolean := FALSE; + variable wh_state : boolean := FALSE; + variable wh_end : boolean := FALSE; + variable rand : std_logic_vector(31 downto 0); + variable rand_back : std_logic_vector(31 downto 0); + variable valid : integer; + + -- scratchpad variables + variable i : integer; + variable temp_int : integer; + variable temp_index : integer; + variable temp_str : text_field; + variable v_temp_vec1 : std_logic_vector(31 downto 0); + variable v_temp_vec2 : std_logic_vector(31 downto 0); + + -------------------------------------------------------------------------- + -- Area for Procedures which may be usefull to more than one instruction. + -- By coding here commonly used code sections ... + -- you know the benifits. + --------------------------------------------------------------------- + ----------------------------------------------------------------- + -- This procedure writes to the arbitor model access port +-- procedure arb_write(add: in integer; ..... +-- end arb_write; + + + begin -- process Read_file + + request <= '0'; + stm_in <= stm_neut; + --fname <= ""; + + + ----------------------------------------------------------------------- + -- Stimulus file instruction definition + -- This is where the instructions used in the stimulus file are defined. + -- Syntax is + -- define_instruction(inst_def_ptr, instruction, paramiters) + -- inst_def_ptr: is a record pointer defined in tb_pkg_header + -- instruction: the text instruction name ie. "ADD_VAR" + -- paramiters: the number of fields or paramiters passed + -- + -- Some basic instruction are created here, the user should create new + -- instructions below the standard ones. + ------------------------------------------------------------------------ + define_instruction(inst_list, "DEFINE_VAR", 2); -- Define a Variable + define_instruction(inst_list, "EQU_VAR", 2); + define_instruction(inst_list, "ADD_VAR", 2); + define_instruction(inst_list, "SUB_VAR", 2); + define_instruction(inst_list, "CALL", 1); + define_instruction(inst_list, "RETURN_CALL", 0); + define_instruction(inst_list, "JUMP", 1); + define_instruction(inst_list, "LOOP", 1); + define_instruction(inst_list, "END_LOOP", 0); + define_instruction(inst_list, "IF", 3); + define_instruction(inst_list, "ELSEIF", 3); + define_instruction(inst_list, "ELSE", 0); + define_instruction(inst_list, "END_IF", 0); + define_instruction(inst_list, "WHILE", 3); + define_instruction(inst_list, "END_WHILE", 0); + define_instruction(inst_list, "MESSAGES_OFF", 0); + define_instruction(inst_list, "MESSAGES_ON", 0); + define_instruction(inst_list, "ABORT", 0); -- Error exit from sim + define_instruction(inst_list, "FINISH", 0); -- Normal exit from sim + define_instruction(inst_list, "INCLUDE", 1); -- Include a script file + -- Start User defined instructions + + -- End User defined instructions + define_instruction(inst_list, "RESET_SYS", 0); + define_instruction(inst_list, "REQUEST", 0); + define_instruction(inst_list, "WRITE_STM", 2); + define_instruction(inst_list, "SET_FN", 0); + define_instruction(inst_list, "TEST_INST", 7); + ------------------------------------------------------------------------ + -- Read, test, and load the stimulus file + read_instruction_file(stimulus_file, inst_list, defined_vars, inst_sequ, + file_list); + + -- initialize last info + last_sequ_num := 0; + last_sequ_ptr := inst_sequ; +------------------------------------------------------------------------ +-- Using the Instruction record list, get the instruction and implement +-- it as per the statements in the elsif tree. + while(v_line < inst_sequ.num_of_lines) loop + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + +-------------------------------------------------------------------------- + --if(instruction(1 to len) = "DEFINE_VAR") then + -- null; -- This instruction was implemented while reading the file + +-------------------------------------------------------------------------- + if(instruction(1 to len) = "INCLUDE") then + null; -- This instruction was implemented while reading the file + +-------------------------------------------------------------------------- + elsif(instruction(1 to len) = "ABORT") then + assert (false) + report "The test has aborted due to an error!!" + severity failure; + +-------------------------------------------------------------------------- + elsif(instruction(1 to len) = "FINISH") then + assert (false) + report "Test Finished with NO errors!!" + severity failure; + +-------------------------------------------------------------------------- + elsif(instruction(1 to len) = "EQU_VAR") then + update_variable(defined_vars, par1, par2, valid); + +-------------------------------------------------------------------------- + elsif(instruction(1 to len) = "ADD_VAR") then + index_variable(defined_vars, par1, temp_int, valid); + if(valid /= 0) then + temp_int := temp_int + par2; + update_variable(defined_vars, par1, temp_int, valid); + else + assert (false) + report "ADD_VAR Error: Not a valid Variable??" + severity failure; + end if; + +-------------------------------------------------------------------------- + elsif(instruction(1 to len) = "SUB_VAR") then + index_variable(defined_vars, par1, temp_int, valid); + if(valid /= 0) then + temp_int := temp_int - par2; + update_variable(defined_vars, par1, temp_int, valid); + else + assert (false) + report "SUB_VAR Error: Not a valid Variable??" + severity failure; + end if; + +-------------------------------------------------------------------------- + elsif(instruction(1 to len) = "CALL") then + if(stack_ptr >= 7) then + assert (false) + report "Call Error: Stack over run, calls to deeply nested!!" + severity failure; + end if; + stack(stack_ptr) := v_line; + stack_ptr := stack_ptr + 1; + v_line := par1 - 1; + +-------------------------------------------------------------------------- + elsif(instruction(1 to len) = "RETURN_CALL") then + if(stack_ptr <= 0) then + assert (false) + report "Call Error: Stack under run??" + severity failure; + end if; + stack_ptr := stack_ptr - 1; + v_line := stack(stack_ptr); + +-------------------------------------------------------------------------- + elsif(instruction(1 to len) = "JUMP") then + v_line := par1 - 1; + wh_state := false; + wh_stack := (others => 0); + wh_dpth := 0; + wh_ptr := 0; + stack := (others => 0); + stack_ptr := 0; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "LOOP") then + loop_num := loop_num + 1; + loop_line(loop_num) := v_line; + curr_loop_count(loop_num) := 0; + term_loop_count(loop_num) := par1; + assert (messages) + report LF & "Executing LOOP Command" & + LF & " Nested Loop:" & HT & integer'image(loop_num) & + LF & " Loop Length:" & HT & integer'image(par1) + severity note; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "END_LOOP") then + curr_loop_count(loop_num) := curr_loop_count(loop_num) + 1; + if (curr_loop_count(loop_num) = term_loop_count(loop_num)) then + loop_num := loop_num - 1; + else + v_line := loop_line(loop_num); + end if; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "IF") then + if_state := false; + case par2 is + when 0 => if(par1 = par3) then if_state := true; end if; + when 1 => if(par1 > par3) then if_state := true; end if; + when 2 => if(par1 < par3) then if_state := true; end if; + when 3 => if(par1 /= par3) then if_state := true; end if; + when 4 => if(par1 >= par3) then if_state := true; end if; + when 5 => if(par1 <= par3) then if_state := true; end if; + when others => + assert (false) + report LF & "ERROR: IF instruction got an unexpected value" & + LF & " in parameter 2!" & LF & + "Found on line " & integer'image(file_line) & " in file " & file_name + severity failure; + end case; + + if(if_state = false) then + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + while(instruction(1 to len) /= "ELSE" and + instruction(1 to len) /= "ELSEIF" and + instruction(1 to len) /= "END_IF") loop + if(v_line < inst_sequ.num_of_lines) then + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + else + assert (false) + report LF & "ERROR: IF instruction unable to find terminating" & + LF & " ELSE, ELSEIF or END_IF statement." + severity failure; + end if; + end loop; + v_line := v_line - 1; -- re-align so it will be operated on. + end if; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "ELSEIF") then + if(if_state = true) then -- if the if_state is true then skip to the end + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + while(instruction(1 to len) /= "END_IF") loop + if(v_line < inst_sequ.num_of_lines) then + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + else + assert (false) + report LF & "ERROR: IF instruction unable to find terminating" & + LF & " ELSE, ELSEIF or END_IF statement." + severity failure; + end if; + end loop; + v_line := v_line - 1; -- re-align so it will be operated on. + + else + case par2 is + when 0 => if(par1 = par3) then if_state := true; end if; + when 1 => if(par1 > par3) then if_state := true; end if; + when 2 => if(par1 < par3) then if_state := true; end if; + when 3 => if(par1 /= par3) then if_state := true; end if; + when 4 => if(par1 >= par3) then if_state := true; end if; + when 5 => if(par1 <= par3) then if_state := true; end if; + when others => + assert (false) + report LF & "ERROR: ELSEIF instruction got an unexpected value" & + LF & " in parameter 2!" & LF & + "Found on line " & integer'image(file_line) & " in file " & file_name + severity failure; + end case; + + if(if_state = false) then + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + while(instruction(1 to len) /= "ELSE" and + instruction(1 to len) /= "ELSEIF" and + instruction(1 to len) /= "END_IF") loop + if(v_line < inst_sequ.num_of_lines) then + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + else + assert (false) + report LF & "ERROR: ELSEIF instruction unable to find terminating" & + LF & " ELSE, ELSEIF or END_IF statement." + severity failure; + end if; + end loop; + v_line := v_line - 1; -- re-align so it will be operated on. + end if; + end if; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "ELSE") then + if(if_state = true) then -- if the if_state is true then skip the else + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + while(instruction(1 to len) /= "END_IF") loop + if(v_line < inst_sequ.num_of_lines) then + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + else + assert (false) + report LF & "ERROR: IF instruction unable to find terminating" & + LF & " ELSE, ELSEIF or END_IF statement." + severity failure; + end if; + end loop; + v_line := v_line - 1; -- re-align so it will be operated on. + end if; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "END_IF") then + null; -- instruction is a place holder for finding the end of IF. + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "WHILE") then + wh_state := false; + case par2 is + when 0 => if(par1 = par3) then wh_state := true; end if; + when 1 => if(par1 > par3) then wh_state := true; end if; + when 2 => if(par1 < par3) then wh_state := true; end if; + when 3 => if(par1 /= par3) then wh_state := true; end if; + when 4 => if(par1 >= par3) then wh_state := true; end if; + when 5 => if(par1 <= par3) then wh_state := true; end if; + when others => + assert (false) + report LF & "ERROR: WHILE instruction got an unexpected value" & + LF & " in parameter 2!" & LF & + "Found on line " & integer'image(file_line) & " in file " & file_name + severity failure; + end case; + + if(wh_state = true) then + wh_stack(wh_ptr) := v_line; + wh_ptr := wh_ptr + 1; + else + wh_end := false; + while(wh_end /= true) loop + if(v_line < inst_sequ.num_of_lines) then + v_line := v_line + 1; + access_inst_sequ(inst_sequ, defined_vars, file_list, v_line, instruction, + par1, par2, par3, par4, par5, par6, txt, len, file_name, file_line, + last_sequ_num, last_sequ_ptr); + else + assert (false) + report LF & "ERROR: WHILE instruction unable to find terminating" & + LF & " END_WHILE statement." + severity failure; + end if; + + -- if is a while need to escape it + if(instruction(1 to len) = "WHILE") then + wh_dpth := wh_dpth + 1; + -- if is the end_while we are looking for + elsif(instruction(1 to len) = "END_WHILE") then + if(wh_dpth = 0) then + wh_end := true; + else + wh_dpth := wh_dpth - 1; + end if; + end if; + end loop; + end if; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "END_WHILE") then + if(wh_ptr > 0) then + v_line := wh_stack(wh_ptr - 1) - 1; + wh_ptr := wh_ptr - 1; + end if; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "MESSAGES_OFF") then + messages := TRUE; +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "MESSAGES_ON") then + messages := FALSE; + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-- USER Istruction area. Add all user instructions below this +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "RESET_SYS") then + STM_IN.rst_n <= '1'; + wait until tb_clk'event and tb_clk = '1'; + STM_IN.rst_n <= '0'; + wait until tb_clk'event and tb_clk = '1'; + STM_IN.rst_n <= '1'; + wait for 0 ps; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "SET_FN") then + i := 1; + while(txt(i) /= nul) loop + fname(i) <= txt(i); + i := i + 1; + end loop; +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "REQUEST") then + request <= '1'; + wait until tb_clk'event and tb_clk = '0'; + request <= '0'; + wait until tb_clk'event and tb_clk = '1'; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "WRITE_STM") then + v_temp_vec1 := std_logic_vector(conv_unsigned(par1, 32)); + v_temp_vec2 := std_logic_vector(conv_unsigned(par2, 32)); + STM_IN.addr <= v_temp_vec1; + STM_IN.wdat <= v_temp_vec2; + STM_IN.rwn <= '0'; + wait for 1 ps; + STM_IN.req_n <= '0'; + wait until STM_OUT.ack_n'event and STM_OUT.ack_n = '0'; + STM_IN.req_n <= '1'; + STM_IN.addr <= (others => 'Z'); + STM_IN.wdat <= (others => 'Z'); + STM_IN.rwn <= '1'; + wait for 1 ps; + +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "TEST_INST") then + temp_int := 0; + if(par1 >= 0) then + temp_int := temp_int + 1; + if(par2 >= 0) then + temp_int := temp_int + 1; + if(par3 >= 0) then + temp_int := temp_int + 1; + if(par4 >= 0) then + temp_int := temp_int + 1; + if(par5 >= 0) then + temp_int := temp_int + 1; + if(par6 >= 0) then + temp_int := temp_int + 1; + end if; + end if; + end if; + end if; + end if; + end if; + print("TEST_INST had " & integer'image(temp_int) & " parameters passed."); + +-------------------------------------------------------------------------------- +-- USER Istruction area. Add all user instructions above this +-------------------------------------------------------------------------------- + -------------------------------------------------------------------------- + -- catch those little mistakes + else + assert (false) + report LF & "ERROR: Seems the command " & instruction(1 to len) & " was defined but" & LF & + "was not found in the elsif chain, please check spelling." + severity failure; + end if; -- else if structure end + -- after the instruction is finished print out any txt and sub vars + txt_print_wvar(defined_vars, txt, hex); + end loop; -- Main Loop end + + assert (false) + report LF & "The end of the simulation! It was not terminated as expected." & LF + severity failure; + + end process Read_file; + + +end bhv; +------------------------------------------------------------------------------- +-- Revision History: +-- version 1.4 +-- $Log: not supported by cvs2svn $ +-- Revision 1.3 2007/11/14 02:35:56 sckoarn +-- Fix to WHILE instruction: Change if_state typo to wh_state +-- +-- Revision 1.2 2007/09/02 04:04:04 sckoarn +-- Update of version 1.2 tb_pkg +-- See documentation for details +-- +-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn +-- Import of the vhld_tb +-- +-- +------------------------------------------------------------------------------- Index: trunk/examples/packet_gen/vhdl/packet_gen_tb_ent.vhd =================================================================== --- trunk/examples/packet_gen/vhdl/packet_gen_tb_ent.vhd (nonexistent) +++ trunk/examples/packet_gen/vhdl/packet_gen_tb_ent.vhd (revision 19) @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------- +-- Copyright ----------------------------------- +-- All Rights Reserved +------------------------------------------------------------------------------- +-- $Author: $ +-- +-- $date: $ +-- +-- $Id: $ +-- +-- $Source: $ +-- +-- Description : +-- This file was generated by TTB Gen Plus Beta 2.0 +-- on 01 May 2011 21:23:14 +------------------------------------------------------------------------------ +-- This software contains concepts confidential to ---------------- +-- ---------. and is only made available within the terms of a written +-- agreement. +------------------------------------------------------------------------------- +-- Revision History: +-- $Log: $ +-- +------------------------------------------------------------------------------- + +library IEEE; +--library tb_pkg; +--possible users libs; +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use std.textio.all; +use work.tb_pkg.all; +use work.pgen.all; +--possible users use statement; +--library synthworks; +-- use SynthWorks.RandomBasePkg.all; +-- use SynthWorks.RandomPkg.all; + +entity packet_gen_tb is + generic ( + stimulus_file: in string + ); + port ( + packet_out : in pack_out; + request : buffer std_logic; + fname : buffer stm_text; + stm_in : buffer stm_sctl; + stm_out : in stm_sack + ); +end packet_gen_tb; Index: trunk/examples/packet_gen/vhdl/packet_gen_users.txt.txt =================================================================== --- trunk/examples/packet_gen/vhdl/packet_gen_users.txt.txt (nonexistent) +++ trunk/examples/packet_gen/vhdl/packet_gen_users.txt.txt (revision 19) @@ -0,0 +1,49 @@ +This file contains the users interface instructions for the packet generator BFM. + +To trigger the generation of a new packet on the packet_out interface, a rising edge +must be applied to the request input pin. The output ready is indicated by the +packet_out.drdy output pin going high. The BMF must also be configured to be enabled. + + +The stimulus access port address mapping is presented below: + +--- +Name Address Bit(s) Description + +Control Register 0 0 Enable + 1 Open file trigger, Write a '1' + to this bit to trigger file open + This bit is self clearing. + 31 - 2 Don't care + +Configuration 1 3-0 Data coding mode +Register 0000 Incrementing + 0001 Random + 0010 Load from file + 0011 User Data + 31 - 4 Don't care + +Error Register 2 Read only definition of error indications + +Seed Register 3 31-0 Seed value for random number + generation + +User Data Memory 0x1000 – 0x107F Bits 7 downto 0 of the data are written to the + addressed location. + + +The fname, stm_text type, input enables the definition of a file name to be dynamic. +Set the file name, stm_text input, to the file you wish to open for loading data +from. Then write the open file trigger bit to open the file. Any previouslly +opened files will be closed first, so you do not have to worry about that. Once +a file is opened, it will be read from until there is no more lines to read, or, +the output packet size has been met. The next request will have the file being +loaded from where it left off on the last load. This enables many packets to be +placed in one file, and loaded request to request without having to deal with file +details. + +To set the user data, write the desired packet to the User Data Memory before the +request for data. Configure generation to be User Data. + +The generic on the BFM enables a particular BMF to be identified if there are +more than one of this type in an environment. Index: trunk/examples/packet_gen/vhdl/tb_pkg_header.vhd =================================================================== --- trunk/examples/packet_gen/vhdl/tb_pkg_header.vhd (nonexistent) +++ trunk/examples/packet_gen/vhdl/tb_pkg_header.vhd (revision 19) @@ -0,0 +1,265 @@ +------------------------------------------------------------------------------- +-- Copyright 2011 Ken Campbell +------------------------------------------------------------------------------- +-- $Author: sckoarn $ +-- +-- $Date: $ +-- +-- $Id: $ +-- +-- $Source: $ +-- +-- Description : The the testbench package header file. +-- GNU release 2 Beta. +-- +------------------------------------------------------------------------------ +--This file is part of The VHDL Test Bench. +-- +-- The VHDL Test Bench is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- The VHDL Test Bench is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with The VHDL Test Bench; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +------------------------------------------------------------------------------- +library IEEE; + +use IEEE.STD_LOGIC_1164.all; +use IEEE.STD_LOGIC_ARITH.all; +use std.textio.all; +--library ieee_proposed; +--use ieee_proposed.STD_LOGIC_1164_additions.all; + +package tb_pkg is + + -- Constants + constant max_str_len : integer := 256; + constant max_field_len : integer := 48; + constant c_stm_text_len : integer := 200; + -- file handles + file stimulus : text; -- file main file + file include_file : text; -- file declaration for includes + + -- Type Def's + type base is (bin, oct, hex, dec); + type stack_register is array(7 downto 0) of integer; + type state_register is array(7 downto 0) of boolean; + type int_array is array(1 to 16) of integer; + + subtype text_line is string(1 to max_str_len); + subtype text_field is string(1 to max_field_len); + subtype stm_text is string(1 to c_stm_text_len); + type stm_text_ptr is access stm_text; + -- define the stimulus line record and access + type stim_line; + type stim_line_ptr is access stim_line; -- Pointer to stim_line record + type stim_line is record + instruction: text_field; + inst_field_1: text_field; + inst_field_2: text_field; + inst_field_3: text_field; + inst_field_4: text_field; + inst_field_5: text_field; + inst_field_6: text_field; + txt: stm_text_ptr; + line_number: integer; -- sequence line + num_of_lines: integer; -- total number of lines + file_line: integer; -- file line number + file_idx: integer; + next_rec: stim_line_ptr; + end record; + -- define the variables field and pointer + type var_field; + type var_field_ptr is access var_field; -- pointer to var_field + type var_field is record + var_name: text_field; + var_index: integer; + var_value: integer; + next_rec: var_field_ptr; + end record; + -- define the instruction structure + type inst_def; + type inst_def_ptr is access inst_def; + type inst_def is record + instruction: text_field; + instruction_l: integer; + params: integer; + next_rec: inst_def_ptr; + end record; + -- define the file handle record + type file_def; + type file_def_ptr is access file_def; + type file_def is record + rec_idx: integer; + file_name: text_line; + next_rec: file_def_ptr; + end record; + + -- define the stimulus slave control record types + type stm_sctl is record + rst_n : std_logic; + addr : std_logic_vector(31 downto 0); + wdat : std_logic_vector(31 downto 0); + rwn : std_logic; + req_n : std_logic; + end record; + type stm_sack is record + rdat : std_logic_vector(31 downto 0); + ack_n : std_logic; + rdy_n : std_logic; + irq_n : std_logic; + end record; + -- define the stimulus master control record types + type stm_mctl is record + addr : std_logic_vector(31 downto 0); + wdat : std_logic_vector(31 downto 0); + rwn : std_logic; + req_n : std_logic; + breq : std_logic; + end record; + type stm_mack is record + rdat : std_logic_vector(31 downto 0); + slv_rdy : std_logic_vector(15 downto 0); + slv_irq : std_logic_vector(15 downto 0); + ack_n : std_logic; + bgrant : std_logic; + end record; + +----- +-- stm interface neutral functions + function stm_neut return stm_sctl; + function stm_neut return stm_sack; + --function stm_neut() return stm_mctl; + --function stm_neut() return stm_mack; + +---***************************************************************************** + -- Function Declaration + function c2std_vec(c: in character) return std_logic_vector; + +-------------------------------------------------------------------------------- + -- Procedure declarations +-------------------------------------------------------------------------- +-- define_instruction +-- inputs file_name the file to be read from +-- +-- output file_line a line of text from the file + procedure define_instruction(variable inst_set: inout inst_def_ptr; + constant inst: in string; + constant args: in integer); + +-------------------------------------------------------------------------------- +-- index_variable +-- inputs: +-- index: the index of the variable being accessed +-- outputs: +-- Variable Value +-- valid is 1 if valid 0 if not + procedure index_variable(variable var_list : in var_field_ptr; + variable index : in integer; + variable value : out integer; + variable valid : out integer); + +-------------------------------------------------------------------------------- +-- update_variable +-- inputs: +-- index: the index of the variable being accessed +-- outputs: +-- Variable Value +-- valid is 1 if valid 0 if not + procedure update_variable(variable var_list : in var_field_ptr; + variable index : in integer; + variable value : in integer; + variable valid : out integer); + +------------------------------------------------------------------------------- +-- read_instruction_file +-- This procedure reads the instruction file, name passed throught file_name. +-- Pointers to records are passed in and out. A table of variables is created +-- with variable name and value (converted to integer). The instructions are +-- parsesed into the inst_sequ list. Instructions are validated against the +-- inst_set which must have been set up prior to loading the instruction file. + procedure read_instruction_file(constant file_name: string; + variable inst_set: inout inst_def_ptr; + variable var_list: inout var_field_ptr; + variable inst_sequ: inout stim_line_ptr; + variable file_list: inout file_def_ptr); + +------------------------------------------------------------------------------ +-- access_inst_sequ +-- This procedure retreeves an instruction from the sequence of instructions. +-- Based on the line number you pass to it, it returns the instruction with +-- any variables substituted as integers. + procedure access_inst_sequ(variable inst_sequ : in stim_line_ptr; + variable var_list : in var_field_ptr; + variable file_list : in file_def_ptr; + variable sequ_num : in integer; + variable inst : out text_field; + variable p1 : out integer; + variable p2 : out integer; + variable p3 : out integer; + variable p4 : out integer; + variable p5 : out integer; + variable p6 : out integer; + variable txt : out stm_text_ptr; + variable inst_len : out integer; + variable fname : out text_line; + variable file_line : out integer; + variable last_num : inout integer; + variable last_ptr : inout stim_line_ptr + ); +------------------------------------------------------------------------ +-- tokenize_line +-- This procedure takes a type text_line in and returns up to 6 +-- tokens and the count in integer valid, as well if text string +-- is found the pointer to that is returned. + procedure tokenize_line(variable text_line: in text_line; + variable token1: out text_field; + variable token2: out text_field; + variable token3: out text_field; + variable token4: out text_field; + variable token5: out text_field; + variable token6: out text_field; + variable token7: out text_field; + variable txt_ptr: out stm_text_ptr; + variable valid: out integer); + +------------------------------------------------------------------------- +-- Procedre print +-- print to stdout string + procedure print(s: in string); +------------------------------------------------------------------------- +-- Procedure print stim txt + procedure txt_print(variable ptr: in stm_text_ptr); +------------------------------------------------------------------------- +-- Procedure print stim txt sub variables found + procedure txt_print_wvar(variable var_list : in var_field_ptr; + variable ptr : in stm_text_ptr; + constant b : in base); + +------------------------------------------------------------------------- +-- convert a std_logic_vector to an unsigned integer + function to_uninteger ( constant vect : in std_logic_vector + ) return integer; + +end tb_pkg; +------------------------------------------------------------------------------- +-- new version 1.4 +-- Revision History: +-- $Log: not supported by cvs2svn $ +-- Revision 1.3 2007/09/02 04:04:04 sckoarn +-- Update of version 1.2 tb_pkg +-- See documentation for details +-- +-- Revision 1.2 2007/08/21 02:43:14 sckoarn +-- Fix package definition to match with body +-- +-- Revision 1.1.1.1 2007/04/06 04:06:48 sckoarn +-- Import of the vhld_tb +------------------------------------------------------------------------------- Index: trunk/examples/tb_code_snips.vhd =================================================================== --- trunk/examples/tb_code_snips.vhd (nonexistent) +++ trunk/examples/tb_code_snips.vhd (revision 19) @@ -0,0 +1,610 @@ +------------------------------------------------------------------------------- +-- Copyright 2011 Ken Campbell +-- All Rights Reserved +------------------------------------------------------------------------------- +-- $Author: ken $ +-- +-- $date: $ +-- +-- $Id: $ +-- +-- $Source: $ +-- +-- Description : +-- Code snipets from / for various VHDL Test Bench Facilities. +-- +-- Contents: +-- Section 1: Code from Usage Tips: Interrupts and Waiting. +-- Section 2: Code from CPU emulation: some starter commands +-- Section 3: Code for internal test bench implementation +-- Section 4: Code for Verify commands +-- +------------------------------------------------------------------------------ +-- +------------------------------------------------------------------------------- +------------------------------------------------------------------------------------- +--################################################################################### +-- Section 1: Interrupts and Waiting. +architecture bhv of tb_xxx is +-- ... +constant MAX_TIME : integer := 60000; +-- ... + +Read_file : process +-- ... + define_instruction(inst_list, "WAIT_IRQ", 0); +-- ... +-------------------------------------------------- + elsif (instruction(1 to len) = "WAIT_IRQ") then + temp_int := 0; -- initialize counter + while(dut_irq /= '1') then -- while IRQ not asserted + wait for clk'event and clk = '1'; -- wait for clock cycle + temp_int := temp_int + 1; -- add one to clock counter + assert (temp_int /= MAX_TIME) -- if count = max time quit. + report "Error: Time out while waiting for IRQ!!" + severity failure; + end loop; + +------------------------------------------------------------------------------------------- + define_instruction(inst_list, "MAX_WAIT_SET", 1); +-- ... +-------------------------------------------------------- + elsif (instruction(1 to len) = "MAX_WAIT_SET") then + MAX_TIME <= par1; -- set the max + wait for 0 ps; + +architecture bhv of tb_xxx is +-- ... + signal irq_expect : boolean := false; +-- ... +Read_file : process +-- ... + define_instruction(inst_list, "EXPECT_IRQ", 1); +-- ... +-------------------------------------------------------------------------------- + elsif (instruction(1 to len) = "EXPECT_IRQ") then + if(par1 = 0) then + irq_expect <= false; + else + irq_expect <= true; + end if; + wait for 0 ps; +-- ... + end process Read_file; + +------------------------ +irq_mon: + process(clk, dut_irq) + begin + -- on the falling edge, assume rising edge assertion, one clock wide + if(clk'event and clk = '0') then + if(dut_irq = '1') then + if(irq_expect = true) then + assert (false) + report "NOTE: An expected IRQ occurred." + severity note; + else + assert (false) + report "ERROR: An unexpected IRQ occurred." + severity failure; + end if; + end if; + end if; +end process irq_mon; +-- END Section 1: +--################################################################################### + + +------------------------------------------------------------------------------------- +--################################################################################### +-- Section 2: CPU Emulation Commands +-- starting from the top of the bhv architecture +architecture bhv of xxx_tb is + -- create type for cpu array of registers + -- Type needed for CPU registers, it can be resized if needed + type cpu_reg_array is array(0 to 7) of std_logic_vector(31 downto 0); + -- optional constant to help test for zero + constant zeros : std_logic_vector(31 downto 0) := (others => '0'); +-- ... +-- ... + -------------------------------------------------------------------------- + Read_file: process +-- ... variable definitions + ------------------- + -- CCR def + -- bit 0 zero, will be set when results are zero + -- bit 1 equal, will be set when compared values are equal + -- bit 2 greater than, will be set when source1 is > source2 + -- bit 3 less than, will be set when source1 is < source2 + -- others undefined + variable v_reg_ccr : std_logic_vector(7 downto 0); -- condition code register + variable v_regs : cpu_reg_array; -- Create variable of cpu regs + variable v_tmp_bit : std_logic; -- nice place to store a bit temp + variable v_read_data : std_logic_vector(31 downto 0); +-- ... + begin -- process Read_file +-- ... + define_instruction(inst_list, "READ_TO_REG", 2); + define_instruction(inst_list, "REG_TO_VAR", 2); + define_instruction(inst_list, "MOV", 2); + define_instruction(inst_list, "MOVI", 2); + define_instruction(inst_list, "AND", 3); + define_instruction(inst_list, "ANDI", 3); + define_instruction(inst_list, "OR", 3); + define_instruction(inst_list, "NOT", 2); + define_instruction(inst_list, "XOR", 3); + define_instruction(inst_list, "SLL", 2); + define_instruction(inst_list, "SLR", 2); + define_instruction(inst_list, "CMP", 2); + define_instruction(inst_list, "BE", 1); + define_instruction(inst_list, "BZ", 1); + define_instruction(inst_list, "BB", 4); + + ------------------------------------------------------------------------ + -- Read, test, and load the stimulus file + read_instruction_file(stimulus_file, inst_list, defined_vars, inst_sequ, + file_list); + -- initialize last info + last_sequ_num := 0; + last_sequ_ptr := inst_sequ; + -- initialize registers -- this is the zering of the registers and CCR + v_regs := (others => (others => '0')); + v_reg_ccr := (others => '0'); +-- ... +-------------------------------------------------------------------------- +-- READ_TO_REG +-- Read a addressed location to the local register array +-- par1 address +-- par2 target reg (index) + elsif(instruction(1 to len) = "READ_TO_REG") then + v_temp_vec1 := std_logic_vector(conv_unsigned(par1, 32)); + STM_ADD <= v_temp_vec1; + STM_DAT <= (others => 'Z'); + STM_RWN <= '1'; + wait for 1 ps; + STM_REQ_N <= '0'; + wait until STM_ACK_N'event and STM_ACK_N = '0'; + STM_REQ_N <= '1'; + STM_ADD <= (others => 'Z'); + v_read_data := STM_DAT; + v_regs(par2) := STM_DAT; + STM_RWN <= '1'; + wait for 1 ps; + +-------------------------------------------------------------------------- +-- REG_TO_VAR +-- Write a register array value to a Variable. +-- par1 target reg (index) +-- par2 Variable to update with value from target reg + elsif(instruction(1 to len) = "REG_TO_VAR") then + temp_int := to_uninteger(v_regs(par1)); --<< NEW to_uninteger conversion function + update_variable(defined_vars, par2, temp_int, valid); +-- the to_uninteger function was added because to add the function through +-- std_developerskit overflowed my PE student simulator. I am tired of +-- conversion and created my own function, tb_pkg contained. see additional +-- code at the bottom of this section. You can replace this with functions +-- you usually use, or use std_developerskit if you are on real tools. +-------------------------------------------------------------------------- +-- MOV +-- Move one register contents to another register. Source contents maintained +-- par1 reg1 index +-- par2 reg2 index + elsif(instruction(1 to len) = "MOV") then + v_regs(par2) := v_regs(par1); + +-------------------------------------------------------------------------- +-- MOVI +-- Move value passed to destination register +-- par1 value +-- par2 reg index + elsif(instruction(1 to len) = "MOVI") then + v_regs(par2) := std_logic_vector(conv_unsigned(par1, 32)); + +-------------------------------------------------------------------------- +-- AND +-- AND two registers and write results to target register +-- par1 reg1 index +-- par2 reg2 index +-- par3 target results reg index + elsif(instruction(1 to len) = "AND") then + v_regs(par3) := v_regs(par1) and v_regs(par2); + if(v_regs(par3) = zeros) then + v_reg_ccr(0) := '1'; + else + v_reg_ccr(0) := '0'; + end if; + +-------------------------------------------------------------------------- +-- ANDI +-- AND the passed value with the indexed register and store in register index +-- par1 value +-- par2 reg index +-- par3 target results reg index + elsif(instruction(1 to len) = "ANDI") then + v_regs(par3) := std_logic_vector(conv_unsigned(par1, 32)) and v_regs(par2); + if(v_regs(par3) = zeros) then + v_reg_ccr(0) := '1'; + else + v_reg_ccr(0) := '0'; + end if; + +-------------------------------------------------------------------------- +-- OR +-- OR two registers and write results to target register +-- par1 reg1 index +-- par2 reg2 index +-- par3 target results reg index + elsif(instruction(1 to len) = "OR") then + v_regs(par3) := v_regs(par1) or v_regs(par2); + if(v_regs(par3) = zeros) then + v_reg_ccr(0) := '1'; + else + v_reg_ccr(0) := '0'; + end if; + +-------------------------------------------------------------------------- +-- XOR +-- XOR two registers and write results to target register +-- par1 reg1 index +-- par2 reg2 index +-- par3 target results reg index + elsif(instruction(1 to len) = "XOR") then + v_regs(par3) := v_regs(par1) xor v_regs(par2); + if(v_regs(par3) = zeros) then + v_reg_ccr(0) := '1'; + else + v_reg_ccr(0) := '0'; + end if; + +-------------------------------------------------------------------------- +-- NOT +-- NOT a register and write results to target register +-- par1 reg1 index +-- par2 target results reg index + elsif(instruction(1 to len) = "NOT") then + v_regs(par2) := not v_regs(par1); + if(v_regs(par2) = zeros) then + v_reg_ccr(0) := '1'; + else + v_reg_ccr(0) := '0'; + end if; + +-------------------------------------------------------------------------- +-- SLL +-- Shift the register left rotate the upper bits into the lower bits +-- par1 reg1 index +-- par2 bit positions to Left + elsif(instruction(1 to len) = "SLL") then + v_temp_vec1 := v_regs(par1); + temp_int := par2 - 1; + v_regs(par1) := v_temp_vec1(31-par2 downto 0) & v_temp_vec1(31 downto 31 - temp_int); + +-------------------------------------------------------------------------- +-- SLR +-- Shift the register right rotate the lower bits into the upper bits +-- par1 reg1 index +-- par2 bit positions to Right + elsif(instruction(1 to len) = "SLR") then + v_temp_vec1 := v_regs(par1); + temp_int := par2 - 1; + v_regs(par1) := v_temp_vec1(temp_int downto 0) & v_temp_vec1(31 downto par2); + +-------------------------------------------------------------------------- +-- CMP +-- Compare one register against another and set CCR bits, no effect on registers +-- par1 reg1 index source1 +-- par2 reg2 index source2 + elsif(instruction(1 to len) = "CMP") then + v_reg_ccr := (others => '0'); + if(v_regs(par1) = v_regs(par2)) then + v_reg_ccr(1) := '1'; + elsif(v_regs(par1) > v_regs(par2)) then + v_reg_ccr(2) := '1'; + elsif(v_regs(par1) < v_regs(par2)) then + v_reg_ccr(3) := '1'; + end if; + + if(v_regs(par1) = zeros) then + v_reg_ccr(1) := '0'; + end if; + +-------------------------------------------------------------------------- +-- BE +-- Branch if equal +-- par1 jump location + elsif(instruction(1 to len) = "BE") then + if(v_reg_ccr(1) = '1') then + v_line := par1 - 1; + wh_state := false; + wh_stack := (others => 0); + wh_dpth := 0; + wh_ptr := 0; + --stack := (others => 0); + --stack_ptr := 0; + end if; + +-------------------------------------------------------------------------- +-- BZ +-- Branch if Zero +-- par1 jump location + elsif(instruction(1 to len) = "BZ") then + if(v_reg_ccr(0) = '1') then + v_line := par1 - 1; + wh_state := false; + wh_stack := (others => 0); + wh_dpth := 0; + wh_ptr := 0; + --stack := (others => 0); + --stack_ptr := 0; + end if; + +-------------------------------------------------------------------------- +-- BB +-- Branch if bit in register is set/clear +-- par1 register +-- par2 register bit index +-- par3 compare value : 0/1 +-- par4 jump location + elsif(instruction(1 to len) = "BB") then + v_temp_vec1 := v_regs(par1); + if(par3 = 0) then + v_tmp_bit := '0'; + else + v_tmp_bit := '1'; + end if; + if(v_temp_vec1(par2) = v_tmp_bit) then + v_line := par4 - 1; + wh_state := false; + wh_stack := (others => 0); + wh_dpth := 0; + wh_ptr := 0; + --stack := (others => 0); + --stack_ptr := 0; + end if; +-- ... + end process Read_file; +end bhv; +-- Stimulus_file commands used for testing. I used no VERIFY command +-- as I watched the functionality in single stepping through code. +DEFINE_VAR dat x01 +EQU_VAR dat x12345678 +MASTR_WRITE 3 $dat +READ_TO_REG 3 0 +OR 0 1 2 +AND 0 2 1 +MOV 1 3 +XOR 0 1 4 +NOT 4 5 +SLL 0 1 +SLL 1 2 +SLL 2 3 +SLL 3 4 +SLR 0 1 +SLR 1 2 +SLR 2 3 +SLR 3 4 +MOVI x87654321 7 + +ANDI 0 0 0 +BZ $B1 +MOVI x1234678 0 + +B1: +CMP 1 2 +BE $B2 +MOVI 0 1 + +B2: +BB 0 0 1 $B3 +BB 0 0 0 $B3 "Didnt jup as expected +MOVI 0 1 + +B3: + +FINISH + +-------------------------------------------------------------------------------- +-- tb_pkg function +--- header section +------------------------------------------------------------------------- +-- convert a std_logic_vector to an unsigned integer + function to_uninteger ( constant vect : in std_logic_vector + ) return integer; +-- body section +--------------------------------------------------------------------------------------- + function to_uninteger ( constant vect : in std_logic_vector + ) return integer is + variable result : integer := 0; + variable len : integer := vect'length; + variable idx : integer; + variable tmp_str : text_field; + variable file_name: text_line; + begin + -- point to start of string + idx := 1; + -- convert std_logic_vector to text_field + for i in len - 1 downto 0 loop + if(vect(i) = '1') then + tmp_str(idx) := '1'; + elsif(vect(i) = '0') then + tmp_str(idx) := '0'; + else + assert(false) + report LF & "ERROR: Non 0/1 value found in std_logic_vector passed to to_uninteger function!!" & LF & + "Returning 0." + severity note; + return result; + end if; + idx := idx + 1; + end loop; + -- call bin txt to int fuction with dummy fn and sequ idx + result := bin2integer(tmp_str, file_name, idx); + return result; + + end to_uninteger; + + + +-- Section 2: END +--################################################################################### + +-- +--################################################################################### +-- Section 3: Begin +-- This section presents the code needed to make an internal test bench +-- an optional compile item through the use of VHDL generics and generate +-- statements. + +-- this is the top enity or at the level where you can assign the +-- en_bfm generic and it makes sense +entity my_top_dut is + generic ( + g_en_bfm : integer := 0 + ); + port ( + -- top port definitions + ); +end enity my_top_dut; + + +architecture struct of my_top_dut is +-- this is the component of an internal block of my_top_dut +component rtl_block + port ( + reset_n : in std_logic; + clk_in : in std_logic; + -- ... + ); +end component; +-- bhv_block has the same pin out as rtl_block, except for the generic +component bhv_block + generic ( + stimulus_file: in string + ); + port ( + reset_n : in std_logic; + clk_in : in std_logic; + -- ... + ); +end component; +--.... +begin + -- if generic is default value, include rtl + if(g_en_bfm = 0) generate + begin + rtl_b1: rtl_block + port map( + reset_n => reset_n, + clk_in => clk, + -- ... + ); + end generate; + -- if generic is set for bhv, include it + if(g_en_bfm = 1) generate + begin + bfm: bhv_block + generic map( + stimulus_file => "stm/stimulus_file.stm" + ) + port map( + reset_n => reset_n, + clk_in => clk, + -- ... + ); + end generate; +-- ... +end struct; + +-- Section 3 End: +--################################################################### + +--#################################################################### +-- Section 4 Start: +-- This section provides some example VERIFY commands. + -------------------------------------------------------------------------- + Read_file: process + -- ... + variable v_tmp_bit : std_logic; + variable v_upb : integer := 31; -- upper bounds + variable v_lob : integer := 0; -- lower bounds + variable v_temp_read : std_logic_vector(31 downto 0); + -- ... + define_instruction(inst_list, "SLICE_SET", 2); + define_instruction(inst_list, "VERIFY", 1); + define_instruction(inst_list, "VERIFY_BIT", 2); + define_instruction(inst_list, "VERIFY_SLICE", 1); + -- ... + + +----------------------------------------------------------------------------- +-- SLICE_SET set the slice of the data for testing +-- par1 upper bound value - must be larger than par2 and less than 32 +-- par2 lower bound value + elsif (instruction(1 to len) = "SLICE_SET") then + -- test user input. + assert (par1 < 32 and par1 >= 1) + report LF & "ERROR: Par1 in SLICE_SET command input range is out of bounds" & LF & + "Found on line " & (integer'image(file_line)) & " in file " & file_name + severity failure; + assert (par2 < 31 and par2 >= 0) + report LF & "ERROR: Par2 in SLICE_SET command input range is out of bounds" & LF & + "Found on line " & (integer'image(file_line)) & " in file " & file_name + severity failure; + assert (par1 > par2) + report LF & "ERROR: SLICE_SET command bounds incorrectly defined. Par1 must be greater than Par2." & LF & + "Found on line " & (integer'image(file_line)) & " in file " & file_name + severity failure; + -- update variables + v_upb := par1; + v_lob := par2; + +----------------------------------------------------------------------------- +-- VERIFY test that the data in temp_read is the passed value. +-- par1 value to test against. + elsif (instruction(1 to len) = "VERIFY") then + v_temp_vec1 := std_logic_vector(conv_unsigned(par1, 32)); + + assert (v_temp_vec1 = v_temp_read) + report LF & "ERROR: VERIFY command compare value was not as expected!!" & + LF & "Got " & (to_hstring(v_temp_read)) & + LF & "Expected " & (to_hstring(v_temp_vec1)) & LF & + "Found on line " & (integer'image(file_line)) & " in file " & file_name + severity failure; + +----------------------------------------------------------------------------- +-- VERIFY_BIT test that the data bit in temp_read is the passed value. +-- par1 index into 32 bit temp_read +-- par2 bit value + elsif (instruction(1 to len) = "VERIFY_BIT") then + assert (par1 >= 0 and par1 < 32) + report LF & "ERROR: VERIFY_BIT command bit index is out of range. Valid is 0 - 31." & LF & + "Found on line " & (integer'image(file_line)) & " in file " & file_name + severity failure; + if(par2 = 0) then + v_tmp_bit := '0'; + else + v_tmp_bit := '1'; + end if; + assert (v_temp_read(par1) = v_tmp_bit) + report LF & "ERROR: VERIFY_BIT command miss-compare!" & LF & + "We tested for " & (integer'image(par2)) & LF & + "Found on line " & (integer'image(file_line)) & " in file " & file_name + severity failure; + +----------------------------------------------------------------------------- +-- VERIFY_SLICE test that the data in temp_read is the passed value. +-- par1 value + elsif (instruction(1 to len) = "VERIFY_SLICE") then + v_temp_vec1 := (others => '0'); + temp_int := v_upb - v_lob + 1; + v_temp_vec1(v_upb downto v_lob) := std_logic_vector(conv_unsigned(par1, temp_int)); + -- no need to test ranges here + assert (v_temp_vec1(v_upb downto v_lob) = v_temp_read(v_upb downto v_lob)) + report LF & "ERROR: VERIFY_SLICE Compare Value was not as expected!!" & + LF & "Got " & (to_hstring(v_temp_read(v_upb downto v_lob))) & + LF & "Expected " & (to_hstring(v_temp_vec1(v_upb downto v_lob))) & LF & + "Found on line " & (integer'image(file_line)) & " in file " & file_name + severity failure; + +-- END Section 4 +--#######################################################################################

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.