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
+--#######################################################################################