aboutsummaryrefslogtreecommitdiffstats
path: root/src/vhdl/simulate/simul-environments.ads
blob: 845c4fafc95c9075856f4df7901729df45618413 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
--  Naive values for interpreted simulation
--  Copyright (C) 2014 Tristan Gingold
--
--  GHDL is free software; you can redistribute it and/or modify it under
--  the terms of the GNU General Public License as published by the Free
--  Software Foundation; either version 2, or (at your option) any later
--  version.
--
--  GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
--  WARRANTY; without even the implied warranty of MERCHANTABILITY or
--  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
--  for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with GHDL; see the file COPYING.  If not, write to the Free
--  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
--  02111-1307, USA.

with Ada.Unchecked_Deallocation;
with Types; use Types;
with Iirs; use Iirs;
with Grt.Types; use Grt.Types;
with Grt.Signals; use Grt.Signals;
with Grt.Files;
with Areapools; use Areapools;
-- with System.Debug_Pools;

package Simul.Environments is
   -- During simulation, all values are contained into objects of type
   -- iir_value_literal.  The annotation pass creates such objects for every
   -- literal of units.  The elaboration pass creates such objects for
   -- signals, variables, contants...
   -- The simulator uses iir_value_literal for intermediate results, for
   -- computed values...

   -- There is several kinds of iir_value_literal, mainly depending on the
   -- type of the value:
   --
   -- iir_value_e32:
   --  the value is an enumeration literal.  The enum field contains the
   --  position of the literal (same as 'pos).
   --
   -- iir_value_i64:
   --  the value is an integer.
   --
   -- iir_value_f64:
   --  the value is a floating point.
   --
   -- iir_value_range:
   --  Boundaries and direction.
   --
   -- iir_value_array:
   --  All the values are contained in the array Val_Array.
   --  Boundaries of the array are contained in the array BOUNDS, one element
   --  per dimension, from 1 to number of dimensions.
   --
   -- iir_value_signal:
   --  Special case: the iir_value_literal designates a signal.
   --
   -- iir_value_record
   --  For records.
   --
   -- iir_value_access
   --  for accesses.
   --
   -- iir_value_file
   --  for files.

   --  Memory management:
   --  The values are always allocated on areapool, which uses a mark/release
   --  management. A release operation frees all the memory of the areapool
   --  allocated since the mark. This memory management is very efficient.
   --
   --  There is one areapool per processes; there is one mark per instances.
   --  Objects (variables, signals, constants, iterators, ...) are allocated
   --  on the per-process pool.  When an activation frame is created (due
   --  to a call to a subprogram), a mark is saved. When the activation frame
   --  is removed (due to a return from subprogram), the memory is released to
   --  the mark. That's simple.
   --
   --  Objects for the process is allocated in that areapool, but never
   --  released (could be if the process is waiting forever if the user don't
   --  need to inspect values).
   --
   --  Signals and constants for blocks/entity/architecture are allocated on
   --  a global pool.
   --
   --  In fact this is not so simple because of functions: they return a
   --  value.  The current solution is to compute every expressions on a
   --  expression pool (only one is needed as the computation cannot be
   --  suspended), use the result (copy in case of assignment or return), and
   --  release that pool.
   --
   --  It is highly recommended to share values as much as possible for
   --  expressions (for example, alias the values of 'others =>'). Do not
   --  share values for names, but be sure to keep the original nodes.
   --  ??? In fact sharing is required to pass actual by references.
   --  When an object is created, be sure to unshare the values.  This is
   --  usually achieved by Copy.
   --
   --  Finally, a pool is also needed during elaboration (as elaboration is
   --  not done within the context of a process).

   type Iir_Value_Kind is
     (Iir_Value_B1, Iir_Value_E8, Iir_Value_E32,
      Iir_Value_I64, Iir_Value_F64,
      Iir_Value_Access,
      Iir_Value_File,
      Iir_Value_Range,
      Iir_Value_Array, Iir_Value_Record,
      Iir_Value_Protected,
      Iir_Value_Signal,
      Iir_Value_Terminal,
      Iir_Value_Quantity,
      Iir_Value_Instance);

   --  Uniq identifier for scalar signal.  First identifier is 'First + 1.
   type Signal_Index_Type is new Natural;
   function Get_Last_Signal_Index return Signal_Index_Type;

   type Protected_Index_Type is new Natural;
   type Quantity_Index_Type is new Natural;
   type Terminal_Index_Type is new Natural;

   --  Scalar values.  Only these ones can be signals.
   subtype Iir_Value_Scalars is
     Iir_Value_Kind range Iir_Value_B1 .. Iir_Value_F64;

   subtype Iir_Value_Discrete is
     Iir_Value_Kind range Iir_Value_B1 .. Iir_Value_I64;

   subtype Iir_Value_Enums is
     Iir_Value_Kind range Iir_Value_B1 .. Iir_Value_E32;

   --  Abstrace numeric types.
   subtype Iir_Value_Numerics is
     Iir_Value_Kind range Iir_Value_I64 .. Iir_Value_F64;

   subtype Iir_Value_Physicals is
     Iir_Value_Kind range Iir_Value_I64 .. Iir_Value_I64;

   type Iir_Value_Literal (Kind: Iir_Value_Kind);

   type Iir_Value_Literal_Acc is access Iir_Value_Literal;

   -- Must start at 0.
   -- Thus, length of the array is val_array'last - 1.
   type Iir_Value_Literal_Array is array (Iir_Index32 range <>) of
     Iir_Value_Literal_Acc;

   type Iir_Value_Literal_Array_Acc is access Iir_Value_Literal_Array;

   type Value_Bounds_Array (Nbr_Dims : Iir_Index32) is record
      D : Iir_Value_Literal_Array (1 .. Nbr_Dims);
   end record;

   type Value_Bounds_Array_Acc is access Value_Bounds_Array;

   type Value_Array (Len : Iir_Index32) is record
      V : Iir_Value_Literal_Array (1 .. Len);
   end record;

   type Value_Array_Acc is access Value_Array;

   -- A block instance with its architecture/entity declaration is an
   -- instancied entity.
   type Block_Instance_Type;
   type Block_Instance_Acc is access Block_Instance_Type;

   type Iir_Value_Literal (Kind: Iir_Value_Kind) is record
      case Kind is
         when Iir_Value_B1 =>
            B1 : Ghdl_B1;
         when Iir_Value_E8 =>
            E8 : Ghdl_E8;
         when Iir_Value_E32 =>
            E32 : Ghdl_E32;
         when Iir_Value_I64 =>
            I64 : Ghdl_I64;
         when Iir_Value_F64 =>
            F64 : Ghdl_F64;
         when Iir_Value_Access =>
            Val_Access: Iir_Value_Literal_Acc;
         when Iir_Value_File =>
            File: Grt.Files.Ghdl_File_Index;
         when Iir_Value_Array =>
            Val_Array: Value_Array_Acc; --  range 1 .. N
            Bounds : Value_Bounds_Array_Acc;   --  range 1 .. Dim
         when Iir_Value_Record =>
            Val_Record: Value_Array_Acc; -- range 1 .. N
         when Iir_Value_Signal =>
            Sig : Ghdl_Signal_Ptr;
            --  Each signal has a uniq identifier.
            Sig_Id : Signal_Index_Type;
         when Iir_Value_Protected =>
            Prot : Protected_Index_Type;
         when Iir_Value_Quantity =>
            Quantity : Quantity_Index_Type;
         when Iir_Value_Terminal =>
            Terminal : Terminal_Index_Type;
         when Iir_Value_Instance =>
            Instance : Block_Instance_Acc;
         when Iir_Value_Range =>
            Dir: Iir_Direction;
            Length : Iir_Index32;
            Left: Iir_Value_Literal_Acc;
            Right: Iir_Value_Literal_Acc;
      end case;
   end record;

   type Object_Slot_Type is new Natural;

   --  This slot is not used.
   Invalid_Object_Slot : constant Object_Slot_Type := 0;

   subtype Parameter_Slot_Type is Object_Slot_Type range 0 .. 2**15;

   type Pkg_Index_Type is new Natural;

   type Block_Instance_Id is new Natural;
   No_Block_Instance_Id : constant Block_Instance_Id := 0;

   type Objects_Array is array (Object_Slot_Type range <>) of
     Iir_Value_Literal_Acc;

   --  For Kind_Extra: a number.  Kind_Extra is not used by annotations, and
   --  is free for another pass like preelab.
   type Extra_Slot_Type is new Natural;

   -- The annotation depends on the kind of the node.
   type Sim_Info_Kind is
     (Kind_Block, Kind_Process, Kind_Frame, Kind_Protected, Kind_Package,
      Kind_Scalar_Type, Kind_File_Type,
      Kind_Object, Kind_Signal,
      Kind_File,
      Kind_Terminal, Kind_Quantity,
      Kind_PSL,
      Kind_Extra);

   type Instance_Slot_Type is new Integer;
   Invalid_Instance_Slot : constant Instance_Slot_Type := -1;

   type Sim_Info_Type (Kind : Sim_Info_Kind);
   type Sim_Info_Acc is access all Sim_Info_Type;

   -- Annotation for an iir node in order to be able to simulate it.
   type Sim_Info_Type (Kind: Sim_Info_Kind) is record
      --  Redundant, to be used only for debugging.
      Ref : Iir;

      case Kind is
         when Kind_Block
           | Kind_Frame
           | Kind_Protected
           | Kind_Process
           | Kind_Package =>
            --  Number of objects/signals.
            Nbr_Objects : Object_Slot_Type;

            case Kind is
               when Kind_Block =>
                  --  Slot number in the parent (for blocks).
                  Inst_Slot : Instance_Slot_Type;

                  --  Number of children (blocks, generate, instantiation).
                  Nbr_Instances : Instance_Slot_Type;

               when Kind_Package =>
                  Pkg_Slot : Object_Slot_Type;
                  Pkg_Parent : Sim_Info_Acc;

               when others =>
                  null;
            end case;

         when Kind_Object
           | Kind_Signal
           | Kind_File
           | Kind_Terminal
           | Kind_Quantity
           | Kind_PSL =>
            --  Block in which this object is declared in.
            Obj_Scope : Sim_Info_Acc;

            --  Variable index in the block.
            Slot: Object_Slot_Type;

         when Kind_Scalar_Type =>
            Scalar_Mode : Iir_Value_Kind;

         when Kind_File_Type =>
            File_Signature : String_Acc;

         when Kind_Extra =>
            Extra_Slot : Extra_Slot_Type;
      end case;
   end record;

   type Block_Instance_Type (Max_Objs : Object_Slot_Type) is record
      --  Flag for wait statement: true if not yet executed.
      In_Wait_Flag : Boolean;

      --  Uniq number for a block instance.
      Id : Block_Instance_Id;

      -- Useful informations for a dynamic block (ie, a frame).
      -- The scope level and an access to the block of upper scope level.
      Block_Scope : Sim_Info_Acc;
      Uninst_Scope : Sim_Info_Acc;
      Up_Block : Block_Instance_Acc;

      --  Block, architecture, package, process, component instantiation for
      --  this instance.
      Label : Iir;

      --  For subprograms: the body.
      Bod : Iir;

      --  For blocks: corresponding block (different from label for direct
      --  component instantiation statement and generate iterator).
      --  For packages: Null_Iir
      --  For subprograms and processes: statement being executed.
      Stmt : Iir;

      --  Instanciation tree.

      --  Parent is always set (but null for top-level block and packages)
      Parent: Block_Instance_Acc;

      --  Chain of children.  They are in declaration order after elaboration.
      --  (in reverse order during elaboration).
      --  Not null only for blocks and processes.
      Children: Block_Instance_Acc;
      Brother: Block_Instance_Acc;

      --  Pool marker for the child (only for subprograms and processes).
      Marker : Areapools.Mark_Type;

      --  Reference to the actuals, for copy-out when returning from a
      --  procedure.
      Actuals_Ref : Value_Array_Acc;

      -- Only for function frame; contains the result.
      Result: Iir_Value_Literal_Acc;

      --  Last object elaborated (or number of objects elaborated).
      --  Note: this is generally the slot index of the next object to be
      --  elaborated (this may be wrong for dynamic objects due to execution
      --  branches).
      Elab_Objects : Object_Slot_Type := 0;

      --  Values of the objects in that frame.
      Objects : Objects_Array (1 .. Max_Objs);
   end record;

   procedure Free is new Ada.Unchecked_Deallocation
     (Object => Block_Instance_Type, Name => Block_Instance_Acc);


   -- What is chosen for time.
   subtype Iir_Value_Time is Ghdl_I64;

   Global_Pool : aliased Areapool;
   Expr_Pool : aliased Areapool;

   --  Areapool used by Create_*_Value
   Current_Pool : Areapool_Acc := Expr_Pool'Access;

   --  Pool for objects allocated in the current instance.
   Instance_Pool : Areapool_Acc;

   function Create_Signal_Value (Sig : Ghdl_Signal_Ptr)
                                return Iir_Value_Literal_Acc;
   function Create_Terminal_Value (Terminal : Terminal_Index_Type)
                                  return Iir_Value_Literal_Acc;
   function Create_Quantity_Value (Quantity : Quantity_Index_Type)
                                  return Iir_Value_Literal_Acc;
   function Create_Instance_Value (Inst : Block_Instance_Acc)
                                  return Iir_Value_Literal_Acc;

   function Create_B1_Value (Val : Ghdl_B1) return Iir_Value_Literal_Acc;
   function Create_E8_Value (Val : Ghdl_E8) return Iir_Value_Literal_Acc;
   function Create_E32_Value (Val : Ghdl_E32) return Iir_Value_Literal_Acc;

   -- Return an iir_value_literal_acc (iir_value_int64).
   function Create_I64_Value (Val : Ghdl_I64) return Iir_Value_Literal_Acc;

   --  Return an iir_value_literal_acc (iir_value_fp64)
   function Create_F64_Value (Val : Ghdl_F64) return Iir_Value_Literal_Acc;

   function Create_Access_Value (Val : Iir_Value_Literal_Acc)
                                return Iir_Value_Literal_Acc;

   function Create_File_Value (Val : Grt.Files.Ghdl_File_Index)
                              return Iir_Value_Literal_Acc;

   function Create_Protected_Value (Prot : Protected_Index_Type)
                                   return Iir_Value_Literal_Acc;

   -- Return an iir_value_literal (iir_value_record) of NBR elements.
   function Create_Record_Value
     (Nbr : Iir_Index32; Pool : Areapool_Acc := Current_Pool)
     return Iir_Value_Literal_Acc;

   --  Allocate array and the dimension vector (but bounds and values aren't
   --  allocated).
   function Create_Array_Value (Dim : Iir_Index32;
                                Pool : Areapool_Acc := Current_Pool)
                               return Iir_Value_Literal_Acc;

   --  Allocate the Val_Array vector.
   procedure Create_Array_Data (Arr : Iir_Value_Literal_Acc;
                                Len : Iir_Index32;
                                Pool : Areapool_Acc := Current_Pool);

   -- Return an array of length LENGTH and DIM bounds.
   -- If DIM is 0, then the bounds array is not allocated.
   function Create_Array_Value (Length: Iir_Index32;
                                Dim : Iir_Index32;
                                Pool : Areapool_Acc := Current_Pool)
                               return Iir_Value_Literal_Acc;

   --  Create a range_value of life LIFE.
   function Create_Range_Value
     (Left, Right : Iir_Value_Literal_Acc;
      Dir : Iir_Direction;
      Length : Iir_Index32)
     return Iir_Value_Literal_Acc;

   --  Create a range_value (compute the length)
   function Create_Range_Value
     (Left, Right : Iir_Value_Literal_Acc;
      Dir : Iir_Direction)
      return Iir_Value_Literal_Acc;

   -- Return true if the value of LEFT and RIGHT are equal.
   -- Return false if they are not equal.
   -- Raise constraint_error if the types differes.
   -- Value or sub-value must not be indirect.
   function Is_Equal (Left, Right: Iir_Value_Literal_Acc) return Boolean;

   --  Return TRUE iif ARANGE is a null range.
   function Is_Null_Range (Arange : Iir_Value_Literal_Acc) return Boolean;

   -- Get order of LEFT with RIGHT.
   -- Must be discrete kind (enum, int, fp, physical) or array (uni dim).
   type Order is (Less, Equal, Greater);
   function Compare_Value (Left, Right : Iir_Value_Literal_Acc)
                           return Order;

   --  Check that SRC has the same structure as DEST.  Report an error at
   --  LOC if not.
   procedure Check_Bounds (Dest : Iir_Value_Literal_Acc;
                           Src : Iir_Value_Literal_Acc;
                           Loc : Iir);

   -- Store (by copy) SRC into DEST.
   -- The type must be equal (otherwise  constraint_error is raised).
   -- Life of DEST must be Target, otherwise program_error is raised.
   -- Value or sub-value must not be indirect.
   procedure Store (Dest : Iir_Value_Literal_Acc; Src : Iir_Value_Literal_Acc);

   --  Create a copy of SRC allocated in POOL.
   function Unshare (Src : Iir_Value_Literal_Acc; Pool : Areapool_Acc)
                    return Iir_Value_Literal_Acc;

   --  If SRC is an array, just copy the bounds in POOL and return it.
   --  Otherwise return SRC.  Values are always kept, so that this could
   --  be used by alias declarations.
   function Unshare_Bounds (Src : Iir_Value_Literal_Acc; Pool : Areapool_Acc)
                           return Iir_Value_Literal_Acc;

   --  Create a copy of SRC on the heap.
   function Unshare_Heap (Src : Iir_Value_Literal_Acc)
                         return Iir_Value_Literal_Acc;

   --  Deallocate value accessed by ACC.
   procedure Free_Heap_Value (Acc : Iir_Value_Literal_Acc);

   --  Increment.
   --  VAL must be of kind integer or enumeration.
   --  VAL must be of life temporary.
   procedure Increment (Val : Iir_Value_Literal_Acc);

   --  Copy BOUNDS of SRC with a specified life.
   --  Note: val_array is allocated but not filled.
   function Copy_Array_Bound (Src : Iir_Value_Literal_Acc)
                             return Iir_Value_Literal_Acc;

   --  Copy the bounds (well the array containing the values) of SRC.
   --  Val_record is allocated but not filled.
   function Copy_Record (Src : Iir_Value_Literal_Acc)
                        return Iir_Value_Literal_Acc;

   --  Return the number of scalars elements in VALS.
   function Get_Nbr_Of_Scalars (Val : Iir_Value_Literal_Acc) return Natural;

   --  Return the position of an enumerated type value.
   function Get_Enum_Pos (Val : Iir_Value_Literal_Acc) return Natural;

   -- Well known values.
   -- Boolean_to_lit can be used to convert a boolean value from Ada to a
   -- boolean value for vhdl.
   type Lit_Enum_Type is array (Boolean) of Iir_Value_Literal_Acc;
   Lit_Enum_0 : constant Iir_Value_Literal_Acc :=
     new Iir_Value_Literal'(Kind => Iir_Value_B1,
                            B1 => False);
   Lit_Enum_1 : constant Iir_Value_Literal_Acc :=
     new Iir_Value_Literal'(Kind => Iir_Value_B1,
                            B1 => True);
   Boolean_To_Lit: constant Lit_Enum_Type :=
     (False => Lit_Enum_0, True => Lit_Enum_1);
   Lit_Boolean_False: Iir_Value_Literal_Acc
     renames Boolean_To_Lit (False);
   Lit_Boolean_True: Iir_Value_Literal_Acc
     renames Boolean_To_Lit (True);

   -- Literal NULL.
   Null_Lit: constant Iir_Value_Literal_Acc :=
     new Iir_Value_Literal'(Kind => Iir_Value_Access,
                            Val_Access => null);

   -- Disp a value_literal in raw form.
   procedure Disp_Value (Value: Iir_Value_Literal_Acc);
   procedure Disp_Value_Tab (Value: Iir_Value_Literal_Acc;
                             Indent : Natural);

   -- Disp literal of an enumerated type.
   procedure Disp_Iir_Value_Enum (Pos : Natural; A_Type : Iir);

   -- Disp a value_literal in readable form.
   procedure Disp_Iir_Value (Value: Iir_Value_Literal_Acc; A_Type: Iir);
end Simul.Environments;