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

Subversion Repositories vhld_tb

[/] [vhld_tb/] [trunk/] [source/] [tb_pkg_body.vhd] - Blame information for rev 19

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 sckoarn
-------------------------------------------------------------------------------
2
--             Copyright 2011  Ken Campbell
3
-------------------------------------------------------------------------------
4
-- $Author: sckoarn $
5
--
6
-- $Date:  $
7
--
8
-- $Id:  $
9
--
10
-- $Source:  $
11
--
12
-- Description :  The the testbench package body file.
13
--                GNU release 2 Beta.
14
--
15
------------------------------------------------------------------------------
16
--This file is part of The VHDL Test Bench.
17
--
18
--    The VHDL Test Bench is free software; you can redistribute it and/or modify
19
--    it under the terms of the GNU General Public License as published by
20
--    the Free Software Foundation; either version 2 of the License, or
21
--    (at your option) any later version.
22
--
23
--    The VHDL Test Bench is distributed in the hope that it will be useful,
24
--    but WITHOUT ANY WARRANTY; without even the implied warranty of
25
--    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
--    GNU General Public License for more details.
27
--
28
--    You should have received a copy of the GNU General Public License
29
--    along with The VHDL Test Bench; if not, write to the Free Software
30
--    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
31
-------------------------------------------------------------------------------
32
 
33
package body tb_pkg is
34
 
35
-------------------------------------------------------------------------------
36
-- FUNCTION Defs
37
-------------------------------------------------------------------------------
38
--  is_digit
39
 function is_digit(constant c: in character) return boolean is
40
   variable rtn : boolean;
41
 begin
42
   if (c >= '0' and c <= '9') then
43
        rtn := true;
44
   else
45
        rtn := false;
46
   end if;
47
   return rtn;
48
 end is_digit;
49
--------------------------------------
50
-- is_space
51
 function is_space(constant c: in character) return boolean is
52
   variable rtn : boolean;
53
 begin
54
   if(c = ' ' or c = ht) then
55
        rtn := true;
56
   else
57
        rtn := false;
58
   end if;
59
   return rtn;
60
 end is_space;
61
------------------------------------------------------------------------------
62
--  to_char
63
  function ew_to_char(int: integer) return character is
64
    variable c: character;
65
  begin
66
    c := nul;
67
    case int is
68
      when 0 => c := '0';
69
      when 1 => c := '1';
70
      when 2 => c := '2';
71
      when 3 => c := '3';
72
      when 4 => c := '4';
73
      when 5 => c := '5';
74
      when 6 => c := '6';
75
      when 7 => c := '7';
76
      when 8 => c := '8';
77
      when 9 => c := '9';
78
      when 10 => c := 'A';
79
      when 11 => c := 'B';
80
      when 12 => c := 'C';
81
      when 13 => c := 'D';
82
      when 14 => c := 'E';
83
      when 15 => c := 'F';
84
      when others =>
85
         assert(false)
86
           report LF & "Error: ew_to_char was given a non Number didgit."
87
         severity failure;
88
    end case;
89
 
90
    return c;
91
  end ew_to_char;
92
 
93
-------------------------------------------------------------------------------
94
--  to_string function  integer
95
  function to_str(int: integer) return string is
96
  begin
97
    return ew_to_str(int,dec) ;
98
  end to_str ;
99
 
100
-------------------------------------------------------------------------------
101
--  ew_str_cat
102
  function ew_str_cat(s1: stm_text;
103
                      s2: text_field) return stm_text is
104
 
105
    variable i:  integer;
106
    variable j:  integer;
107
    variable sc: stm_text;
108
 
109
  begin
110
    sc := s1;
111
    i := 1;
112
    while(sc(i) /= nul) loop
113
      i := i + 1;
114
    end loop;
115
    j := 1;
116
    while(s2(j) /= nul) loop
117
      sc(i) := s2(j);
118
      i := i + 1;
119
      j := j + 1;
120
    end loop;
121
 
122
    return sc;
123
  end ew_str_cat;
124
 
125
-------------------------------------------------------------------------------
126
-- fld_len    field length
127
--          inputs :  string of type text_field
128
--          return :  integer number of non 'nul' chars
129
function fld_len(s : in text_field) return integer is
130
    variable i:  integer := 1;
131
  begin
132
    while(s(i) /= nul) loop
133
      i := i + 1;
134
    end loop;
135
    return (i - 1);
136
  end fld_len;
137
------------------------------------------------------------------------------
138
-- c2int   convert character to integer
139
function c2int(c: in character) return integer is
140
  variable i:  integer;
141
begin
142
  i := -1;
143
  case c is
144
    when '0' => i := 0;
145
    when '1' => i := 1;
146
    when '2' => i := 2;
147
    when '3' => i := 3;
148
    when '4' => i := 4;
149
    when '5' => i := 5;
150
    when '6' => i := 6;
151
    when '7' => i := 7;
152
    when '8' => i := 8;
153
    when '9' => i := 9;
154
    when others =>
155
      assert(false)
156
        report LF & "Error: c2int was given a non Number didgit."
157
      severity failure;
158
  end case;
159
  return i;
160
end c2int;
161
-------------------------------------------------------------------------------
162
-- str2integer   Convert a string to integer number.
163
--   inputs  :  string
164
--   output  :  int value
165
function str2integer(str: in string) return integer is
166
  variable l:   integer;
167
  variable j:   integer := 1;
168
  variable rtn: integer := 0;
169
begin
170
  l := fld_len(str);
171
 
172
  for i in l downto 1 loop
173
    rtn := rtn + (c2int(str(j)) *(10**(i - 1)));
174
    j := j + 1;
175
  end loop;
176
 
177
  return rtn;
178
end str2integer;
179
-------------------------------------------------------------------------------
180
-- hex2integer    convert hex Stimulus field to integer
181
--          inputs :  string of type text_field containing only Hex numbers
182
--          return :  integer value
183
function hex2integer(hex_number:  in text_field;
184
                     file_name:   in text_line;
185
                     line:        in integer) return integer is
186
    variable len:         integer;
187
    variable temp_field:  text_field;
188
    variable temp_int:    integer;
189
    variable power:       integer;
190
    variable int_number:  integer;
191
  begin
192
     len      := fld_len(hex_number);
193
     power    := 0;
194
     temp_int := 0;
195
     for i in len downto 1 loop
196
       case hex_number(i) is
197
         when '0' =>
198
           int_number  := 0;
199
         when '1' =>
200
           int_number  := 1;
201
         when '2' =>
202
           int_number  := 2;
203
         when '3' =>
204
           int_number  := 3;
205
         when '4' =>
206
           int_number  := 4;
207
         when '5' =>
208
           int_number  := 5;
209
         when '6' =>
210
           int_number  := 6;
211
         when '7' =>
212
           int_number  := 7;
213
         when '8' =>
214
           int_number  := 8;
215
         when '9' =>
216
           int_number  := 9;
217
         when 'a' | 'A'=>
218
           int_number  := 10;
219
         when 'b' | 'B'=>
220
           int_number  := 11;
221
         when 'c' | 'C'=>
222
           int_number  := 12;
223
         when 'd' | 'D'=>
224
           int_number  := 13;
225
         when 'e' | 'E'=>
226
           int_number  := 14;
227
         when 'f' | 'F'=>
228
           int_number  := 15;
229
         when others =>
230
         assert(false)
231
           report LF & "Error: hex2integer found non Hex didgit on line "
