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 23

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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