232
                     & (integer'image(line)) & " of file " & file_name
233
         severity failure;
234
       end case;
235
 
236
       temp_int  := temp_int + (int_number *(16 ** power));
237
       power     := power + 1;
238
     end loop;
239
 
240
     return temp_int;
241
  end hex2integer;
242
-------------------------------------------------------------------------------
243
-- convert character to 4 bit vector
244
--   input    character
245
--   output   std_logic_vector  4 bits
246
function c2std_vec(c: in character) return std_logic_vector is
247
begin
248
  case c is
249
    when '0' =>  return "0000";
250
    when '1' =>  return "0001";
251
    when '2' =>  return "0010";
252
    when '3' =>  return "0011";
253
    when '4' =>  return "0100";
254
    when '5' =>  return "0101";
255
    when '6' =>  return "0110";
256
    when '7' =>  return "0111";
257
    when '8' =>  return "1000";
258
    when '9' =>  return "1001";
259
    when 'a' | 'A' =>  return "1010";
260
    when 'b' | 'B' =>  return "1011";
261
    when 'c' | 'C' =>  return "1100";
262
    when 'd' | 'D' =>  return "1101";
263
    when 'e' | 'E' =>  return "1110";
264
    when 'f' | 'F' =>  return "1111";
265
    when others =>
266
     assert(false)
267
       report LF & "Error: c2std_vec found non Hex didgit on file line "
268
     severity failure;
269
     return "XXXX";
270
  end case;
271
end c2std_vec;
272
-------------------------------------------------------------------------------
273
--  std_vec2c  convert 4 bit std_vector to a character
274
--     input  std_logic_vector 4 bits
275
--     output  character
276
function std_vec2c(vec: in std_logic_vector(3 downto 0)) return character is
277
begin
278
  case vec is
279
    when "0000" => return '0';
280
    when "0001" => return '1';
281
    when "0010" => return '2';
282
    when "0011" => return '3';
283
    when "0100" => return '4';
284
    when "0101" => return '5';
285
    when "0110" => return '6';
286
    when "0111" => return '7';
287
    when "1000" => return '8';
288
    when "1001" => return '9';
289
    when "1010" => return 'A';
290
    when "1011" => return 'B';
291
    when "1100" => return 'C';
292
    when "1101" => return 'D';
293
    when "1110" => return 'E';
294
    when "1111" => return 'F';
295
    when others =>
296
     assert(false)
297
       report LF & "Error: std_vec2c found non-binary didgit in vec "
298
     severity failure;
299
     return 'X';
300
  end case;
301
end std_vec2c;
302
-------------------------------------------------------------------------------
303
-- bin2integer    convert bin Stimulus field to integer
304
--          inputs :  string of type text_field containing only binary numbers
305
--          return :  integer value
306
function bin2integer(bin_number:  in text_field;
307
                     file_name:   in text_line;
308
                     line:        in integer) return integer is
309
    variable len:         integer;
310
    variable temp_field:  text_field;
311
    variable temp_int:    integer;
312
    variable power:       integer;
313
    variable int_number:  integer;
314
  begin
315
     len      := fld_len(bin_number);
316
     power    := 0;
317
     temp_int := 0;
318
     for i in len downto 1 loop
319
       case bin_number(i) is
320
         when '0' =>
321
           int_number  := 0;
322
         when '1' =>
323
           int_number  := 1;
324
         when others =>
325
         assert(false)
326
           report LF & "Error: bin2integer found non Binary didgit on line "
327
                     & (integer'image(line)) & " of file " & file_name
328
         severity failure;
329
       end case;
330
 
331
       if (int_number = 1) then
332
         temp_int  := temp_int + (int_number *(2 ** power));
333
       end if;
334
       power     := power + 1;
335
     end loop;
336
 
337
     return temp_int;
338
  end bin2integer;
339
-------------------------------------------------------------------------------
340
-- stim_to_integer    convert Stimulus field to integer
341
--          inputs :  string of type text_field "stimulus format of number"
342
--          return :  integer value
343
function stim_to_integer(field:      in text_field;
344
                         file_name:  in text_line;
345
                         line:       in integer) return integer is
346
    variable len:       integer;
347
    variable value:     integer := 1;
348
    variable temp_str : string(1 to 48);
349
  begin
350
    len := fld_len(field);
351
 
352
    case field(1) is
353
      when 'x' | 'h' =>
354
        value := 2;
355
        while(field(value) /= nul) loop
356
          temp_str(value - 1) := field(value);
357
          value := value + 1;
358
        end loop;
359
        value  := hex2integer(temp_str,file_name,line);
360
      when 'b' =>
361
        value := 2;
362
        while(field(value) /= nul) loop
363
          temp_str(value - 1) := field(value);
364
          value := value + 1;
365
        end loop;
366
        value  := bin2integer(temp_str,file_name,line);
367
      when others =>
368
--        value  := from_string(field(1 to len));
369
        value  := str2integer(field);
370
    end case;
371
    return value;
372
  end stim_to_integer;
373
 
374
-------------------------------------------------------------------------------
375
--  to_str function  with base parameter
376
--     Convert integer to number base
377
  function ew_to_str(int: integer; b: base) return text_field is
378
 
379
    variable temp  : text_field ;
380
    variable temp1 : text_field ;
381
    variable radix : integer := 0;
382
    variable num   : integer := 0;
383
    variable power : integer := 1;
384
    variable len   : integer := 1;
385
    variable pre   : string(1 to 2);
386
    variable i     : integer;
387
    variable j     : integer;
388
    variable vec   : std_logic_vector(31 downto 0);
389
 
390
  begin
391
 
392
    num := int;
393
    temp := (others => nul);
394
    case b is
395
      when bin =>
396
        radix := 2;                -- depending on what
397
        pre := "0b";
398
      when oct =>
399
        radix := 8;                -- base the number is
400
        pre := "0o";
401
      when hex =>
402
        radix := 16;               -- to be displayed as
403
        pre := "0x";
404
      when dec =>
405
        radix := 10;               -- choose a radix range
406
        pre := (others => nul);
407
    end case ;
408
    -- Now jump through Hoops because of sign
409
    if(num < 0 and b = hex) then
410
      vec := std_logic_vector(conv_unsigned(int, 32));
411
      temp(1) := std_vec2c(vec(31 downto 28));
412
      temp(2) := std_vec2c(vec(27 downto 24));
413
      temp(3) := std_vec2c(vec(23 downto 20));
414
      temp(4) := std_vec2c(vec(19 downto 16));
415
      temp(5) := std_vec2c(vec(15 downto 12));
416
      temp(6) := std_vec2c(vec(11 downto 8));
417
      temp(7) := std_vec2c(vec(7 downto 4));
418
      temp(8) := std_vec2c(vec(3 downto 0));
419
    else
420
      while num >= radix loop                   -- determine how many
421
        len := len + 1;                        -- characters required
422
        num := num / radix;                    -- to represent the
423
      end loop ;                                -- number.
424
      for i in len downto 1 loop                -- convert the number to
425
        temp(i) := ew_to_char(int/power mod radix); -- a string starting
426
        power := power * radix;                 -- with the right hand
427
      end loop ;                                -- side.
428
    end if;
429
    -- add prefix if is one
430
    if(pre(1) /= nul) then
431
      temp1 := temp;
432
      i := 1;
433
      j := 3;
434
      temp(1 to 2) := pre;
435
      while(temp1(i) /= nul) loop
436
        temp(j) := temp1(i);
437
        i := i + 1;
438
        j := j + 1;
439
      end loop;
440
    end if;
441
 
442
    return temp;
443
 
444
  end ew_to_str ;
445
 
446
---------------------------------------------------------------------------------------
447
-- convert std_logic_vector to an unsigned integer
448
  function to_uninteger ( constant vect     : in std_logic_vector
449
                        ) return integer is
450
    variable result   : integer := 0;
451
    variable len      : integer := vect'length;
452
    variable idx      : integer;
453
    variable tmp_str  : text_field;
454
    variable file_name: text_line;
455
  begin
456
    -- point to start of string
457
    idx  :=  1;
458
    -- convert std_logic_vector to text_field
459
    for i in len - 1 downto 0 loop
460
      if(vect(i) = '1') then
461
        tmp_str(idx) := '1';
462
      elsif(vect(i) = '0') then
463
        tmp_str(idx) := '0';
464
      else
465
        assert(false)
466
          report LF & "ERROR:  Non 0/1 value found in std_logic_vector passed to to_uninteger function!!" & LF &
467
                "Returning 0."
468
        severity note;
469
        return result;
470
      end if;
471
      idx := idx + 1;
472
    end loop;
473
    -- call bin txt to int fuction with dummy fn and sequ idx
474
    result := bin2integer(tmp_str, file_name, idx);
475
    return result;
476
 
477
  end to_uninteger;
478
 
479
 
480
--------------------
481
-- stm neut
482
  function stm_neut return stm_sctl is
483
    variable tmp  : stm_sctl;
484
  begin
485
    tmp.rst_n    :=  '1';
486
    tmp.addr     := (others => 'Z');
487
    tmp.wdat     := (others => 'Z');
488
    tmp.rwn      := 'Z';
489
    tmp.req_n    := 'Z';
490
    return tmp;
491
  end stm_neut;
492
 
493
  function stm_neut return stm_sack is
494
    variable tmp  : stm_sack;
495
  begin
496
    tmp.rdat     := (others => 'Z');
497
    tmp.ack_n    := '1';
498
    tmp.rdy_n    := '1';
499
    tmp.irq_n    := '1';
500
    return tmp;
501
  end stm_neut;
502
--------------------------------------------------------------------------------
503
--  access_variable
504
--     inputs:
505
--               Text field containing variable
506
--     outputs:
507
--               value  $VAR  returns Value of VAR
508
--               value  VAR   returns index of VAR
509
--
510
--               valid  is 1 if valid 0 if not
511
  procedure access_variable(variable var_list : in  var_field_ptr;
512
                            variable var      : in text_field;
513
                            variable value    : out integer;
514
                            variable valid    : out integer) is
515
    variable l          : integer;
516
    variable l_2        : integer;
517
    variable var_ptr    : var_field_ptr;
518
    variable temp_field : text_field;
519
    variable ptr        : integer := 0;  -- 0 is index, 1 is pointer
520
  begin
521
    l      := fld_len(var);
522
    valid  := 0;
523
    -- if the variable is a special
524
    if(var(1) = '=') then
525
          value  := 0;
526
          valid  := 1;
527
    elsif(var(1 to 2) = ">=") then
528
          value  := 4;
529
          valid  := 1;
530
    elsif(var(1 to 2) = "<=") then
531
          value  := 5;
532
          valid  := 1;
533
    elsif(var(1) = '>') then
534
          value  := 1;
535
          valid  := 1;
536
    elsif(var(1) = '<') then
537
          value  := 2;
538
          valid  := 1;
539
    elsif(var(1 to 2) = "!=") then
540
          value  := 3;
541
          valid  := 1;
542
 
543
    else
544
      if(var(1) = '$') then
545
        ptr := 1; -- this is a pointer
546
        for i in 2 to l loop
547
          temp_field(i-1) := var(i);
548
        end loop;
549
      else
550
        temp_field  :=  var;
551
      end if;
552
 
553
      var_ptr := var_list;
554
      while(var_ptr.next_rec  /= null) loop
555
        -- if we have a match
556
        if(temp_field = var_ptr.var_name) then
557
          if(ptr = 1) then
558
            value  := var_ptr.var_value;
559
            valid  := 1;
560
          else
561
            value  := var_ptr.var_index;
562
            valid  := 1;
563
          end if;
564
          exit;
565
        end if;
566
        var_ptr := var_ptr.next_rec;
567
      end loop;
568
 
569
      -- if we have a match and was the last record
570
      if(var_ptr.next_rec  = null and temp_field = var_ptr.var_name) then
571
        if(ptr = 1) then
572
          value  := var_ptr.var_value;
573
          valid  := 1;
574
        else
575
          value  := var_ptr.var_index;
576
          valid  := 1;
577
        end if;
578
      end if;
579
    end if;
580
  end access_variable;
581
--------------------------------------------------------------------------------
582
--  index_variable
583
--     inputs:
584
--               index:  the index of the variable being accessed
585
--     outputs:
586
--               Variable Value
587
--               valid  is 1 if valid 0 if not
588
  procedure index_variable(variable var_list : in  var_field_ptr;
589
                           variable index    : in  integer;
590
                           variable value    : out integer;
591
                           variable valid    : out integer) is
592
    variable ptr:  var_field_ptr;
593
  begin
594
    ptr    :=  var_list;
595
    valid  :=  0;
596
    while(ptr.next_rec  /= null) loop
597
      if(ptr.var_index = index) then
598
        value :=  ptr.var_value;
599
        valid :=  1;
600
        exit;
601
      end if;
602
      ptr  :=  ptr.next_rec;
603
    end loop;
604
    if(ptr.var_index = index) then
605
      value :=  ptr.var_value;
606
      valid :=  1;
607
    end if;
608
  end index_variable;
609
 
610
--------------------------------------------------------------------------------
611
--  update_variable
612
--     inputs:
613
--               index:  the index of the variable being updated
614
--     outputs:
615
--               valid  is 1 if valid 0 if not
616
  procedure update_variable(variable var_list : in  var_field_ptr;
617
                            variable index    : in  integer;
618
                            variable value    : in  integer;
619
                            variable valid    : out integer) is
620
    variable ptr:  var_field_ptr;
621
  begin
622
    ptr    :=  var_list;
623
    valid  :=  0;
624
    while(ptr.next_rec  /= null) loop
625
      if(ptr.var_index = index) then
626
        ptr.var_value :=  value;
627
        valid :=  1;
628
        exit;
629
      end if;
630
      ptr  :=  ptr.next_rec;
631
    end loop;
632
    -- check the current one
633
    if(ptr.var_index = index) then
634
      ptr.var_value :=  value;
635
      valid :=  1;
636
    end if;
637
  end update_variable;
638
 
639
-------------------------------------------------------------------------------
640
-- Read a line from a file
641
--   inputs  :   file of type text
642
--   outputs :   The line of type text_line
643
  procedure file_read_line(file file_name: text;
644
                           variable file_line: out text_line
645
                          ) is
646
    variable index:  integer;             -- index into string
647
    variable rline:  line;
648
 
649
  begin
650
 
651
    index := 1;  -- set index to begin of string
652
    file_line := (others => nul);
653
    if(not endfile(file_name)) then
654
      readline(file_name,rline);
655
 
656
      while(rline'right /= (index - 1) and rline'length /= 0) loop
657
        file_line(index) := rline(index);
658
        index    := index + 1;
659
      end loop;
660
    end if;
661
  end file_read_line;
662
 
663
  ------------------------------------------------------------------------------
664
  -- procedure to break a line down in to text fields
665
  procedure tokenize_line(variable text_line:   in  text_line;
666
                          variable token1:      out text_field;
667
                          variable token2:      out text_field;
668
                          variable token3:      out text_field;
669
                          variable token4:      out text_field;
670
                          variable token5:      out text_field;
671
                          variable token6:      out text_field;
672
                          variable token7:      out text_field;
673
                          variable txt_ptr:     out stm_text_ptr;
674
                          variable valid:       out integer) is
675
    variable token_index:     integer  :=  0;
676
    variable current_token:   text_field;
677
    variable token_number:    integer  :=  0;
678
    variable c:               string(1 to 2);
679
    variable comment_found:   integer  :=  0;
680
    variable txt_found:       integer  :=  0;
681
    variable j:               integer;
682
 
683
  begin
684
    -- null outputs
685
    token1  :=  (others => nul);
686
    token2  :=  (others => nul);
687
    token3  :=  (others => nul);
688
    token4  :=  (others => nul);
689
    token5  :=  (others => nul);
690
    token6  :=  (others => nul);
691
    token7  :=  (others => nul);
692
    txt_ptr :=  null;
693
    valid   :=  0;
694
    txt_found  :=  0;
695
    j := 1;
696
 
697
    -- loop for max number of char
698
    for i in 1 to text_line'high loop
699
      -- collect for comment test ** assumed no line will be max 256
700
      c(1)  := text_line(i);
701
      c(2)  := text_line(i + 1);  -- or this line will blow up
702
      if(c = "--") then
703
        comment_found  :=  1;
704
        exit;
705
      end if;
706
      -- if is begin text char '"'
707
      if(c(1) = '"') then  --"  <-- this double quote is just to fix highlighting.
708
        txt_found := 1;
709
        txt_ptr := new stm_text;
710
        next;
711
      end if;
712
 
713
      -- if we have found a txt string
714
      if (txt_found = 1 and text_line(i) /= nul) then
715
        -- if string too long, prevent tool hang, truncate and notify
716
        if(j > c_stm_text_len) then
717
          print("tokenize_line: truncated txt line, it was larger than c_stm_text_len");
718
          exit;
719
        end if;
720
        txt_ptr(j) := text_line(i);
721
        j := j + 1;
722
      -- if is a character store in the right token
723
      elsif(is_space(text_line(i)) = false and text_line(i) /= nul) then
724
        token_index  := token_index + 1;
725
        current_token(token_index)    := text_line(i);
726
      -- else is a space, deal with pointers
727
      elsif(is_space(text_line(i + 1)) = false and text_line(i + 1) /= nul) then
728
        case token_number is
729
          when 0 =>
730
            if(token_index /= 0) then
731
              token1  :=  current_token;
732
              current_token  :=  (others => nul);
733
              token_number := 1;
734
              valid        := 1;
735
              token_index  := 0;
736
            end if;
737
          when 1 =>
738
            token2  :=  current_token;
739
            current_token  :=  (others => nul);
740
            token_number := 2;
741
            valid        := 2;
742
            token_index  := 0;
743
          when 2 =>
744
            token3  :=  current_token;
745
            current_token  :=  (others => nul);
746
            token_number := 3;
747
            valid        := 3;
748
            token_index  := 0;
749
          when 3 =>
750
            token4  :=  current_token;
751
            current_token  :=  (others => nul);
752
            token_number := 4;
753
            valid        := 4;
754
            token_index  := 0;
755
          when 4 =>
756
            token5  :=  current_token;
757
            current_token  :=  (others => nul);
758
            token_number := 5;
759
            valid        := 5;
760
            token_index  := 0;
761
          when 5 =>
762
            token6  :=  current_token;
763
            current_token  :=  (others => nul);
764
            token_number := 6;
765
            valid        := 6;
766
            token_index  := 0;
767
          when 6 =>
768
            token7  :=  current_token;
769
            current_token  :=  (others => nul);
770
            token_number := 7;
771
            valid        := 7;
772
            token_index  := 0;
773
          when 7 =>
774
          when others =>
775
            null;
776
        end case;
777
      end if;
778
      -- break from loop if is null
779
      if(text_line(i) = nul) then
780
        if(token_index /= 0) then
781
          case token_number is
782
            when 0 =>
783
              token1  :=  current_token;
784
              valid   := 1;
785
            when 1 =>
786
              token2  :=  current_token;
787
              valid   := 2;
788
            when 2 =>
789
              token3  :=  current_token;
790
              valid   := 3;
791
            when 3 =>
792
              token4  :=  current_token;
793
              valid   := 4;
794
            when 4 =>
795
              token5  :=  current_token;
796
              valid   := 5;
797
            when 5 =>
798
              token6  :=  current_token;
799
              valid   := 6;
800
            when 6 =>
801
              token7  :=  current_token;
802
              valid   := 7;
803
            when others =>
804
              null;
805
          end case;
806
        end if;
807
        exit;
808
      end if;
809
    end loop;
810
    -- did we find a comment and there is a token
811
    if(comment_found = 1) then
812
      if(token_index /= 0) then
813
        case token_number is
814
          when 0 =>
815
            token1  :=  current_token;
816
            valid   := 1;
817
          when 1 =>
818
            token2  :=  current_token;
819
            valid   := 2;
820
          when 2 =>
821
            token3  :=  current_token;
822
            valid   := 3;
823
          when 3 =>
824
            token4  :=  current_token;
825
            valid   := 4;
826
          when 4 =>
827
            token5  :=  current_token;
828
            valid   := 5;
829
          when 5 =>
830
            token6  :=  current_token;
831
            valid   := 6;
832
          when 6 =>
833
            token7  :=  current_token;
834
            valid   := 7;
835
          when others =>
836
            null;
837
        end case;
838
      end if;
839
    end if;
840
  end tokenize_line;
841
-------------------------------------------------------------------------------
842
-- Add a new instruction to the instruction list
843
--   inputs  :   the linked list of instructions
844
--               the instruction
845
--               the number of args
846
--   outputs :   Updated instruction set linked list
847
  procedure define_instruction(variable inst_set: inout inst_def_ptr;
848
                               constant inst:     in    string;
849
                               constant args:     in    integer) is
850
    variable v_inst_ptr:    inst_def_ptr;
851
    variable v_prev_ptr:    inst_def_ptr;
852
    variable v_new_ptr:     inst_def_ptr;
853
    variable v_temp_inst:   inst_def_ptr;
854
    variable v_length:      integer;
855
    variable v_list_size:   integer;
856
    variable v_dup_error:   boolean;
857
 
858
  begin
859
    assert(inst'high <= max_field_len)
860
      report LF & "Error: Creation of Instruction of length greater than Max_field_len attemped!!" &
861
             LF & "This Max is currently set to " & (integer'image(max_field_len))
862
    severity failure;
863
    -- get to the last element and test is not exsiting
864
    v_temp_inst :=  inst_set;
865
    v_inst_ptr  :=  inst_set;
866
    -- zero the size
867
    v_list_size :=  0;
868
    while(v_inst_ptr /= null) loop
869
      -- if there is a chance of a duplicate command
870
      if(v_inst_ptr.instruction_l = inst'high) then
871
        v_dup_error := true;
872
        for i in 1 to inst'high loop
873
          if(v_inst_ptr.instruction(i) /= inst(i)) then
874
            v_dup_error := false;
875
          end if;
876
        end loop;
877
        -- if we find a duplicate, die
878
        assert(v_dup_error = false)
879
          report LF & "Error: Duplicate instruction definition attempted!"
880
        severity failure;
881
      end if;
882
      v_prev_ptr  := v_inst_ptr;  -- store for pointer updates
883
      v_inst_ptr  := v_inst_ptr.next_rec;
884
      v_list_size :=  v_list_size + 1;
885
    end loop;
886
 
887
    -- add the new instruction
888
    v_new_ptr   := new inst_def;
889
    -- if this is the first command return new pointer
890
    if(v_list_size = 0) then
891
      v_temp_inst :=  v_new_ptr;
892
    -- else write new pointer to next_rec
893
    else
894
      v_prev_ptr.next_rec  :=  v_new_ptr;
895
    end if;
896
    v_new_ptr.instruction_l := inst'high;
897
    v_new_ptr.params        := args;
898
    -- copy the instruction text into field
899
    for i in 1 to v_new_ptr.instruction_l loop
900
      v_new_ptr.instruction(i) := inst(i);
901
    end loop;
902
    -- return the pointer
903
    inst_set  :=  v_temp_inst;
904
 
905
  end define_instruction;
906
 
907
--------------------------------------------------------------------------------
908
--  Check for valid instruction in the list of instructions
909
procedure check_valid_inst(variable inst     :  in text_field;
910
                           variable inst_set :  in inst_def_ptr;
911
                           variable token_num:  in integer;
912
                           variable line_num :  in integer;
913
                           variable name     :  in text_line) is
914
    variable l :     integer  := 0;
915
    variable seti:   inst_def_ptr;
916
    variable match:  integer  := 0;
917
    variable ilv:    integer  := 0;  -- inline variable
918
  begin
919
    -- create useable pointer
920
    seti  := inst_set;
921
    -- count up the characters in inst
922
    l := fld_len(inst);
923
      -- if this is a referance variable -- handle in add variable Proc
924
    if(inst(l) = ':') then
925
      match  := 1;
926
      ilv    := 1;
927
    else
928
      -- process list till null next
929
      while (seti.next_rec /= null) loop
930
        if(seti.instruction_l = l) then
931
          match  := 1;
932
          for j in 1 to l loop
933
            if(seti.instruction(j) /= inst(j)) then
934
              match  := 0;
935
            end if;
936
          end loop;
937
        end if;
938
        if(match = 0) then
939
          seti  := seti.next_rec;
940
        else
941
          exit;
942
        end if;
943
      end loop;
944
      -- check current one
945
      if(seti.instruction_l = l and match = 0) then
946
        match  := 1;
947
        for j in 1 to l loop
948
          if(seti.instruction(j) /= inst(j)) then
949
            match  := 0;
950
          end if;
951
        end loop;
952
      end if;
953
    end if;
954
 
955
    -- if instruction was not found, die
956
    assert(match = 1)
957
      report LF & "Error: Undefined Instruction on line " & (integer'image(line_num)) &
958
                  " found in input file " & name & LF
959
    severity failure;
960
 
961
      -- if the definition of the number of parameters is > 6 skip testing
962
      --   this is how the variable number of parameters is implemented
963
      --   just skip testing for specified number
964
      if(seti.params > 6) then
965
        return;
966
      end if;
967
    -- if we had a match, check the number of paramiters
968
    if(match = 1 and ilv = 0) then
969
      assert(seti.params = (token_num - 1))
970
        report LF & "Error: Undefined Instruction was found, incorrect number of fields passed!" & LF &
971
                    "This is found on line " & (integer'image(line_num)) & " in file " & name & LF
972
      severity failure;
973
    end if;
974
  end check_valid_inst;
975
 
976
--------------------------------------------------------------------------------
977
--  add_variable
978
--    This procedure adds a variable to the variable list.  This is localy
979
--    available at this time.
980
procedure add_variable(variable var_list  :   inout  var_field_ptr;
981
                       variable p1        :  in text_field;  -- should be var name
982
                       variable p2        :  in text_field;  -- should be value
983
                       variable token_num :  in integer;
984
                       variable sequ_num  :  in integer;
985
                       variable line_num  :  in integer;
986
                       variable name      :  in text_line;
987
                       variable length    :  in integer) is
988
 
989
    variable temp_var:       var_field_ptr;
990
    variable current_ptr:    var_field_ptr;
991
    variable index:          integer := 1;
992
    variable len:            integer := 0;
993
 
994
  begin
995
    -- if this is NOT the first one
996
    if(var_list /= null) then
997
      current_ptr  := var_list;
998
      index        := index + 1;
999
      if(p1(length) /= ':') then  -- is not an inline variable
1000
        while(current_ptr.next_rec /= null) loop
1001
          -- if we have defined the current before then die
1002
          assert(current_ptr.var_name /= p1)
1003
            report LF & "Error: Attemping to add a duplicate Variable definition "
1004
                      & " on line " & (integer'image(line_num)) & " of file " & name
1005
          severity failure;
1006
 
1007
          current_ptr  :=  current_ptr.next_rec;
1008
          index  := index + 1;
1009
        end loop;
1010
        -- if we have defined the current before then die. This checks the last one
1011
        assert(current_ptr.var_name /= p1)
1012
          report LF & "Error: Attemping to add a duplicate Variable definition "
1013
                    & " on line " & (integer'image(line_num)) & " of file " & name
1014
        severity failure;
1015
 
1016
        temp_var              := new var_field;
1017
        temp_var.var_name     := p1;  -- direct write of text_field
1018
        temp_var.var_value    := stim_to_integer(p2,name,line_num); -- convert text_field to integer
1019
        temp_var.var_index    := index;
1020
        current_ptr.next_rec  :=  temp_var;
1021
      else  -- this is an inline variable
1022
        while(current_ptr.next_rec /= null) loop
1023
          -- if we have defined the current before then die
1024
          len  :=  fld_len(current_ptr.var_name);
1025
          assert(current_ptr.var_name(1 to len) /= p1(1 to (length - 1)))
1026
            report LF & "Error: Attemping to add a duplicate Inline Variable definition "
1027
                      & " on line " & (integer'image(line_num)) & " of file " & name
1028
          severity failure;
1029
 
1030
          current_ptr  :=  current_ptr.next_rec;
1031
          index  := index + 1;
1032
        end loop;
1033
        -- if we have defined the current before then die. This checks the last one
1034
        len  :=  fld_len(current_ptr.var_name);
1035
        assert(current_ptr.var_name(1 to len) /= p1(1 to (length - 1)))
1036
          report LF & "Error: Attemping to add a duplicate Inline Variable definition "
1037
                    & " on line " & (integer'image(line_num)) & " of file " & name
1038
        severity failure;
1039
 
1040
        temp_var              := new var_field;
1041
        temp_var.var_name(1 to (length - 1))     := p1(1 to (length - 1));
1042
        temp_var.var_value    := sequ_num;
1043
        temp_var.var_index    := index;
1044
        current_ptr.next_rec  :=  temp_var;
1045
      end if;
1046
    -- this is the first one
1047
    else
1048
      if(p1(length) /= ':') then  -- is not an inline variable
1049
        temp_var            := new var_field;
1050
        temp_var.var_name   := p1;  -- direct write of text_field
1051
        temp_var.var_index  := index;
1052
        temp_var.var_value  := stim_to_integer(p2,name,line_num); -- convert text_field to integer
1053
        var_list  :=  temp_var;
1054
      else
1055
        temp_var              := new var_field;
1056
        temp_var.var_name(1 to (length - 1))     := p1(1 to (length - 1));
1057
        temp_var.var_value    := sequ_num;
1058
        temp_var.var_index    := index;
1059
        var_list              :=  temp_var;
1060
      end if;
1061
    end if;
1062
  end add_variable;
1063
--------------------------------------------------------------------------------
1064
--  add_instruction
1065
--    This is the procedure that adds the instruction to the linked list of
1066
--    instructions.  Also Variable addition are called and or handled.
1067
--    the instruction sequence Link list.
1068
--     inputs:
1069
--               stim_line_ptr   is the pointer to the instruction List
1070
--               inst            is the instruction token
1071
--               p1              paramitor one, corrisponds to field one of stimulus
1072
--               p2              paramitor one, corrisponds to field two of stimulus
1073
--               p3              paramitor one, corrisponds to field three of stimulus
1074
--               p4              paramitor one, corrisponds to field four of stimulus
1075
--               p5              paramitor one, corrisponds to field three of stimulus
1076
--               p6              paramitor one, corrisponds to field four of stimulus
1077
--               str_ptr         pointer to string for print instruction
1078
--               token_num       the number of tokens, including instruction
1079
--               sequ_num        is the stimulus file line referance  ie program line number
1080
--               line_num        Line number in the text file
1081
--     outputs:
1082
--               none.  Error will terminate sim
1083
  procedure add_instruction(variable inst_list  :  inout stim_line_ptr;
1084
                            variable var_list   :  inout var_field_ptr;
1085
                            variable inst       :  in text_field;
1086
                            variable p1         :  in text_field;
1087
                            variable p2         :  in text_field;
1088
                            variable p3         :  in text_field;
1089
                            variable p4         :  in text_field;
1090
                            variable p5         :  in text_field;
1091
                            variable p6         :  in text_field;
1092
                            variable str_ptr    :  in stm_text_ptr;
1093
                            variable token_num  :  in integer;
1094
                            variable sequ_num   :  inout integer;
1095
                            variable line_num   :  in integer;
1096
                            variable file_name  :  in text_line;
1097
                            variable file_idx   :  in integer) is
1098
   variable temp_stim_line:  stim_line_ptr;
1099
   variable temp_current:    stim_line_ptr;
1100
   variable valid:           integer;
1101
   variable l:               integer;
1102
 begin
1103
   valid  := 1;
1104
   l := fld_len(inst);
1105
   temp_current  :=  inst_list;
1106
   -- take care of special cases
1107
   if(inst(1 to l) = "DEFINE_VAR") then
1108
     l := fld_len(p1);
1109
     --  Add the variable to the Variable pool, not considered an instruction
1110
     add_variable(var_list,p1,p2,token_num,sequ_num,line_num,file_name,l);
1111
     valid := 0;  --Removes this from the instruction list
1112
   elsif(inst(l) = ':') then
1113
     add_variable(var_list,inst,p1,token_num,sequ_num,line_num,file_name,l);
1114
     valid := 0;
1115
   end if;
1116
 
1117
   if(valid = 1) then
1118
     -- prepare the new record
1119
     temp_stim_line  := new stim_line;
1120
     temp_stim_line.instruction   := inst;
1121
     temp_stim_line.inst_field_1  := p1;
1122
     temp_stim_line.inst_field_2  := p2;
1123
     temp_stim_line.inst_field_3  := p3;
1124
     temp_stim_line.inst_field_4  := p4;
1125
     temp_stim_line.inst_field_5  := p5;
1126
     temp_stim_line.inst_field_6  := p6;
1127
     temp_stim_line.txt           := str_ptr;
1128
     temp_stim_line.line_number   := sequ_num;
1129
     temp_stim_line.file_idx     := file_idx;
1130
     temp_stim_line.file_line     := line_num;
1131
 
1132
     -- if is not the first instruction
1133
     if(inst_list /= null) then
1134
       while(temp_current.next_rec /= null) loop
1135
         temp_current  := temp_current.next_rec;
1136
       end loop;
1137
       temp_current.next_rec  :=  temp_stim_line;
1138
       inst_list.num_of_lines :=  inst_list.num_of_lines + 1;
1139
     -- other wise is first instruction to be added
1140
     else
1141
       inst_list  :=  temp_stim_line;
1142
       inst_list.num_of_lines := 1;
1143
     end if;
1144
     sequ_num  :=  sequ_num + 1;
1145
--     print_inst(temp_stim_line);  -- for debug
1146
   end if;
1147
 
1148
 end add_instruction;
1149
------------------------------------------------------------------------------
1150
-- test_inst_sequ
1151
--  This procedure accesses the full instruction sequence and checks for valid
1152
--   variables.  This is prior to the simulation run start.
1153
  procedure test_inst_sequ(variable inst_sequ  :  in  stim_line_ptr;
1154
                           variable file_list  :  in  file_def_ptr;
1155
                           variable var_list   :  in  var_field_ptr
1156
                          ) is
1157
    variable temp_text_field:     text_field;
1158
    variable temp_var:            text_field;
1159
    variable inst_ptr:            stim_line_ptr;
1160
    variable valid:               integer;
1161
    variable line:                integer;  -- value of the file_line
1162
    variable file_name:           text_line;
1163
    variable v_p:                 integer;
1164
    variable inst       :         text_field;
1165
    variable txt        :         stm_text_ptr;
1166
    variable inst_len   :         integer;
1167
    variable fname      :         text_line;
1168
    variable file_line  :         integer;
1169
    variable temp_fn_prt:         file_def_ptr;
1170
    variable tmp_int    :         integer;
1171
 
1172
  begin
1173
    inst_ptr  :=  inst_sequ;
1174
    -- go through all the instructions
1175
    while(inst_ptr.next_rec /= null) loop
1176
      inst := inst_ptr.instruction;
1177
      inst_len := fld_len(inst_ptr.instruction);
1178
      file_line := inst_ptr.file_line;
1179
      line      := inst_ptr.file_line;
1180
      -- recover the file name this line came from
1181
      temp_fn_prt := file_list;
1182
      tmp_int   :=  inst_ptr.file_idx;
1183
      while (temp_fn_prt.next_rec /= null) loop
1184
        if(temp_fn_prt.rec_idx = tmp_int) then
1185
          exit;
1186
        end if;
1187
        temp_fn_prt  :=  temp_fn_prt.next_rec;
1188
      end loop;
1189
      for i in 1 to fname'high loop
1190
        file_name(i) :=  temp_fn_prt.file_name(i);
1191
      end loop;
1192
 
1193
      txt       := inst_ptr.txt;
1194
      -- load parameter one
1195
      temp_text_field  :=  inst_ptr.inst_field_1;
1196
      if(temp_text_field(1) /= nul) then
1197
        -- if this is a numaric  do nothing
1198
        if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1199
           temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
1200
           null;
1201
        else  -- else is a variable, get the value or halt incase of error
1202
          access_variable(var_list,temp_text_field,v_p,valid);
1203
          assert(valid = 1)
1204
            report LF & "Error: First variable on stimulus line " & (integer'image(line))
1205
                      & " is not valid!!" & LF & "In file " & file_name
1206
          severity failure;
1207
        end if;
1208
      end if;
1209
      -- load parameter two
1210
      temp_text_field  :=  inst_ptr.inst_field_2;
1211
      if(temp_text_field(1) /= nul) then
1212
        -- if this is a numaric do nothing
1213
        if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1214
           temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
1215
           null;
1216
        else  -- else is a variable, get the value or halt incase of error
1217
          access_variable(var_list,temp_text_field,v_p,valid);
1218
          assert(valid = 1)
1219
            report LF & "Error: Second variable on stimulus line " & (integer'image(line))
1220
                      & " is not valid!!" & LF & "In file " & file_name
1221
          severity failure;
1222
        end if;
1223
      end if;
1224
      -- load parameter three
1225
      temp_text_field  :=  inst_ptr.inst_field_3;
1226
      if(temp_text_field(1) /= nul) then
1227
        -- if this is a numaric do nothing
1228
        if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1229
           temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
1230
           null;
1231
        else  -- else is a variable, get the value or halt incase of error
1232
          access_variable(var_list,temp_text_field,v_p,valid);
1233
          assert(valid = 1)
1234
            report LF & "Error: Third variable on stimulus line " & (integer'image(line))
1235
                      & " is not valid!!" & LF & "In file " & file_name
1236
          severity failure;
1237
        end if;
1238
      end if;
1239
      -- load parameter four
1240
      temp_text_field  :=  inst_ptr.inst_field_4;
1241
      if(temp_text_field(1) /= nul) then
1242
        -- if this is a numaric do nothing
1243
        if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1244
           temp_text_field(1) = 'b'or is_digit(temp_text_field(1)) = true) then
1245
           null;
1246
        else  -- else is a variable, get the value or halt incase of error
1247
          access_variable(var_list,temp_text_field,v_p,valid);
1248
          assert(valid = 1)
1249
            report LF & "Error: Forth variable on stimulus line " & (integer'image(line))
1250
                      & " is not valid!!" & LF & "In file " & file_name
1251
          severity failure;
1252
        end if;
1253
      end if;
1254
      -- load parameter five
1255
      temp_text_field  :=  inst_ptr.inst_field_5;
1256
      if(temp_text_field(1) /= nul) then
1257
        -- if this is a numaric do nothing
1258
        if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1259
          temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
1260
          null;
1261
        else  -- else is a variable, get the value or halt incase of error
1262
          access_variable(var_list,temp_text_field,v_p,valid);
1263
          assert(valid = 1)
1264
            report LF & "Error: Fifth variable on stimulus line " & (integer'image(line))
1265
                      & " is not valid!!" & LF & "In file " & file_name
1266
          severity failure;
1267
        end if;
1268
      end if;
1269
      -- load parameter six
1270
      temp_text_field  :=  inst_ptr.inst_field_6;
1271
      if(temp_text_field(1) /= nul) then
1272
        -- if this is a numaric field convert to integer
1273
        if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1274
           temp_text_field(1) = 'b' or is_digit(temp_text_field(1)) = true) then
1275
           null;
1276
        else  -- else is a variable, get the value or halt incase of error
1277
          access_variable(var_list,temp_text_field,v_p,valid);
1278
          assert(valid = 1)
1279
            report LF & "Error: Sixth variable on stimulus line " & (integer'image(line))
1280
                      & " is not valid!!" & LF & "In file " & file_name
1281
          severity failure;
1282
        end if;
1283
      end if;
1284
      -- point to next record
1285
      inst_ptr := inst_ptr.next_rec;
1286
    end loop;
1287
 
1288
  end test_inst_sequ;
1289
--------------------------------------------------------------------------------
1290
--  The read include file procedure
1291
--    This is the main procedure for reading, parcing, checking and returning
1292
--    the instruction sequence Link list.
1293
  procedure read_include_file(variable name:       text_line;
1294
                              variable sequ_numb:  inout integer;
1295
                              variable file_list:  inout file_def_ptr;
1296
                              variable inst_set:   inout inst_def_ptr;
1297
                              variable var_list:   inout var_field_ptr;
1298
                              variable inst_sequ:  inout stim_line_ptr;
1299
                              variable status:     inout integer) is
1300
    variable l:          text_line; -- the line
1301
    variable l_num:      integer;   -- line number file
1302
    variable sequ_line:  integer;   -- line number program
1303
    variable t1:         text_field;
1304
    variable t2:         text_field;
1305
    variable t3:         text_field;
1306
    variable t4:         text_field;
1307
    variable t5:         text_field;
1308
    variable t6:         text_field;
1309
    variable t7:         text_field;
1310
    variable t_txt:      stm_text_ptr;
1311
    variable valid:      integer;
1312
    variable v_inst_ptr: inst_def_ptr;
1313
    variable v_var_prt:  var_field_ptr;
1314
    variable v_sequ_ptr: stim_line_ptr;
1315
    variable v_len:      integer;
1316
    variable v_stat:     file_open_status;
1317
    variable idx:        integer;
1318
    variable v_tmp:      text_line;
1319
 
1320
    variable v_tmp_fn_ptr: file_def_ptr;
1321
    variable v_new_fn:     integer;
1322
    variable v_tmp_fn:   file_def_ptr;
1323
    variable v_txt:      stm_text; --stm_text_ptr;
1324
 
1325
  begin
1326
    sequ_line     :=  sequ_numb;
1327
    v_tmp_fn_ptr  :=  file_list;
1328
    -- for linux systems, trailing spaces need to be removed
1329
    --    from file names
1330
    --  copy text string to temp
1331
    for i in 1 to c_stm_text_len loop
1332
      if(name(i) = nul) then
1333
        v_tmp(i) := name(i);
1334
        exit;
1335
      else
1336
        v_tmp(i) := name(i);
1337
      end if;
1338
    end loop;
1339
    --fix up any trailing white space in txt
1340
    idx  :=  0;
1341
    --    get to the end of the string
1342
    for i in 1 to c_stm_text_len loop
1343
      if(v_tmp(i) /= nul) then
1344
        idx  :=  idx + 1;
1345
      else
1346
        exit;
1347
      end if;
1348
    end loop;
1349
    --  now nul out spaces
1350
    for i in idx downto 1 loop
1351
      if(is_space(v_tmp(i)) = true) then
1352
        v_tmp(i) := nul;
1353
      else
1354
        exit;
1355
      end if;
1356
    end loop;
1357
    --  open include file
1358
    file_open(v_stat, include_file, v_tmp, read_mode);
1359
    if(v_stat /= open_ok) then
1360
      print("Error: Unable to open include file  " & name);
1361
      status   :=  1;
1362
      return;
1363
    end if;
1364
    l_num      :=  1;  -- initialize line number
1365
 
1366
    --  the file is opened, put it on the file name LL
1367
    while (v_tmp_fn_ptr.next_rec /= null) loop
1368
      v_tmp_fn_ptr :=  v_tmp_fn_ptr.next_rec;
1369
    end loop;
1370
    v_new_fn   :=  v_tmp_fn_ptr.rec_idx + 1;
1371
    v_tmp_fn            :=  new file_def;
1372
    v_tmp_fn_ptr.next_rec  :=  v_tmp_fn;
1373
    v_tmp_fn.rec_idx    := v_new_fn;
1374
 
1375
    --  nul the text line
1376
    v_tmp_fn.file_name  := (others => nul);
1377
    for i in 1 to name'high loop
1378
      v_tmp_fn.file_name(i)  := name(i);
1379
    end loop;
1380
    v_tmp_fn.next_rec  :=  null;
1381
 
1382
 
1383
    v_inst_ptr :=  inst_set;
1384
    v_var_prt  :=  var_list;
1385
    v_sequ_ptr :=  inst_sequ;
1386
 
1387
    -- while not the end of file read it
1388
    while(not endfile(include_file)) loop
1389
      file_read_line(include_file,l);
1390
      --  tokenize the line
1391
      tokenize_line(l,t1,t2,t3,t4,t5,t6,t7,t_txt,valid);
1392
      v_len  := fld_len(t1);
1393
      if(t1(1 to v_len) = "INCLUDE") then
1394
        print("Nested INCLUDE statement found in " & v_tmp & " on line " &
1395
              (integer'image(l_num)));
1396
        assert(false)
1397
          report LF & "Error: Nested INCLUDE statements are not supported at this time."
1398
        severity failure;
1399
 
1400
      -- if there was valid tokens
1401
      elsif(valid /= 0) then
1402
        check_valid_inst(t1, v_inst_ptr, valid, l_num, name);
1403
        add_instruction(v_sequ_ptr,v_var_prt,t1,t2,t3,t4,t5,t6,t7,t_txt,valid,
1404
                        sequ_line,l_num,name,v_new_fn);
1405
      end if;
1406
      l_num  :=  l_num + 1;
1407
    end loop; -- end loop read file
1408
    file_close(include_file);
1409
    sequ_numb  :=  sequ_line;
1410
    inst_set   :=  v_inst_ptr;
1411
    var_list   :=  v_var_prt;
1412
    inst_sequ  :=  v_sequ_ptr;
1413
  end read_include_file;
1414
 
1415
--------------------------------------------------------------------------------
1416
--  The read instruction file procedure
1417
--    This is the main procedure for reading, parcing, checking and returning
1418
--    the instruction sequence Link list.
1419
  procedure read_instruction_file(constant file_name:  string;
1420
                                  variable inst_set:   inout inst_def_ptr;
1421
                                  variable var_list:   inout var_field_ptr;
1422
                                  variable inst_sequ:  inout stim_line_ptr;
1423
                                  variable file_list:  inout file_def_ptr) is
1424
    variable l:          text_line; -- the line
1425
    variable l_num:      integer;   -- line number file
1426
    variable sequ_line:  integer;   -- line number program
1427
    variable t1:         text_field;
1428
    variable t2:         text_field;
1429
    variable t3:         text_field;
1430
    variable t4:         text_field;
1431
    variable t5:         text_field;
1432
    variable t6:         text_field;
1433
    variable t7:         text_field;
1434
    variable t_txt:      stm_text_ptr;
1435
    variable valid:      integer;
1436
    variable v_ostat:    integer;
1437
    variable v_inst_ptr: inst_def_ptr;
1438
    variable v_var_prt:  var_field_ptr;
1439
    variable v_sequ_ptr: stim_line_ptr;
1440
    variable v_len:      integer;
1441
    variable v_stat:     file_open_status;
1442
    variable v_name:     text_line;
1443
    variable v_iname:    text_line;
1444
    variable v_tmp_fn:   file_def_ptr;
1445
    variable v_fn_idx:   integer;
1446
    variable v_idx:      integer;
1447
 
1448
  begin
1449
    -- open the stimulus_file and check
1450
    file_open(v_stat, stimulus, file_name, read_mode);
1451
    assert(v_stat = open_ok)
1452
      report LF & "Error: Unable to open stimulus_file  " & file_name
1453
    severity failure;
1454
    -- copy file name to type text_line
1455
    for i in 1 to file_name'high loop
1456
      v_name(i)  := file_name(i);
1457
    end loop;
1458
    -- the first item on the file names link list
1459
    file_list           :=  null;
1460
    v_tmp_fn            :=  new file_def;
1461
    v_tmp_fn.rec_idx    := 1;
1462
    v_fn_idx            := 1;
1463
    v_idx               := 1;
1464
    --  nul the text line
1465
    v_tmp_fn.file_name  := (others => nul);
1466
    for i in 1 to file_name'high loop
1467
      v_tmp_fn.file_name(i)  := file_name(i);
1468
    end loop;
1469
    v_tmp_fn.next_rec  :=  null;
1470
 
1471
    l_num      :=  1;
1472
    sequ_line  :=  1;
1473
    v_ostat    :=  0;
1474
 
1475
    v_inst_ptr :=  inst_set;
1476
    v_var_prt  :=  var_list;
1477
    v_sequ_ptr :=  inst_sequ;
1478
 
1479
    -- while not the end of file read it
1480
    while(not endfile(stimulus)) loop
1481
      file_read_line(stimulus,l);
1482
      --  tokenize the line
1483
      tokenize_line(l,t1,t2,t3,t4,t5,t6,t7,t_txt,valid);
1484
      v_len  := fld_len(t1);
1485
      -- if there is an INCLUDE instruction
1486
      if(t1(1 to v_len) = "INCLUDE") then
1487
        -- if file name is in par2
1488
        if(valid = 2) then
1489
          v_iname  := (others => nul);
1490
          for i in 1 to max_field_len loop
1491
            v_iname(i) := t2(i);
1492
          end loop;
1493
        -- elsif the text string is not null
1494
        elsif(t_txt /= null) then
1495
          v_iname  := (others => nul);
1496
          for i in 1 to c_stm_text_len loop
1497
            v_iname(i) := t_txt(i);
1498
            if(t_txt(i) = nul) then
1499
              exit;
1500
            end if;
1501
          end loop;
1502
        else
1503
          assert(false)
1504
            report LF & "Error:  INCLUDE instruction has not file name included.  Found on" & LF &
1505
                        "line " & (integer'image(l_num)) & " in file " & file_name & LF
1506
          severity failure;
1507
        end if;
1508
        print("INCLUDE found: Loading file " & v_iname);
1509
        read_include_file(v_iname,sequ_line,v_tmp_fn,v_inst_ptr,v_var_prt,v_sequ_ptr,v_ostat);
1510
        -- if include file not found
1511
        if(v_ostat = 1) then
1512
          exit;
1513
        end if;
1514
      -- if there was valid tokens
1515
      elsif(valid /= 0) then
1516
        check_valid_inst(t1, v_inst_ptr, valid, l_num, v_name);
1517
        add_instruction(v_sequ_ptr,v_var_prt,t1,t2,t3,t4,t5,t6,t7,t_txt,valid,
1518
                        sequ_line,l_num,v_name,v_fn_idx);
1519
      end if;
1520
      l_num  :=  l_num + 1;
1521
    end loop; -- end loop read file
1522
 
1523
    file_close(stimulus);  -- close the file when done
1524
 
1525
    assert(v_ostat = 0)
1526
      report LF & "Include file specified on line " & (integer'image(l_num)) &
1527
                  " in file " &  file_name &
1528
                  " was not found! Test Terminated" & LF
1529
    severity failure;
1530
 
1531
    inst_set   :=  v_inst_ptr;
1532
    var_list   :=  v_var_prt;
1533
    inst_sequ  :=  v_sequ_ptr;
1534
    file_list  :=  v_tmp_fn;
1535
 
1536
    --  Now that all the stimulus is loaded, test for invalid variables
1537
    test_inst_sequ(inst_sequ, v_tmp_fn, var_list);
1538
 
1539
  end read_instruction_file;
1540
 
1541
------------------------------------------------------------------------------
1542
-- access_inst_sequ
1543
--  This procedure accesses the instruction sequence and returns the parameters
1544
--  as they exsist related to the variables state.
1545
--  INPUTS:   inst_sequ  link list of instructions from stimulus
1546
--            var_list   link list of variables
1547
--            file_list  link list of file names
1548
--            sequ_num   the sequence number to recover
1549
--
1550
--  OUTPUTS:  inst  instruction text
1551
--            p1    paramiter 1 in integer form
1552
--            p2    paramiter 2 in integer form
1553
--            p3    paramiter 3 in integer form
1554
--            p4    paramiter 4 in integer form
1555
--            p5    paramiter 5 in integer form
1556
--            p6    paramiter 6 in integer form
1557
--            txt   pointer to any text string of this sequence
1558
--            inst_len  the lenth of inst in characters
1559
--            fname  file name this sequence came from
1560
--            file_line  the line number in fname this sequence came from
1561
--
1562
  procedure access_inst_sequ(variable inst_sequ  :  in  stim_line_ptr;
1563
                             variable var_list   :  in  var_field_ptr;
1564
                             variable file_list  :  in  file_def_ptr;
1565
                             variable sequ_num   :  in  integer;
1566
                             variable inst       :  out text_field;
1567
                             variable p1         :  out integer;
1568
                             variable p2         :  out integer;
1569
                             variable p3         :  out integer;
1570
                             variable p4         :  out integer;
1571
                             variable p5         :  out integer;
1572
                             variable p6         :  out integer;
1573
                             variable txt        :  out stm_text_ptr;
1574
                             variable inst_len   :  out integer;
1575
                             variable fname      :  out text_line;
1576
                             variable file_line  :  out integer;
1577
                             variable last_num   :  inout integer;
1578
                             variable last_ptr   :  inout stim_line_ptr
1579
                             ) is
1580
    variable temp_text_field:     text_field;
1581
    variable temp_var:            text_field;
1582
    variable inst_ptr:            stim_line_ptr;
1583
    variable valid:               integer;
1584
    variable line:                integer;  -- value of the file_line
1585
    variable file_name:           text_line;
1586
    variable tmp_int:             integer;
1587
    variable temp_fn_prt:         file_def_ptr;
1588
  begin
1589
   -- get to the instruction indicated by sequ_num
1590
   -- check to see if this sequence is before the last
1591
   --    so search from start
1592
    if(last_num  > sequ_num) then
1593
      inst_ptr  :=  inst_sequ;
1594
      while(inst_ptr.next_rec /= null) loop
1595
        if(inst_ptr.line_number = sequ_num) then
1596
          exit;
1597
        else
1598
          inst_ptr := inst_ptr.next_rec;
1599
        end if;
1600
      end loop;
1601
    -- else is equal or greater, so search forward
1602
    else
1603
      inst_ptr  :=  last_ptr;
1604
      while(inst_ptr.next_rec /= null) loop
1605
        if(inst_ptr.line_number = sequ_num) then
1606
          exit;
1607
        else
1608
          inst_ptr := inst_ptr.next_rec;
1609
        end if;
1610
      end loop;
1611
    end if;
1612
 
1613
    -- update the last sequence number and record pointer
1614
    last_num  :=  sequ_num;
1615
    last_ptr  :=  inst_ptr;
1616
 
1617
    -- output the instruction and its length
1618
    inst := inst_ptr.instruction;
1619
    inst_len := fld_len(inst_ptr.instruction);
1620
    file_line := inst_ptr.file_line;
1621
    line      := inst_ptr.file_line;
1622
    -- recover the file name this line came from
1623
    temp_fn_prt := file_list;
1624
    tmp_int   :=  inst_ptr.file_idx;
1625
    while (temp_fn_prt.next_rec /= null) loop
1626
      if(temp_fn_prt.rec_idx = tmp_int) then
1627
        exit;
1628
      end if;
1629
      temp_fn_prt  :=  temp_fn_prt.next_rec;
1630
    end loop;
1631
    for i in 1 to fname'high loop                       --<<<<<<<<<<<<<  Fix for file name output Apr 2011.
1632
      file_name(i) :=  temp_fn_prt.file_name(i);
1633
      fname(i)     :=  temp_fn_prt.file_name(i);
1634
      if(temp_fn_prt.file_name(i) = nul) then
1635
        exit;
1636
      end if;
1637
    end loop;
1638
 
1639
    txt       := inst_ptr.txt;
1640
    -- load parameter one
1641
    temp_text_field  :=  inst_ptr.inst_field_1;
1642
    if(temp_text_field(1) /= nul) then
1643
      -- if this is a numaric field convert to integer
1644
      if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1645
         temp_text_field(1) = 'b') then
1646
        p1 := stim_to_integer(temp_text_field,file_name,line);
1647
      elsif(is_digit(temp_text_field(1)) = true) then
1648
        p1 := stim_to_integer(temp_text_field,file_name,line);
1649
      else  -- else is a variable, get the value or halt incase of error
1650
        access_variable(var_list,temp_text_field,p1,valid);
1651
        assert(valid = 1)
1652
          report LF & "Error: First variable on stimulus line " & (integer'image(line))
1653
                    & " is not valid!!" & LF & "In file " & file_name
1654
        severity failure;
1655
      end if;
1656
    end if;
1657
    -- load parameter two
1658
    temp_text_field  :=  inst_ptr.inst_field_2;
1659
    if(temp_text_field(1) /= nul) then
1660
      -- if this is a numaric field convert to integer
1661
      if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1662
         temp_text_field(1) = 'b') then
1663
        p2 := stim_to_integer(temp_text_field,file_name,line);
1664
      elsif(is_digit(temp_text_field(1)) = true) then
1665
        p2 := stim_to_integer(temp_text_field,file_name,line);
1666
      else  -- else is a variable, get the value or halt incase of error
1667
        access_variable(var_list,temp_text_field,p2,valid);
1668
        assert(valid = 1)
1669
          report LF & "Error: Second variable on stimulus line " & (integer'image(line))
1670
                    & " is not valid!!" & LF & "In file " & file_name
1671
        severity failure;
1672
      end if;
1673
    end if;
1674
    -- load parameter three
1675
    temp_text_field  :=  inst_ptr.inst_field_3;
1676
    if(temp_text_field(1) /= nul) then
1677
      -- if this is a numaric field convert to integer
1678
      if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1679
         temp_text_field(1) = 'b') then
1680
        p3 := stim_to_integer(temp_text_field,file_name,line);
1681
      elsif(is_digit(temp_text_field(1)) = true) then
1682
        p3 := stim_to_integer(temp_text_field,file_name,line);
1683
      else  -- else is a variable, get the value or halt incase of error
1684
        access_variable(var_list,temp_text_field,p3,valid);
1685
        assert(valid = 1)
1686
          report LF & "Error: Third variable on stimulus line " & (integer'image(line))
1687
                    & " is not valid!!" & LF & "In file " & file_name
1688
        severity failure;
1689
      end if;
1690
    end if;
1691
    -- load parameter four
1692
    temp_text_field  :=  inst_ptr.inst_field_4;
1693
    if(temp_text_field(1) /= nul) then
1694
      -- if this is a numaric field convert to integer
1695
      if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1696
         temp_text_field(1) = 'b') then
1697
        p4 := stim_to_integer(temp_text_field,file_name,line);
1698
      elsif(is_digit(temp_text_field(1)) = true) then
1699
        p4 := stim_to_integer(temp_text_field,file_name,line);
1700
      else  -- else is a variable, get the value or halt incase of error
1701
        access_variable(var_list,temp_text_field,p4,valid);
1702
        assert(valid = 1)
1703
          report LF & "Error: Forth variable on stimulus line " & (integer'image(line))
1704
                    & " is not valid!!" & LF & "In file " & file_name
1705
        severity failure;
1706
      end if;
1707
    end if;
1708
    -- load parameter five
1709
    temp_text_field  :=  inst_ptr.inst_field_5;
1710
    if(temp_text_field(1) /= nul) then
1711
      -- if this is a numaric field convert to integer
1712
      if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1713
         temp_text_field(1) = 'b') then
1714
        p5 := stim_to_integer(temp_text_field,file_name,line);
1715
      elsif(is_digit(temp_text_field(1)) = true) then
1716
        p5 := stim_to_integer(temp_text_field,file_name,line);
1717
      else  -- else is a variable, get the value or halt incase of error
1718
        access_variable(var_list,temp_text_field,p5,valid);
1719
        assert(valid = 1)
1720
          report LF & "Error: Fifth variable on stimulus line " & (integer'image(line))
1721
                    & " is not valid!!" & LF & "In file " & file_name
1722
        severity failure;
1723
      end if;
1724
    end if;
1725
    -- load parameter six
1726
    temp_text_field  :=  inst_ptr.inst_field_6;
1727
    if(temp_text_field(1) /= nul) then
1728
      -- if this is a numaric field convert to integer
1729
      if(temp_text_field(1) = 'x' or temp_text_field(1) = 'h' or
1730
         temp_text_field(1) = 'b') then
1731
        p6 := stim_to_integer(temp_text_field,file_name,line);
1732
      elsif(is_digit(temp_text_field(1)) = true) then
1733
        p6 := stim_to_integer(temp_text_field,file_name,line);
1734
      else  -- else is a variable, get the value or halt incase of error
1735
        access_variable(var_list,temp_text_field,p6,valid);
1736
        assert(valid = 1)
1737
          report LF & "Error: Sixth variable on stimulus line " & (integer'image(line))
1738
                    & " is not valid!!" & LF & "In file " & file_name
1739
        severity failure;
1740
      end if;
1741
    end if;
1742
  end access_inst_sequ;
1743
 
1744
-------------------------------------------------------------------------------
1745
-- Procedure to print messages to stdout
1746
  procedure print(s: in string) is
1747
    variable l: line;
1748
  begin
1749
    write(l, s);
1750
    writeline(output,l);
1751
  end print;
1752
 
1753
-------------------------------------------------------------------------------
1754
--  procedure to print to the stdout the txt pointer
1755
  procedure txt_print(variable ptr: in stm_text_ptr) is
1756
    variable txt_str      : stm_text;
1757
  begin
1758
 
1759
    if (ptr /= null) then
1760
      txt_str := (others => nul);
1761
      for i in 1 to c_stm_text_len loop
1762
        if (ptr(i) = nul) then
1763
          exit;
1764
        end if;
1765
        txt_str(i) := ptr(i);
1766
      end loop;
1767
      print(txt_str);
1768
    end if;
1769
  end txt_print;
1770
 
1771
-------------------------------------------------------------------------------
1772
--  procedure to print to the stdout the txt pointer, and
1773
--     sub any variables found
1774
  procedure txt_print_wvar(variable var_list : in var_field_ptr;
1775
                           variable ptr      : in stm_text_ptr;
1776
                           constant b        : in base) is
1777
 
1778
    variable i:          integer;
1779
    variable j:          integer;
1780
    variable k:          integer;
1781
    variable txt_str:    stm_text;
1782
    variable tmp_str:    stm_text;
1783
    variable v1:         integer;
1784
    variable valid:      integer;
1785
    variable tmp_field:  text_field;
1786
    variable tmp_i:      integer;
1787
 
1788
  begin
1789
    if(ptr /= null) then
1790
      i := 1;
1791
      j := 1;
1792
      txt_str := (others => nul);
1793
      while(i <= c_stm_text_len and j <= c_stm_text_len) loop
1794
        if(ptr(i) /= '$') then
1795
          txt_str(j) := ptr(i);
1796
          i := i + 1;
1797
          j := j + 1;
1798
        else
1799
          tmp_field := (others => nul);
1800
          tmp_i := 1;
1801
          tmp_field(tmp_i) := ptr(i);
1802
          i := i + 1;
1803
          tmp_i := tmp_i + 1;
1804
          -- parse to the next space
1805
          while(ptr(i) /= ' ' and ptr(i) /= nul) loop
1806
            tmp_field(tmp_i) := ptr(i);
1807
            i := i + 1;
1808
            tmp_i := tmp_i + 1;
1809
          end loop;
1810
          access_variable(var_list,tmp_field,v1,valid);
1811
          assert(valid = 1)
1812
            report LF & "Invalid Variable found in stm_text_ptr: ignoring."
1813
          severity warning;
1814
 
1815
          if(valid = 1) then
1816
 
1817
            txt_str :=  ew_str_cat(txt_str, ew_to_str(v1, b));
1818
            k := 1;
1819
            while(txt_str(k) /= nul) loop
1820
              k := k + 1;
1821
            end loop;
1822
            j := k;
1823
          end if;
1824
        end if;
1825
      end loop;
1826
      -- print the created string
1827
      print(txt_str);
1828
    end if;
1829
  end txt_print_wvar;
1830
 
1831
end tb_pkg;
1832
 
1833
-------------------------------------------------------------------------------
1834
--  Revision  1.3
1835
-- Revision History:
1836
-- $Log: not supported by cvs2svn $
1837
-- Revision 1.2  2007/09/02 04:04:04  sckoarn
1838
-- Update of version 1.2 tb_pkg
1839
-- See documentation for details
1840
--
1841
-- Revision 1.1.1.1  2007/04/06 04:06:48  sckoarn
1842
-- Import of the vhld_tb
1843
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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