aboutsummaryrefslogtreecommitdiffstats
path: root/src/simulate/execution.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/simulate/execution.adb')
-rw-r--r--src/simulate/execution.adb4837
1 files changed, 4837 insertions, 0 deletions
diff --git a/src/simulate/execution.adb b/src/simulate/execution.adb
new file mode 100644
index 000000000..ef4cccc46
--- /dev/null
+++ b/src/simulate/execution.adb
@@ -0,0 +1,4837 @@
+-- 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_Conversion;
+with Ada.Text_IO; use Ada.Text_IO;
+with System;
+with Grt.Types; use Grt.Types;
+with Errorout; use Errorout;
+with Std_Package;
+with Evaluation;
+with Iirs_Utils; use Iirs_Utils;
+with Annotations; use Annotations;
+with Name_Table;
+with File_Operation;
+with Debugger; use Debugger;
+with Std_Names;
+with Str_Table;
+with Files_Map;
+with Iir_Chains; use Iir_Chains;
+with Simulation; use Simulation;
+with Grt.Astdio;
+with Grt.Stdio;
+with Grt.Options;
+with Grt.Vstrings;
+with Grt_Interface;
+with Grt.Values;
+with Grt.Errors;
+with Grt.Std_Logic_1164;
+
+package body Execution is
+
+ function Execute_Function_Call
+ (Block: Block_Instance_Acc; Expr: Iir; Imp : Iir)
+ return Iir_Value_Literal_Acc;
+
+ procedure Finish_Sequential_Statements
+ (Proc : Process_State_Acc; Complex_Stmt : Iir);
+ procedure Init_Sequential_Statements
+ (Proc : Process_State_Acc; Complex_Stmt : Iir);
+ procedure Update_Next_Statement (Proc : Process_State_Acc);
+
+ -- Display a message when an assertion has failed.
+ procedure Execute_Failed_Assertion (Report : String;
+ Severity : Natural;
+ Stmt: Iir);
+
+ function Get_Instance_By_Scope_Level
+ (Instance: Block_Instance_Acc; Scope_Level: Scope_Level_Type)
+ return Block_Instance_Acc
+ is
+ Current: Block_Instance_Acc := Instance;
+ begin
+ while Current /= null loop
+ if Current.Scope_Level = Scope_Level then
+ return Current;
+ end if;
+ Current := Current.Up_Block;
+ end loop;
+ -- Global scope (packages)
+ if Scope_Level < Scope_Level_Global then
+ return Package_Instances (Instance_Slot_Type (-Scope_Level));
+ end if;
+ if Current_Component /= null
+ and then Current_Component.Scope_Level = Scope_Level
+ then
+ return Current_Component;
+ end if;
+ if Scope_Level = Scope_Level_Global then
+ return null;
+ end if;
+ raise Internal_Error;
+ end Get_Instance_By_Scope_Level;
+
+ function Get_Instance_For_Slot (Instance: Block_Instance_Acc; Decl: Iir)
+ return Block_Instance_Acc
+ is
+ begin
+ return Get_Instance_By_Scope_Level (Instance,
+ Get_Info (Decl).Scope_Level);
+ end Get_Instance_For_Slot;
+
+ function Create_Bounds_From_Length (Block : Block_Instance_Acc;
+ Atype : Iir;
+ Len : Iir_Index32)
+ return Iir_Value_Literal_Acc
+ is
+ Res : Iir_Value_Literal_Acc;
+ Index_Bounds : Iir_Value_Literal_Acc;
+ begin
+ Index_Bounds := Execute_Bounds (Block, Atype);
+
+ Res := Create_Range_Value (Left => Index_Bounds.Left,
+ Right => null,
+ Dir => Index_Bounds.Dir,
+ Length => Len);
+
+ if Len = 0 then
+ -- Special case.
+ Res.Right := Res.Left;
+ case Res.Left.Kind is
+ when Iir_Value_I64 =>
+ case Index_Bounds.Dir is
+ when Iir_To =>
+ Res.Left := Create_I64_Value (Res.Right.I64 + 1);
+ when Iir_Downto =>
+ Res.Left := Create_I64_Value (Res.Right.I64 - 1);
+ end case;
+ when others =>
+ raise Internal_Error;
+ end case;
+ else
+ case Res.Left.Kind is
+ when Iir_Value_E32 =>
+ declare
+ R : Ghdl_E32;
+ begin
+ case Index_Bounds.Dir is
+ when Iir_To =>
+ R := Res.Left.E32 + Ghdl_E32 (Len - 1);
+ when Iir_Downto =>
+ R := Res.Left.E32 - Ghdl_E32 (Len - 1);
+ end case;
+ Res.Right := Create_E32_Value (R);
+ end;
+ when Iir_Value_I64 =>
+ declare
+ R : Ghdl_I64;
+ begin
+ case Index_Bounds.Dir is
+ when Iir_To =>
+ R := Res.Left.I64 + Ghdl_I64 (Len - 1);
+ when Iir_Downto =>
+ R := Res.Left.I64 - Ghdl_I64 (Len - 1);
+ end case;
+ Res.Right := Create_I64_Value (R);
+ end;
+ when others =>
+ raise Internal_Error;
+ end case;
+ end if;
+ return Res;
+ end Create_Bounds_From_Length;
+
+ function Execute_High_Limit (Bounds : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc is
+ begin
+ if Bounds.Dir = Iir_To then
+ return Bounds.Right;
+ else
+ return Bounds.Left;
+ end if;
+ end Execute_High_Limit;
+
+ function Execute_Low_Limit (Bounds : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc is
+ begin
+ if Bounds.Dir = Iir_To then
+ return Bounds.Left;
+ else
+ return Bounds.Right;
+ end if;
+ end Execute_Low_Limit;
+
+ function Execute_Left_Limit (Bounds : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc is
+ begin
+ return Bounds.Left;
+ end Execute_Left_Limit;
+
+ function Execute_Right_Limit (Bounds : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc is
+ begin
+ return Bounds.Right;
+ end Execute_Right_Limit;
+
+ function Execute_Length (Bounds : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc is
+ begin
+ return Create_I64_Value (Ghdl_I64 (Bounds.Length));
+ end Execute_Length;
+
+ function Create_Enum_Value (Pos : Natural; Etype : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Base_Type : constant Iir := Get_Base_Type (Etype);
+ Mode : constant Iir_Value_Kind :=
+ Get_Info (Base_Type).Scalar_Mode;
+ begin
+ case Mode is
+ when Iir_Value_E32 =>
+ return Create_E32_Value (Ghdl_E32 (Pos));
+ when Iir_Value_B1 =>
+ return Create_B1_Value (Ghdl_B1'Val (Pos));
+ when others =>
+ raise Internal_Error;
+ end case;
+ end Create_Enum_Value;
+
+ function String_To_Iir_Value (Str : String) return Iir_Value_Literal_Acc
+ is
+ Res : Iir_Value_Literal_Acc;
+ begin
+ Res := Create_Array_Value (Str'Length, 1);
+ Res.Bounds.D (1) := Create_Range_Value
+ (Create_I64_Value (1),
+ Create_I64_Value (Str'Length),
+ Iir_To);
+ for I in Str'Range loop
+ Res.Val_Array.V (1 + Iir_Index32 (I - Str'First)) :=
+ Create_E32_Value (Character'Pos (Str (I)));
+ end loop;
+ return Res;
+ end String_To_Iir_Value;
+
+ function Execute_Image_Attribute (Val : Iir_Value_Literal_Acc;
+ Expr_Type : Iir)
+ return String
+ is
+ begin
+ case Get_Kind (Expr_Type) is
+ when Iir_Kind_Floating_Type_Definition
+ | Iir_Kind_Floating_Subtype_Definition =>
+ declare
+ Str : String (1 .. 24);
+ Last : Natural;
+ begin
+ Grt.Vstrings.To_String (Str, Last, Val.F64);
+ return Str (Str'First .. Last);
+ end;
+ when Iir_Kind_Integer_Type_Definition
+ | Iir_Kind_Integer_Subtype_Definition =>
+ declare
+ Str : String (1 .. 21);
+ First : Natural;
+ begin
+ Grt.Vstrings.To_String (Str, First, Val.I64);
+ return Str (First .. Str'Last);
+ end;
+ when Iir_Kind_Enumeration_Type_Definition
+ | Iir_Kind_Enumeration_Subtype_Definition =>
+ declare
+ Lits : constant Iir_List :=
+ Get_Enumeration_Literal_List (Expr_Type);
+ Pos : Natural;
+ begin
+ case Val.Kind is
+ when Iir_Value_B1 =>
+ Pos := Ghdl_B1'Pos (Val.B1);
+ when Iir_Value_E32 =>
+ Pos := Ghdl_E32'Pos (Val.E32);
+ when others =>
+ raise Internal_Error;
+ end case;
+ return Name_Table.Image
+ (Get_Identifier (Get_Nth_Element (Lits, Pos)));
+ end;
+ when Iir_Kind_Physical_Type_Definition
+ | Iir_Kind_Physical_Subtype_Definition =>
+ declare
+ Str : String (1 .. 21);
+ First : Natural;
+ Id : constant Name_Id :=
+ Get_Identifier (Get_Primary_Unit (Get_Base_Type (Expr_Type)));
+ begin
+ Grt.Vstrings.To_String (Str, First, Val.I64);
+ return Str (First .. Str'Last) & ' ' & Name_Table.Image (Id);
+ end;
+ when others =>
+ Error_Kind ("execute_image_attribute", Expr_Type);
+ end case;
+ end Execute_Image_Attribute;
+
+ function Execute_Shift_Operator (Left : Iir_Value_Literal_Acc;
+ Count : Ghdl_I64;
+ Expr : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Func : constant Iir_Predefined_Shift_Functions :=
+ Get_Implicit_Definition (Get_Implementation (Expr));
+ Cnt : Iir_Index32;
+ Len : constant Iir_Index32 := Left.Bounds.D (1).Length;
+ Dir_Left : Boolean;
+ P : Iir_Index32;
+ Res : Iir_Value_Literal_Acc;
+ E : Iir_Value_Literal_Acc;
+ begin
+ -- LRM93 7.2.3
+ -- That is, if R is 0 or if L is a null array, the return value is L.
+ if Count = 0 or else Len = 0 then
+ return Left;
+ end if;
+
+ case Func is
+ when Iir_Predefined_Array_Sll
+ | Iir_Predefined_Array_Sla
+ | Iir_Predefined_Array_Rol =>
+ Dir_Left := True;
+ when Iir_Predefined_Array_Srl
+ | Iir_Predefined_Array_Sra
+ | Iir_Predefined_Array_Ror =>
+ Dir_Left := False;
+ end case;
+ if Count < 0 then
+ Cnt := Iir_Index32 (-Count);
+ Dir_Left := not Dir_Left;
+ else
+ Cnt := Iir_Index32 (Count);
+ end if;
+
+ case Func is
+ when Iir_Predefined_Array_Sll
+ | Iir_Predefined_Array_Srl =>
+ E := Create_Enum_Value
+ (0, Get_Element_Subtype (Get_Base_Type (Get_Type (Expr))));
+ when Iir_Predefined_Array_Sla
+ | Iir_Predefined_Array_Sra =>
+ if Dir_Left then
+ E := Left.Val_Array.V (Len);
+ else
+ E := Left.Val_Array.V (1);
+ end if;
+ when Iir_Predefined_Array_Rol
+ | Iir_Predefined_Array_Ror =>
+ Cnt := Cnt mod Len;
+ if not Dir_Left then
+ Cnt := (Len - Cnt) mod Len;
+ end if;
+ end case;
+
+ Res := Create_Array_Value (1);
+ Res.Bounds.D (1) := Left.Bounds.D (1);
+ Create_Array_Data (Res, Len);
+ P := 1;
+
+ case Func is
+ when Iir_Predefined_Array_Sll
+ | Iir_Predefined_Array_Srl
+ | Iir_Predefined_Array_Sla
+ | Iir_Predefined_Array_Sra =>
+ if Dir_Left then
+ if Cnt < Len then
+ for I in Cnt .. Len - 1 loop
+ Res.Val_Array.V (P) := Left.Val_Array.V (I + 1);
+ P := P + 1;
+ end loop;
+ else
+ Cnt := Len;
+ end if;
+ for I in 0 .. Cnt - 1 loop
+ Res.Val_Array.V (P) := E;
+ P := P + 1;
+ end loop;
+ else
+ if Cnt > Len then
+ Cnt := Len;
+ end if;
+ for I in 0 .. Cnt - 1 loop
+ Res.Val_Array.V (P) := E;
+ P := P + 1;
+ end loop;
+ for I in Cnt .. Len - 1 loop
+ Res.Val_Array.V (P) := Left.Val_Array.V (I - Cnt + 1);
+ P := P + 1;
+ end loop;
+ end if;
+ when Iir_Predefined_Array_Rol
+ | Iir_Predefined_Array_Ror =>
+ for I in 1 .. Len loop
+ Res.Val_Array.V (P) := Left.Val_Array.V (Cnt + 1);
+ P := P + 1;
+ Cnt := Cnt + 1;
+ if Cnt = Len then
+ Cnt := 0;
+ end if;
+ end loop;
+ end case;
+ return Res;
+ end Execute_Shift_Operator;
+
+ Hex_Chars : constant array (Natural range 0 .. 15) of Character :=
+ "0123456789ABCDEF";
+
+ function Execute_Bit_Vector_To_String (Val : Iir_Value_Literal_Acc;
+ Log_Base : Natural)
+ return Iir_Value_Literal_Acc
+ is
+ Base : constant Natural := 2 ** Log_Base;
+ Blen : constant Natural := Natural (Val.Bounds.D (1).Length);
+ Str : String (1 .. (Blen + Log_Base - 1) / Log_Base);
+ Pos : Natural;
+ V : Natural;
+ N : Natural;
+ begin
+ V := 0;
+ N := 1;
+ Pos := Str'Last;
+ for I in reverse Val.Val_Array.V'Range loop
+ V := V + Ghdl_B1'Pos (Val.Val_Array.V (I).B1) * N;
+ N := N * 2;
+ if N = Base or else I = Val.Val_Array.V'First then
+ Str (Pos) := Hex_Chars (V);
+ Pos := Pos - 1;
+ N := 1;
+ V := 0;
+ end if;
+ end loop;
+ return String_To_Iir_Value (Str);
+ end Execute_Bit_Vector_To_String;
+
+ procedure Check_Std_Ulogic_Dc
+ (Loc : Iir; V : Grt.Std_Logic_1164.Std_Ulogic)
+ is
+ use Grt.Std_Logic_1164;
+ begin
+ if V = '-' then
+ Execute_Failed_Assertion
+ ("STD_LOGIC_1164: '-' operand for matching ordering operator",
+ 2, Loc);
+ end if;
+ end Check_Std_Ulogic_Dc;
+
+ -- EXPR is the expression whose implementation is an implicit function.
+ function Execute_Implicit_Function (Block : Block_Instance_Acc;
+ Expr: Iir;
+ Left_Param : Iir;
+ Right_Param : Iir;
+ Res_Type : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ pragma Unsuppress (Overflow_Check);
+
+ Func : Iir_Predefined_Functions;
+
+ -- Rename definition for monadic operations.
+ Left, Right: Iir_Value_Literal_Acc;
+ Operand : Iir_Value_Literal_Acc renames Left;
+ Result: Iir_Value_Literal_Acc;
+
+ procedure Eval_Right is
+ begin
+ Right := Execute_Expression (Block, Right_Param);
+ end Eval_Right;
+
+ -- Eval right argument, check left and right have same length,
+ -- Create RESULT from left.
+ procedure Eval_Array is
+ begin
+ Eval_Right;
+ if Left.Bounds.D (1).Length /= Right.Bounds.D (1).Length then
+ Error_Msg_Constraint (Expr);
+ end if;
+ -- Need to copy as the result is modified.
+ Result := Unshare (Left, Expr_Pool'Access);
+ end Eval_Array;
+
+ Imp : Iir;
+ begin
+ Imp := Get_Implementation (Expr);
+ if Get_Kind (Imp) in Iir_Kinds_Denoting_Name then
+ Imp := Get_Named_Entity (Imp);
+ end if;
+ Func := Get_Implicit_Definition (Imp);
+
+ -- Eval left operand.
+ case Func is
+ when Iir_Predefined_Now_Function =>
+ Left := null;
+ when Iir_Predefined_Bit_Rising_Edge
+ | Iir_Predefined_Boolean_Rising_Edge
+ | Iir_Predefined_Bit_Falling_Edge
+ | Iir_Predefined_Boolean_Falling_Edge=>
+ Operand := Execute_Name (Block, Left_Param, True);
+ when others =>
+ Left := Execute_Expression (Block, Left_Param);
+ end case;
+ Right := null;
+
+ case Func is
+ when Iir_Predefined_Error =>
+ raise Internal_Error;
+
+ when Iir_Predefined_Array_Array_Concat
+ | Iir_Predefined_Element_Array_Concat
+ | Iir_Predefined_Array_Element_Concat
+ | Iir_Predefined_Element_Element_Concat =>
+ Eval_Right;
+
+ declare
+ -- Array length of the result.
+ Len: Iir_Index32;
+
+ -- Index into the result.
+ Pos: Iir_Index32;
+ begin
+ -- Compute the length of the result.
+ case Func is
+ when Iir_Predefined_Array_Array_Concat =>
+ Len := Left.Val_Array.Len + Right.Val_Array.Len;
+ when Iir_Predefined_Element_Array_Concat =>
+ Len := 1 + Right.Val_Array.Len;
+ when Iir_Predefined_Array_Element_Concat =>
+ Len := Left.Val_Array.Len + 1;
+ when Iir_Predefined_Element_Element_Concat =>
+ Len := 1 + 1;
+ when others =>
+ raise Program_Error;
+ end case;
+
+ -- LRM93 7.2.4
+ -- If both operands are null arrays, then the result of the
+ -- concatenation is the right operand.
+ if Len = 0 then
+ -- Note: this return is allowed since LEFT is free, and
+ -- RIGHT must not be free.
+ return Right;
+ end if;
+
+ -- Create the array result.
+ Result := Create_Array_Value (Len, 1);
+ Result.Bounds.D (1) := Create_Bounds_From_Length
+ (Block, Get_First_Element (Get_Index_Subtype_List (Res_Type)),
+ Len);
+
+ -- Fill the result: left.
+ case Func is
+ when Iir_Predefined_Array_Array_Concat
+ | Iir_Predefined_Array_Element_Concat =>
+ for I in Left.Val_Array.V'Range loop
+ Result.Val_Array.V (I) := Left.Val_Array.V (I);
+ end loop;
+ Pos := Left.Val_Array.Len;
+ when Iir_Predefined_Element_Array_Concat
+ | Iir_Predefined_Element_Element_Concat =>
+ Result.Val_Array.V (1) := Left;
+ Pos := 1;
+ when others =>
+ raise Program_Error;
+ end case;
+
+ -- Note: here POS is equal to the position of the last element
+ -- filled, or 0 if no elements were filled.
+
+ -- Fill the result: right.
+ case Func is
+ when Iir_Predefined_Array_Array_Concat
+ | Iir_Predefined_Element_Array_Concat =>
+ for I in Right.Val_Array.V'Range loop
+ Result.Val_Array.V (Pos + I) := Right.Val_Array.V (I);
+ end loop;
+ when Iir_Predefined_Array_Element_Concat
+ | Iir_Predefined_Element_Element_Concat =>
+ Result.Val_Array.V (Pos + 1) := Right;
+ when others =>
+ raise Program_Error;
+ end case;
+ end;
+
+ when Iir_Predefined_Bit_And
+ | Iir_Predefined_Boolean_And =>
+ if Left.B1 = Lit_Enum_0.B1 then
+ -- Short circuit operator.
+ Result := Lit_Enum_0;
+ else
+ Eval_Right;
+ Result := Boolean_To_Lit (Right.B1 = Lit_Enum_1.B1);
+ end if;
+ when Iir_Predefined_Bit_Nand
+ | Iir_Predefined_Boolean_Nand =>
+ if Left.B1 = Lit_Enum_0.B1 then
+ -- Short circuit operator.
+ Result := Lit_Enum_1;
+ else
+ Eval_Right;
+ Result := Boolean_To_Lit (Right.B1 = Lit_Enum_0.B1);
+ end if;
+ when Iir_Predefined_Bit_Or
+ | Iir_Predefined_Boolean_Or =>
+ if Left.B1 = Lit_Enum_1.B1 then
+ -- Short circuit operator.
+ Result := Lit_Enum_1;
+ else
+ Eval_Right;
+ Result := Boolean_To_Lit (Right.B1 = Lit_Enum_1.B1);
+ end if;
+ when Iir_Predefined_Bit_Nor
+ | Iir_Predefined_Boolean_Nor =>
+ if Left.B1 = Lit_Enum_1.B1 then
+ -- Short circuit operator.
+ Result := Lit_Enum_0;
+ else
+ Eval_Right;
+ Result := Boolean_To_Lit (Right.B1 = Lit_Enum_0.B1);
+ end if;
+ when Iir_Predefined_Bit_Xor
+ | Iir_Predefined_Boolean_Xor =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Left.B1 /= Right.B1);
+ when Iir_Predefined_Bit_Xnor
+ | Iir_Predefined_Boolean_Xnor =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Left.B1 = Right.B1);
+ when Iir_Predefined_Bit_Not
+ | Iir_Predefined_Boolean_Not =>
+ Result := Boolean_To_Lit (Operand.B1 = Lit_Enum_0.B1);
+
+ when Iir_Predefined_Bit_Condition =>
+ Result := Boolean_To_Lit (Operand.B1 = Lit_Enum_1.B1);
+
+ when Iir_Predefined_Array_Sll
+ | Iir_Predefined_Array_Srl
+ | Iir_Predefined_Array_Sla
+ | Iir_Predefined_Array_Sra
+ | Iir_Predefined_Array_Rol
+ | Iir_Predefined_Array_Ror =>
+ Eval_Right;
+ Result := Execute_Shift_Operator (Left, Right.I64, Expr);
+
+ when Iir_Predefined_Enum_Equality
+ | Iir_Predefined_Integer_Equality
+ | Iir_Predefined_Array_Equality
+ | Iir_Predefined_Access_Equality
+ | Iir_Predefined_Physical_Equality
+ | Iir_Predefined_Floating_Equality
+ | Iir_Predefined_Record_Equality
+ | Iir_Predefined_Bit_Match_Equality
+ | Iir_Predefined_Bit_Array_Match_Equality =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Is_Equal (Left, Right));
+ when Iir_Predefined_Enum_Inequality
+ | Iir_Predefined_Integer_Inequality
+ | Iir_Predefined_Array_Inequality
+ | Iir_Predefined_Access_Inequality
+ | Iir_Predefined_Physical_Inequality
+ | Iir_Predefined_Floating_Inequality
+ | Iir_Predefined_Record_Inequality
+ | Iir_Predefined_Bit_Match_Inequality
+ | Iir_Predefined_Bit_Array_Match_Inequality =>
+ Eval_Right;
+ Result := Boolean_To_Lit (not Is_Equal (Left, Right));
+ when Iir_Predefined_Integer_Less
+ | Iir_Predefined_Physical_Less =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ Result := Boolean_To_Lit (Left.I64 < Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Integer_Greater
+ | Iir_Predefined_Physical_Greater =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ Result := Boolean_To_Lit (Left.I64 > Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Integer_Less_Equal
+ | Iir_Predefined_Physical_Less_Equal =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ Result := Boolean_To_Lit (Left.I64 <= Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Integer_Greater_Equal
+ | Iir_Predefined_Physical_Greater_Equal =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ Result := Boolean_To_Lit (Left.I64 >= Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Enum_Less =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_B1 =>
+ Result := Boolean_To_Lit (Left.B1 < Right.B1);
+ when Iir_Value_E32 =>
+ Result := Boolean_To_Lit (Left.E32 < Right.E32);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Enum_Greater =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_B1 =>
+ Result := Boolean_To_Lit (Left.B1 > Right.B1);
+ when Iir_Value_E32 =>
+ Result := Boolean_To_Lit (Left.E32 > Right.E32);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Enum_Less_Equal =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_B1 =>
+ Result := Boolean_To_Lit (Left.B1 <= Right.B1);
+ when Iir_Value_E32 =>
+ Result := Boolean_To_Lit (Left.E32 <= Right.E32);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Enum_Greater_Equal =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_B1 =>
+ Result := Boolean_To_Lit (Left.B1 >= Right.B1);
+ when Iir_Value_E32 =>
+ Result := Boolean_To_Lit (Left.E32 >= Right.E32);
+ when others =>
+ raise Internal_Error;
+ end case;
+
+ when Iir_Predefined_Enum_Minimum
+ | Iir_Predefined_Physical_Minimum =>
+ Eval_Right;
+ if Compare_Value (Left, Right) = Less then
+ Result := Left;
+ else
+ Result := Right;
+ end if;
+ when Iir_Predefined_Enum_Maximum
+ | Iir_Predefined_Physical_Maximum =>
+ Eval_Right;
+ if Compare_Value (Left, Right) = Less then
+ Result := Right;
+ else
+ Result := Left;
+ end if;
+
+ when Iir_Predefined_Integer_Plus
+ | Iir_Predefined_Physical_Plus =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ Result := Create_I64_Value (Left.I64 + Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Integer_Minus
+ | Iir_Predefined_Physical_Minus =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ Result := Create_I64_Value (Left.I64 - Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Integer_Mul =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ Result := Create_I64_Value (Left.I64 * Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Integer_Mod =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ if Right.I64 = 0 then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Result := Create_I64_Value (Left.I64 mod Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Integer_Rem =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ if Right.I64 = 0 then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Result := Create_I64_Value (Left.I64 rem Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Predefined_Integer_Div =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ if Right.I64 = 0 then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Result := Create_I64_Value (Left.I64 / Right.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+
+ when Iir_Predefined_Integer_Absolute
+ | Iir_Predefined_Physical_Absolute =>
+ case Operand.Kind is
+ when Iir_Value_I64 =>
+ Result := Create_I64_Value (abs Operand.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+
+ when Iir_Predefined_Integer_Negation
+ | Iir_Predefined_Physical_Negation =>
+ case Operand.Kind is
+ when Iir_Value_I64 =>
+ Result := Create_I64_Value (-Operand.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+
+ when Iir_Predefined_Integer_Identity
+ | Iir_Predefined_Physical_Identity =>
+ case Operand.Kind is
+ when Iir_Value_I64 =>
+ Result := Create_I64_Value (Operand.I64);
+ when others =>
+ raise Internal_Error;
+ end case;
+
+ when Iir_Predefined_Integer_Exp =>
+ Eval_Right;
+ case Left.Kind is
+ when Iir_Value_I64 =>
+ if Right.I64 < 0 then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Result := Create_I64_Value (Left.I64 ** Natural (Right.I64));
+ when others =>
+ raise Internal_Error;
+ end case;
+
+ when Iir_Predefined_Integer_Minimum =>
+ Eval_Right;
+ Result := Create_I64_Value (Ghdl_I64'Min (Left.I64, Right.I64));
+ when Iir_Predefined_Integer_Maximum =>
+ Eval_Right;
+ Result := Create_I64_Value (Ghdl_I64'Max (Left.I64, Right.I64));
+
+ when Iir_Predefined_Floating_Mul =>
+ Eval_Right;
+ Result := Create_F64_Value (Left.F64 * Right.F64);
+ when Iir_Predefined_Floating_Div =>
+ Eval_Right;
+ Result := Create_F64_Value (Left.F64 / Right.F64);
+ when Iir_Predefined_Floating_Minus =>
+ Eval_Right;
+ Result := Create_F64_Value (Left.F64 - Right.F64);
+ when Iir_Predefined_Floating_Plus =>
+ Eval_Right;
+ Result := Create_F64_Value (Left.F64 + Right.F64);
+ when Iir_Predefined_Floating_Exp =>
+ Eval_Right;
+ Result := Create_F64_Value (Left.F64 ** Integer (Right.I64));
+ when Iir_Predefined_Floating_Identity =>
+ Result := Create_F64_Value (Operand.F64);
+ when Iir_Predefined_Floating_Negation =>
+ Result := Create_F64_Value (-Operand.F64);
+ when Iir_Predefined_Floating_Absolute =>
+ Result := Create_F64_Value (abs (Operand.F64));
+ when Iir_Predefined_Floating_Less =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Left.F64 < Right.F64);
+ when Iir_Predefined_Floating_Less_Equal =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Left.F64 <= Right.F64);
+ when Iir_Predefined_Floating_Greater =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Left.F64 > Right.F64);
+ when Iir_Predefined_Floating_Greater_Equal =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Left.F64 >= Right.F64);
+
+ when Iir_Predefined_Floating_Minimum =>
+ Eval_Right;
+ Result := Create_F64_Value (Ghdl_F64'Min (Left.F64, Right.F64));
+ when Iir_Predefined_Floating_Maximum =>
+ Eval_Right;
+ Result := Create_F64_Value (Ghdl_F64'Max (Left.F64, Right.F64));
+
+ when Iir_Predefined_Integer_Physical_Mul =>
+ Eval_Right;
+ Result := Create_I64_Value (Left.I64 * Right.I64);
+ when Iir_Predefined_Physical_Integer_Mul =>
+ Eval_Right;
+ Result := Create_I64_Value (Left.I64 * Right.I64);
+ when Iir_Predefined_Physical_Physical_Div =>
+ Eval_Right;
+ Result := Create_I64_Value (Left.I64 / Right.I64);
+ when Iir_Predefined_Physical_Integer_Div =>
+ Eval_Right;
+ Result := Create_I64_Value (Left.I64 / Right.I64);
+ when Iir_Predefined_Real_Physical_Mul =>
+ Eval_Right;
+ Result := Create_I64_Value
+ (Ghdl_I64 (Left.F64 * Ghdl_F64 (Right.I64)));
+ when Iir_Predefined_Physical_Real_Mul =>
+ Eval_Right;
+ Result := Create_I64_Value
+ (Ghdl_I64 (Ghdl_F64 (Left.I64) * Right.F64));
+ when Iir_Predefined_Physical_Real_Div =>
+ Eval_Right;
+ Result := Create_I64_Value
+ (Ghdl_I64 (Ghdl_F64 (Left.I64) / Right.F64));
+
+ when Iir_Predefined_Universal_I_R_Mul =>
+ Eval_Right;
+ Result := Create_F64_Value (Ghdl_F64 (Left.I64) * Right.F64);
+ when Iir_Predefined_Universal_R_I_Mul =>
+ Eval_Right;
+ Result := Create_F64_Value (Left.F64 * Ghdl_F64 (Right.I64));
+
+ when Iir_Predefined_TF_Array_And =>
+ Eval_Array;
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 and Right.Val_Array.V (I).B1;
+ end loop;
+ when Iir_Predefined_TF_Array_Nand =>
+ Eval_Array;
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 and Right.Val_Array.V (I).B1);
+ end loop;
+ when Iir_Predefined_TF_Array_Or =>
+ Eval_Array;
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 or Right.Val_Array.V (I).B1;
+ end loop;
+ when Iir_Predefined_TF_Array_Nor =>
+ Eval_Array;
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 or Right.Val_Array.V (I).B1);
+ end loop;
+ when Iir_Predefined_TF_Array_Xor =>
+ Eval_Array;
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 xor Right.Val_Array.V (I).B1;
+ end loop;
+ when Iir_Predefined_TF_Array_Xnor =>
+ Eval_Array;
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 xor Right.Val_Array.V (I).B1);
+ end loop;
+
+ when Iir_Predefined_TF_Array_Element_And =>
+ Eval_Right;
+ Result := Unshare (Left, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 and Right.B1;
+ end loop;
+ when Iir_Predefined_TF_Element_Array_And =>
+ Eval_Right;
+ Result := Unshare (Right, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 and Left.B1;
+ end loop;
+
+ when Iir_Predefined_TF_Array_Element_Or =>
+ Eval_Right;
+ Result := Unshare (Left, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 or Right.B1;
+ end loop;
+ when Iir_Predefined_TF_Element_Array_Or =>
+ Eval_Right;
+ Result := Unshare (Right, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 or Left.B1;
+ end loop;
+
+ when Iir_Predefined_TF_Array_Element_Xor =>
+ Eval_Right;
+ Result := Unshare (Left, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 xor Right.B1;
+ end loop;
+ when Iir_Predefined_TF_Element_Array_Xor =>
+ Eval_Right;
+ Result := Unshare (Right, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ Result.Val_Array.V (I).B1 xor Left.B1;
+ end loop;
+
+ when Iir_Predefined_TF_Array_Element_Nand =>
+ Eval_Right;
+ Result := Unshare (Left, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 and Right.B1);
+ end loop;
+ when Iir_Predefined_TF_Element_Array_Nand =>
+ Eval_Right;
+ Result := Unshare (Right, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 and Left.B1);
+ end loop;
+
+ when Iir_Predefined_TF_Array_Element_Nor =>
+ Eval_Right;
+ Result := Unshare (Left, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 or Right.B1);
+ end loop;
+ when Iir_Predefined_TF_Element_Array_Nor =>
+ Eval_Right;
+ Result := Unshare (Right, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 or Left.B1);
+ end loop;
+
+ when Iir_Predefined_TF_Array_Element_Xnor =>
+ Eval_Right;
+ Result := Unshare (Left, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 xor Right.B1);
+ end loop;
+ when Iir_Predefined_TF_Element_Array_Xnor =>
+ Eval_Right;
+ Result := Unshare (Right, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 :=
+ not (Result.Val_Array.V (I).B1 xor Left.B1);
+ end loop;
+
+ when Iir_Predefined_TF_Array_Not =>
+ -- Need to copy as the result is modified.
+ Result := Unshare (Operand, Expr_Pool'Access);
+ for I in Result.Val_Array.V'Range loop
+ Result.Val_Array.V (I).B1 := not Result.Val_Array.V (I).B1;
+ end loop;
+
+ when Iir_Predefined_TF_Reduction_And =>
+ Result := Create_B1_Value (True);
+ for I in Operand.Val_Array.V'Range loop
+ Result.B1 := Result.B1 and Operand.Val_Array.V (I).B1;
+ end loop;
+ when Iir_Predefined_TF_Reduction_Nand =>
+ Result := Create_B1_Value (True);
+ for I in Operand.Val_Array.V'Range loop
+ Result.B1 := Result.B1 and Operand.Val_Array.V (I).B1;
+ end loop;
+ Result.B1 := not Result.B1;
+ when Iir_Predefined_TF_Reduction_Or =>
+ Result := Create_B1_Value (False);
+ for I in Operand.Val_Array.V'Range loop
+ Result.B1 := Result.B1 or Operand.Val_Array.V (I).B1;
+ end loop;
+ when Iir_Predefined_TF_Reduction_Nor =>
+ Result := Create_B1_Value (False);
+ for I in Operand.Val_Array.V'Range loop
+ Result.B1 := Result.B1 or Operand.Val_Array.V (I).B1;
+ end loop;
+ Result.B1 := not Result.B1;
+ when Iir_Predefined_TF_Reduction_Xor =>
+ Result := Create_B1_Value (False);
+ for I in Operand.Val_Array.V'Range loop
+ Result.B1 := Result.B1 xor Operand.Val_Array.V (I).B1;
+ end loop;
+ when Iir_Predefined_TF_Reduction_Xnor =>
+ Result := Create_B1_Value (False);
+ for I in Operand.Val_Array.V'Range loop
+ Result.B1 := Result.B1 xor Operand.Val_Array.V (I).B1;
+ end loop;
+ Result.B1 := not Result.B1;
+
+ when Iir_Predefined_Bit_Rising_Edge
+ | Iir_Predefined_Boolean_Rising_Edge =>
+ return Boolean_To_Lit
+ (Execute_Event_Attribute (Operand)
+ and then Execute_Signal_Value (Operand).B1 = True);
+ when Iir_Predefined_Bit_Falling_Edge
+ | Iir_Predefined_Boolean_Falling_Edge =>
+ return Boolean_To_Lit
+ (Execute_Event_Attribute (Operand)
+ and then Execute_Signal_Value (Operand).B1 = False);
+
+ when Iir_Predefined_Array_Greater =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Compare_Value (Left, Right) = Greater);
+
+ when Iir_Predefined_Array_Greater_Equal =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Compare_Value (Left, Right) >= Equal);
+
+ when Iir_Predefined_Array_Less =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Compare_Value (Left, Right) = Less);
+
+ when Iir_Predefined_Array_Less_Equal =>
+ Eval_Right;
+ Result := Boolean_To_Lit (Compare_Value (Left, Right) <= Equal);
+
+ when Iir_Predefined_Array_Minimum =>
+ Eval_Right;
+ if Compare_Value (Left, Right) = Less then
+ Result := Left;
+ else
+ Result := Right;
+ end if;
+ when Iir_Predefined_Array_Maximum =>
+ Eval_Right;
+ if Compare_Value (Left, Right) = Less then
+ Result := Right;
+ else
+ Result := Left;
+ end if;
+
+ when Iir_Predefined_Vector_Maximum =>
+ declare
+ El_St : constant Iir :=
+ Get_Return_Type (Get_Implementation (Expr));
+ V : Iir_Value_Literal_Acc;
+ begin
+ Result := Execute_Low_Limit (Execute_Bounds (Block, El_St));
+ for I in Left.Val_Array.V'Range loop
+ V := Left.Val_Array.V (I);
+ if Compare_Value (V, Result) = Greater then
+ Result := V;
+ end if;
+ end loop;
+ end;
+ when Iir_Predefined_Vector_Minimum =>
+ declare
+ El_St : constant Iir :=
+ Get_Return_Type (Get_Implementation (Expr));
+ V : Iir_Value_Literal_Acc;
+ begin
+ Result := Execute_High_Limit (Execute_Bounds (Block, El_St));
+ for I in Left.Val_Array.V'Range loop
+ V := Left.Val_Array.V (I);
+ if Compare_Value (V, Result) = Less then
+ Result := V;
+ end if;
+ end loop;
+ end;
+
+ when Iir_Predefined_Endfile =>
+ Result := Boolean_To_Lit (File_Operation.Endfile (Left, Null_Iir));
+
+ when Iir_Predefined_Now_Function =>
+ Result := Create_I64_Value (Ghdl_I64 (Grt.Types.Current_Time));
+
+ when Iir_Predefined_Integer_To_String
+ | Iir_Predefined_Floating_To_String
+ | Iir_Predefined_Physical_To_String =>
+ Result := String_To_Iir_Value
+ (Execute_Image_Attribute (Left, Get_Type (Left_Param)));
+
+ when Iir_Predefined_Enum_To_String =>
+ declare
+ use Name_Table;
+ Base_Type : constant Iir :=
+ Get_Base_Type (Get_Type (Left_Param));
+ Lits : constant Iir_List :=
+ Get_Enumeration_Literal_List (Base_Type);
+ Pos : constant Natural := Get_Enum_Pos (Left);
+ Id : Name_Id;
+ begin
+ if Base_Type = Std_Package.Character_Type_Definition then
+ Result := String_To_Iir_Value ((1 => Character'Val (Pos)));
+ else
+ Id := Get_Identifier (Get_Nth_Element (Lits, Pos));
+ if Is_Character (Id) then
+ Result := String_To_Iir_Value ((1 => Get_Character (Id)));
+ else
+ Result := String_To_Iir_Value (Image (Id));
+ end if;
+ end if;
+ end;
+
+ when Iir_Predefined_Array_Char_To_String =>
+ declare
+ Str : String (1 .. Natural (Left.Bounds.D (1).Length));
+ Lits : constant Iir_List :=
+ Get_Enumeration_Literal_List
+ (Get_Base_Type
+ (Get_Element_Subtype (Get_Type (Left_Param))));
+ Pos : Natural;
+ begin
+ for I in Left.Val_Array.V'Range loop
+ Pos := Get_Enum_Pos (Left.Val_Array.V (I));
+ Str (Positive (I)) := Name_Table.Get_Character
+ (Get_Identifier (Get_Nth_Element (Lits, Pos)));
+ end loop;
+ Result := String_To_Iir_Value (Str);
+ end;
+
+ when Iir_Predefined_Bit_Vector_To_Hstring =>
+ return Execute_Bit_Vector_To_String (Left, 4);
+
+ when Iir_Predefined_Bit_Vector_To_Ostring =>
+ return Execute_Bit_Vector_To_String (Left, 3);
+
+ when Iir_Predefined_Real_To_String_Digits =>
+ Eval_Right;
+ declare
+ Str : Grt.Vstrings.String_Real_Digits;
+ Last : Natural;
+ begin
+ Grt.Vstrings.To_String
+ (Str, Last, Left.F64, Ghdl_I32 (Right.I64));
+ Result := String_To_Iir_Value (Str (1 .. Last));
+ end;
+ when Iir_Predefined_Real_To_String_Format =>
+ Eval_Right;
+ declare
+ Format : String (1 .. Natural (Right.Val_Array.Len) + 1);
+ Str : Grt.Vstrings.String_Real_Format;
+ Last : Natural;
+ begin
+ for I in Right.Val_Array.V'Range loop
+ Format (Positive (I)) :=
+ Character'Val (Right.Val_Array.V (I).E32);
+ end loop;
+ Format (Format'Last) := ASCII.NUL;
+ Grt.Vstrings.To_String
+ (Str, Last, Left.F64, To_Ghdl_C_String (Format'Address));
+ Result := String_To_Iir_Value (Str (1 .. Last));
+ end;
+ when Iir_Predefined_Time_To_String_Unit =>
+ Eval_Right;
+ declare
+ Str : Grt.Vstrings.String_Time_Unit;
+ First : Natural;
+ Unit : Iir;
+ begin
+ Unit := Get_Unit_Chain (Std_Package.Time_Type_Definition);
+ while Unit /= Null_Iir loop
+ exit when Evaluation.Get_Physical_Value (Unit)
+ = Iir_Int64 (Right.I64);
+ Unit := Get_Chain (Unit);
+ end loop;
+ if Unit = Null_Iir then
+ Error_Msg_Exec
+ ("to_string for time called with wrong unit", Expr);
+ end if;
+ Grt.Vstrings.To_String (Str, First, Left.I64, Right.I64);
+ Result := String_To_Iir_Value
+ (Str (First .. Str'Last) & ' '
+ & Name_Table.Image (Get_Identifier (Unit)));
+ end;
+
+ when Iir_Predefined_Std_Ulogic_Match_Equality =>
+ Eval_Right;
+ declare
+ use Grt.Std_Logic_1164;
+ begin
+ Result := Create_E32_Value
+ (Std_Ulogic'Pos
+ (Match_Eq_Table (Std_Ulogic'Val (Left.E32),
+ Std_Ulogic'Val (Right.E32))));
+ end;
+ when Iir_Predefined_Std_Ulogic_Match_Inequality =>
+ Eval_Right;
+ declare
+ use Grt.Std_Logic_1164;
+ begin
+ Result := Create_E32_Value
+ (Std_Ulogic'Pos
+ (Not_Table (Match_Eq_Table (Std_Ulogic'Val (Left.E32),
+ Std_Ulogic'Val (Right.E32)))));
+ end;
+ when Iir_Predefined_Std_Ulogic_Match_Ordering_Functions =>
+ Eval_Right;
+ declare
+ use Grt.Std_Logic_1164;
+ L : constant Std_Ulogic := Std_Ulogic'Val (Left.E32);
+ R : constant Std_Ulogic := Std_Ulogic'Val (Right.E32);
+ Res : Std_Ulogic;
+ begin
+ Check_Std_Ulogic_Dc (Expr, L);
+ Check_Std_Ulogic_Dc (Expr, R);
+ case Iir_Predefined_Std_Ulogic_Match_Ordering_Functions (Func)
+ is
+ when Iir_Predefined_Std_Ulogic_Match_Less =>
+ Res := Match_Lt_Table (L, R);
+ when Iir_Predefined_Std_Ulogic_Match_Less_Equal =>
+ Res := Or_Table (Match_Lt_Table (L, R),
+ Match_Eq_Table (L, R));
+ when Iir_Predefined_Std_Ulogic_Match_Greater =>
+ Res := Not_Table (Or_Table (Match_Lt_Table (L, R),
+ Match_Eq_Table (L, R)));
+ when Iir_Predefined_Std_Ulogic_Match_Greater_Equal =>
+ Res := Not_Table (Match_Lt_Table (L, R));
+ end case;
+ Result := Create_E32_Value (Std_Ulogic'Pos (Res));
+ end;
+
+ when Iir_Predefined_Std_Ulogic_Array_Match_Equality
+ | Iir_Predefined_Std_Ulogic_Array_Match_Inequality =>
+ Eval_Right;
+ if Left.Bounds.D (1).Length /= Right.Bounds.D (1).Length then
+ Error_Msg_Constraint (Expr);
+ end if;
+ declare
+ use Grt.Std_Logic_1164;
+ Res : Std_Ulogic := '1';
+ begin
+ Result := Create_E32_Value (Std_Ulogic'Pos ('1'));
+ for I in Left.Val_Array.V'Range loop
+ Res := And_Table
+ (Res,
+ Match_Eq_Table
+ (Std_Ulogic'Val (Left.Val_Array.V (I).E32),
+ Std_Ulogic'Val (Right.Val_Array.V (I).E32)));
+ end loop;
+ if Func = Iir_Predefined_Std_Ulogic_Array_Match_Inequality then
+ Res := Not_Table (Res);
+ end if;
+ Result := Create_E32_Value (Std_Ulogic'Pos (Res));
+ end;
+
+ when others =>
+ Error_Msg ("execute_implicit_function: unimplemented " &
+ Iir_Predefined_Functions'Image (Func));
+ raise Internal_Error;
+ end case;
+ return Result;
+ exception
+ when Constraint_Error =>
+ Error_Msg_Constraint (Expr);
+ end Execute_Implicit_Function;
+
+ procedure Execute_Implicit_Procedure
+ (Block: Block_Instance_Acc; Stmt: Iir_Procedure_Call)
+ is
+ Imp : constant Iir_Implicit_Procedure_Declaration :=
+ Get_Named_Entity (Get_Implementation (Stmt));
+ Assoc_Chain : constant Iir := Get_Parameter_Association_Chain (Stmt);
+ Assoc: Iir;
+ Args: Iir_Value_Literal_Array (0 .. 3);
+ Inter_Chain : Iir;
+ Expr_Mark : Mark_Type;
+ begin
+ Mark (Expr_Mark, Expr_Pool);
+ Assoc := Assoc_Chain;
+ for I in Iir_Index32 loop
+ exit when Assoc = Null_Iir;
+ Args (I) := Execute_Expression (Block, Get_Actual (Assoc));
+ Assoc := Get_Chain (Assoc);
+ end loop;
+ Inter_Chain := Get_Interface_Declaration_Chain (Imp);
+ case Get_Implicit_Definition (Imp) is
+ when Iir_Predefined_Deallocate =>
+ if Args (0).Val_Access /= null then
+ Free_Heap_Value (Args (0));
+ Args (0).Val_Access := null;
+ end if;
+ when Iir_Predefined_File_Open =>
+ File_Operation.File_Open
+ (Args (0), Args (1), Args (2), Inter_Chain, Stmt);
+ when Iir_Predefined_File_Open_Status =>
+ File_Operation.File_Open_Status
+ (Args (0), Args (1), Args (2), Args (3),
+ Get_Chain (Inter_Chain), Stmt);
+ when Iir_Predefined_Write =>
+ if Get_Text_File_Flag (Get_Type (Inter_Chain)) then
+ File_Operation.Write_Text (Args (0), Args (1));
+ else
+ File_Operation.Write_Binary (Args (0), Args (1));
+ end if;
+ when Iir_Predefined_Read_Length =>
+ if Get_Text_File_Flag (Get_Type (Inter_Chain)) then
+ File_Operation.Read_Length_Text
+ (Args (0), Args (1), Args (2));
+ else
+ File_Operation.Read_Length_Binary
+ (Args (0), Args (1), Args (2));
+ end if;
+ when Iir_Predefined_Read =>
+ File_Operation.Read_Binary (Args (0), Args (1));
+ when Iir_Predefined_Flush =>
+ File_Operation.Flush (Args (0));
+ when Iir_Predefined_File_Close =>
+ if Get_Text_File_Flag (Get_Type (Inter_Chain)) then
+ File_Operation.File_Close_Text (Args (0), Stmt);
+ else
+ File_Operation.File_Close_Binary (Args (0), Stmt);
+ end if;
+ when others =>
+ Error_Kind ("execute_implicit_procedure",
+ Get_Implicit_Definition (Imp));
+ end case;
+ Release (Expr_Mark, Expr_Pool);
+ end Execute_Implicit_Procedure;
+
+ procedure Execute_Foreign_Procedure
+ (Block: Block_Instance_Acc; Stmt: Iir_Procedure_Call)
+ is
+ Imp : constant Iir_Implicit_Procedure_Declaration :=
+ Get_Implementation (Stmt);
+ Assoc_Chain : constant Iir := Get_Parameter_Association_Chain (Stmt);
+ Assoc: Iir;
+ Args: Iir_Value_Literal_Array (0 .. 3) := (others => null);
+ Expr_Mark : Mark_Type;
+ begin
+ Mark (Expr_Mark, Expr_Pool);
+ Assoc := Assoc_Chain;
+ for I in Args'Range loop
+ exit when Assoc = Null_Iir;
+ Args (I) := Execute_Expression (Block, Get_Actual (Assoc));
+ Assoc := Get_Chain (Assoc);
+ end loop;
+ case Get_Identifier (Imp) is
+ when Std_Names.Name_Untruncated_Text_Read =>
+ File_Operation.Untruncated_Text_Read
+ (Args (0), Args (1), Args (2));
+ when Std_Names.Name_Control_Simulation =>
+ Put_Line (Standard_Error, "simulation finished");
+ raise Simulation_Finished;
+ when others =>
+ Error_Msg_Exec ("unsupported foreign procedure call", Stmt);
+ end case;
+ Release (Expr_Mark, Expr_Pool);
+ end Execute_Foreign_Procedure;
+
+ -- Compute the offset for INDEX into a range BOUNDS.
+ -- EXPR is only used in case of error.
+ function Get_Index_Offset
+ (Index: Iir_Value_Literal_Acc;
+ Bounds: Iir_Value_Literal_Acc;
+ Expr: Iir)
+ return Iir_Index32
+ is
+ Left_Pos, Right_Pos: Iir_Value_Literal_Acc;
+ begin
+ Left_Pos := Bounds.Left;
+ Right_Pos := Bounds.Right;
+ if Index.Kind /= Left_Pos.Kind or else Index.Kind /= Right_Pos.Kind then
+ raise Internal_Error;
+ end if;
+ case Index.Kind is
+ when Iir_Value_B1 =>
+ case Bounds.Dir is
+ when Iir_To =>
+ if Index.B1 >= Left_Pos.B1 and then
+ Index.B1 <= Right_Pos.B1
+ then
+ -- to
+ return Ghdl_B1'Pos (Index.B1) - Ghdl_B1'Pos (Left_Pos.B1);
+ end if;
+ when Iir_Downto =>
+ if Index.B1 <= Left_Pos.B1 and then
+ Index.B1 >= Right_Pos.B1
+ then
+ -- downto
+ return Ghdl_B1'Pos (Left_Pos.B1) - Ghdl_B1'Pos (Index.B1);
+ end if;
+ end case;
+ when Iir_Value_E32 =>
+ case Bounds.Dir is
+ when Iir_To =>
+ if Index.E32 >= Left_Pos.E32 and then
+ Index.E32 <= Right_Pos.E32
+ then
+ -- to
+ return Iir_Index32 (Index.E32 - Left_Pos.E32);
+ end if;
+ when Iir_Downto =>
+ if Index.E32 <= Left_Pos.E32 and then
+ Index.E32 >= Right_Pos.E32
+ then
+ -- downto
+ return Iir_Index32 (Left_Pos.E32 - Index.E32);
+ end if;
+ end case;
+ when Iir_Value_I64 =>
+ case Bounds.Dir is
+ when Iir_To =>
+ if Index.I64 >= Left_Pos.I64 and then
+ Index.I64 <= Right_Pos.I64
+ then
+ -- to
+ return Iir_Index32 (Index.I64 - Left_Pos.I64);
+ end if;
+ when Iir_Downto =>
+ if Index.I64 <= Left_Pos.I64 and then
+ Index.I64 >= Right_Pos.I64
+ then
+ -- downto
+ return Iir_Index32 (Left_Pos.I64 - Index.I64);
+ end if;
+ end case;
+ when others =>
+ raise Internal_Error;
+ end case;
+ Error_Msg_Constraint (Expr);
+ return 0;
+ end Get_Index_Offset;
+
+ -- Create an iir_value_literal of kind iir_value_array and of life LIFE.
+ -- Allocate the array of bounds, and fill it from A_TYPE.
+ -- Allocate the array of values.
+ function Create_Array_Bounds_From_Type
+ (Block : Block_Instance_Acc;
+ A_Type : Iir;
+ Create_Val_Array : Boolean)
+ return Iir_Value_Literal_Acc
+ is
+ Res : Iir_Value_Literal_Acc;
+ Index_List : Iir_List;
+ Len : Iir_Index32;
+ Bound : Iir_Value_Literal_Acc;
+ begin
+ -- Only for constrained subtypes.
+ if Get_Kind (A_Type) = Iir_Kind_Array_Type_Definition then
+ raise Internal_Error;
+ end if;
+
+ Index_List := Get_Index_Subtype_List (A_Type);
+ Res := Create_Array_Value
+ (Iir_Index32 (Get_Nbr_Elements (Index_List)));
+ Len := 1;
+ for I in 1 .. Res.Bounds.Nbr_Dims loop
+ Bound := Execute_Bounds
+ (Block, Get_Nth_Element (Index_List, Natural (I - 1)));
+ Len := Len * Bound.Length;
+ Res.Bounds.D (I) := Bound;
+ end loop;
+ if Create_Val_Array then
+ Create_Array_Data (Res, Len);
+ end if;
+ return Res;
+ end Create_Array_Bounds_From_Type;
+
+ -- Return the steps (ie, offset in the array when index DIM is increased
+ -- by one) for array ARR and dimension DIM.
+ function Get_Step_For_Dim (Arr: Iir_Value_Literal_Acc; Dim : Natural)
+ return Iir_Index32
+ is
+ Bounds : Value_Bounds_Array_Acc renames Arr.Bounds;
+ Res : Iir_Index32;
+ begin
+ Res := 1;
+ for I in Iir_Index32 (Dim + 1) .. Bounds.Nbr_Dims loop
+ Res := Res * Bounds.D (I).Length;
+ end loop;
+ return Res;
+ end Get_Step_For_Dim;
+
+ -- Create a literal for a string or a bit_string
+ function String_To_Enumeration_Array_1 (Str: Iir; El_Type : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Lit: Iir_Value_Literal_Acc;
+ Element_Mode : Iir_Value_Scalars;
+
+ procedure Create_Lit_El
+ (Index : Iir_Index32; Literal: Iir_Enumeration_Literal)
+ is
+ R : Iir_Value_Literal_Acc;
+ P : constant Iir_Int32 := Get_Enum_Pos (Literal);
+ begin
+ case Element_Mode is
+ when Iir_Value_B1 =>
+ R := Create_B1_Value (Ghdl_B1'Val (P));
+ when Iir_Value_E32 =>
+ R := Create_E32_Value (Ghdl_E32'Val (P));
+ when others =>
+ raise Internal_Error;
+ end case;
+ Lit.Val_Array.V (Index) := R;
+ end Create_Lit_El;
+
+ El_Btype : constant Iir := Get_Base_Type (El_Type);
+ Literal_List: constant Iir_List :=
+ Get_Enumeration_Literal_List (El_Btype);
+ Len: Iir_Index32;
+ Str_As_Str: constant String := Iirs_Utils.Image_String_Lit (Str);
+ El : Iir;
+ begin
+ Element_Mode := Get_Info (El_Btype).Scalar_Mode;
+
+ case Get_Kind (Str) is
+ when Iir_Kind_String_Literal =>
+ Len := Iir_Index32 (Str_As_Str'Length);
+ Lit := Create_Array_Value (Len, 1);
+
+ for I in Lit.Val_Array.V'Range loop
+ -- FIXME: use literal from type ??
+ El := Find_Name_In_List
+ (Literal_List,
+ Name_Table.Get_Identifier (Str_As_Str (Natural (I))));
+ if El = Null_Iir then
+ -- FIXME: could free what was already built.
+ return null;
+ end if;
+ Create_Lit_El (I, El);
+ end loop;
+
+ when Iir_Kind_Bit_String_Literal =>
+ declare
+ Lit_0, Lit_1 : Iir;
+ Buf : String_Fat_Acc;
+ Len1 : Int32;
+ begin
+ Lit_0 := Get_Bit_String_0 (Str);
+ Lit_1 := Get_Bit_String_1 (Str);
+ Buf := Str_Table.Get_String_Fat_Acc (Get_String_Id (Str));
+ Len1 := Get_String_Length (Str);
+ Lit := Create_Array_Value (Iir_Index32 (Len1), 1);
+
+ if Lit_0 = Null_Iir or Lit_1 = Null_Iir then
+ raise Internal_Error;
+ end if;
+ for I in 1 .. Len1 loop
+ case Buf (I) is
+ when '0' =>
+ Create_Lit_El (Iir_Index32 (I), Lit_0);
+ when '1' =>
+ Create_Lit_El (Iir_Index32 (I), Lit_1);
+ when others =>
+ raise Internal_Error;
+ end case;
+ end loop;
+ end;
+ when others =>
+ raise Internal_Error;
+ end case;
+
+ return Lit;
+ end String_To_Enumeration_Array_1;
+
+ -- Create a literal for a string or a bit_string
+ function String_To_Enumeration_Array (Block: Block_Instance_Acc; Str: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Res : Iir_Value_Literal_Acc;
+ Array_Type: constant Iir := Get_Type (Str);
+ Index_Types : constant Iir_List := Get_Index_Subtype_List (Array_Type);
+ begin
+ if Get_Nbr_Elements (Index_Types) /= 1 then
+ raise Internal_Error; -- array must be unidimensional
+ end if;
+
+ Res := String_To_Enumeration_Array_1
+ (Str, Get_Element_Subtype (Array_Type));
+
+ -- When created from static evaluation, a string may still have an
+ -- unconstrained type.
+ if Get_Constraint_State (Array_Type) /= Fully_Constrained then
+ Res.Bounds.D (1) :=
+ Create_Range_Value (Create_I64_Value (1),
+ Create_I64_Value (Ghdl_I64 (Res.Val_Array.Len)),
+ Iir_To,
+ Res.Val_Array.Len);
+ else
+ Res.Bounds.D (1) :=
+ Execute_Bounds (Block, Get_First_Element (Index_Types));
+ end if;
+
+ -- The range may not be statically constant.
+ if Res.Bounds.D (1).Length /= Res.Val_Array.Len then
+ Error_Msg_Constraint (Str);
+ end if;
+
+ return Res;
+ end String_To_Enumeration_Array;
+
+ -- Fill LENGTH elements of RES, starting at ORIG by steps of STEP.
+ -- Use expressions from (BLOCK, AGGREGATE) to fill the elements.
+ -- EL_TYPE is the type of the array element.
+ procedure Fill_Array_Aggregate_1
+ (Block : Block_Instance_Acc;
+ Aggregate : Iir;
+ Res : Iir_Value_Literal_Acc;
+ Orig : Iir_Index32;
+ Step : Iir_Index32;
+ Dim : Iir_Index32;
+ Nbr_Dim : Iir_Index32;
+ El_Type : Iir)
+ is
+ Value : Iir;
+ Bound : constant Iir_Value_Literal_Acc := Res.Bounds.D (Dim);
+
+ procedure Set_Elem (Pos : Iir_Index32)
+ is
+ Val : Iir_Value_Literal_Acc;
+ begin
+ if Dim = Nbr_Dim then
+ -- VALUE is an expression (which may be an aggregate, but not
+ -- a sub-aggregate.
+ Val := Execute_Expression_With_Type (Block, Value, El_Type);
+ -- LRM93 7.3.2.2
+ -- For a multi-dimensional aggregate of dimension n, a check
+ -- is made that all (n-1)-dimensional subaggregates have the
+ -- same bounds.
+ -- GHDL: I have added an implicit array conversion, however
+ -- it may be useful to allow cases like this:
+ -- type str_array is array (natural range <>)
+ -- of string (10 downto 1);
+ -- constant floats : str_array :=
+ -- ( "00000000.0", HT & "+1.5ABCDE");
+ -- The subtype of the first sub-aggregate (0.0) is
+ -- determinated by the context, according to rule 9 and 4
+ -- of LRM93 7.3.2.2 and therefore is string (10 downto 1),
+ -- while the subtype of the second sub-aggregate (HT & ...)
+ -- is determinated by rules 1 and 2 of LRM 7.2.4, and is
+ -- string (1 to 10).
+ -- Unless an implicit conversion is used, according to the
+ -- LRM, this should fail, but it makes no sens.
+ --
+ -- FIXME: Add a warning, a flag ?
+ --Implicit_Array_Conversion (Block, Val, El_Type, Value);
+ --Check_Constraints (Block, Val, El_Type, Value);
+ Res.Val_Array.V (1 + Orig + Pos * Step) := Val;
+ else
+ case Get_Kind (Value) is
+ when Iir_Kind_Aggregate =>
+ -- VALUE is a sub-aggregate.
+ Fill_Array_Aggregate_1 (Block, Value, Res,
+ Orig + Pos * Step,
+ Step / Res.Bounds.D (Dim + 1).Length,
+ Dim + 1, Nbr_Dim, El_Type);
+ when Iir_Kind_String_Literal
+ | Iir_Kind_Bit_String_Literal =>
+ pragma Assert (Dim + 1 = Nbr_Dim);
+ Val := String_To_Enumeration_Array_1 (Value, El_Type);
+ if Val.Val_Array.Len /= Res.Bounds.D (Nbr_Dim).Length then
+ Error_Msg_Constraint (Value);
+ end if;
+ for I in Val.Val_Array.V'Range loop
+ Res.Val_Array.V (Orig + Pos * Step + I) :=
+ Val.Val_Array.V (I);
+ end loop;
+ when others =>
+ Error_Kind ("fill_array_aggregate_1", Value);
+ end case;
+ end if;
+ end Set_Elem;
+
+ procedure Set_Elem_By_Expr (Expr : Iir)
+ is
+ Expr_Pos: Iir_Value_Literal_Acc;
+ begin
+ Expr_Pos := Execute_Expression (Block, Expr);
+ Set_Elem (Get_Index_Offset (Expr_Pos, Bound, Expr));
+ end Set_Elem_By_Expr;
+
+ procedure Set_Elem_By_Range (Expr : Iir)
+ is
+ A_Range : Iir_Value_Literal_Acc;
+ High, Low : Iir_Value_Literal_Acc;
+ begin
+ A_Range := Execute_Bounds (Block, Expr);
+ if Is_Nul_Range (A_Range) then
+ return;
+ end if;
+ if A_Range.Dir = Iir_To then
+ High := A_Range.Right;
+ Low := A_Range.Left;
+ else
+ High := A_Range.Left;
+ Low := A_Range.Right;
+ end if;
+
+ -- Locally modified (incremented)
+ Low := Unshare (Low, Expr_Pool'Access);
+
+ loop
+ Set_Elem (Get_Index_Offset (Low, Bound, Expr));
+ exit when Is_Equal (Low, High);
+ Increment (Low);
+ end loop;
+ end Set_Elem_By_Range;
+
+ Length : constant Iir_Index32 := Bound.Length;
+ Assoc : Iir;
+ Pos : Iir_Index32;
+ begin
+ Assoc := Get_Association_Choices_Chain (Aggregate);
+ Pos := 0;
+ while Assoc /= Null_Iir loop
+ Value := Get_Associated_Expr (Assoc);
+ loop
+ case Get_Kind (Assoc) is
+ when Iir_Kind_Choice_By_None =>
+ if Pos >= Length then
+ Error_Msg_Constraint (Assoc);
+ end if;
+ Set_Elem (Pos);
+ Pos := Pos + 1;
+ when Iir_Kind_Choice_By_Expression =>
+ Set_Elem_By_Expr (Get_Choice_Expression (Assoc));
+ when Iir_Kind_Choice_By_Range =>
+ Set_Elem_By_Range (Get_Choice_Range (Assoc));
+ when Iir_Kind_Choice_By_Others =>
+ for J in 1 .. Length loop
+ if Res.Val_Array.V (Orig + J * Step) = null then
+ Set_Elem (J - 1);
+ end if;
+ end loop;
+ return;
+ when others =>
+ raise Internal_Error;
+ end case;
+ Assoc := Get_Chain (Assoc);
+ exit when Assoc = Null_Iir;
+ exit when not Get_Same_Alternative_Flag (Assoc);
+ end loop;
+ end loop;
+
+ -- Check each elements have been set.
+ -- FIXME: check directly with type.
+ for J in 1 .. Length loop
+ if Res.Val_Array.V (Orig + J * Step) = null then
+ Error_Msg_Constraint (Aggregate);
+ end if;
+ end loop;
+ end Fill_Array_Aggregate_1;
+
+ -- Use expressions from (BLOCK, AGGREGATE) to fill RES.
+ procedure Fill_Array_Aggregate
+ (Block : Block_Instance_Acc;
+ Aggregate : Iir;
+ Res : Iir_Value_Literal_Acc)
+ is
+ Aggr_Type : constant Iir := Get_Type (Aggregate);
+ El_Type : constant Iir := Get_Element_Subtype (Aggr_Type);
+ Index_List : constant Iir_List := Get_Index_Subtype_List (Aggr_Type);
+ Nbr_Dim : constant Iir_Index32 :=
+ Iir_Index32 (Get_Nbr_Elements (Index_List));
+ Step : Iir_Index32;
+ begin
+ Step := Get_Step_For_Dim (Res, 1);
+ Fill_Array_Aggregate_1
+ (Block, Aggregate, Res, 0, Step, 1, Nbr_Dim, El_Type);
+ end Fill_Array_Aggregate;
+
+ function Execute_Record_Aggregate (Block: Block_Instance_Acc;
+ Aggregate: Iir;
+ Aggregate_Type: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ List : constant Iir_List :=
+ Get_Elements_Declaration_List (Get_Base_Type (Aggregate_Type));
+
+ Res: Iir_Value_Literal_Acc;
+ Expr : Iir;
+
+ procedure Set_Expr (Pos : Iir_Index32) is
+ El : constant Iir := Get_Nth_Element (List, Natural (Pos - 1));
+ begin
+ Res.Val_Record.V (Pos) :=
+ Execute_Expression_With_Type (Block, Expr, Get_Type (El));
+ end Set_Expr;
+
+ Pos : Iir_Index32;
+ Assoc: Iir;
+ N_Expr : Iir;
+ begin
+ Res := Create_Record_Value (Iir_Index32 (Get_Nbr_Elements (List)));
+
+ Assoc := Get_Association_Choices_Chain (Aggregate);
+ Pos := 1;
+ loop
+ N_Expr := Get_Associated_Expr (Assoc);
+ if N_Expr /= Null_Iir then
+ Expr := N_Expr;
+ end if;
+ case Get_Kind (Assoc) is
+ when Iir_Kind_Choice_By_None =>
+ Set_Expr (Pos);
+ Pos := Pos + 1;
+ when Iir_Kind_Choice_By_Name =>
+ Set_Expr (1 + Get_Element_Position (Get_Choice_Name (Assoc)));
+ when Iir_Kind_Choice_By_Others =>
+ for I in Res.Val_Record.V'Range loop
+ if Res.Val_Record.V (I) = null then
+ Set_Expr (I);
+ end if;
+ end loop;
+ when others =>
+ Error_Kind ("execute_record_aggregate", Assoc);
+ end case;
+ Assoc := Get_Chain (Assoc);
+ exit when Assoc = Null_Iir;
+ end loop;
+ return Res;
+ end Execute_Record_Aggregate;
+
+ function Execute_Aggregate
+ (Block: Block_Instance_Acc;
+ Aggregate: Iir;
+ Aggregate_Type: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ begin
+ case Get_Kind (Aggregate_Type) is
+ when Iir_Kind_Array_Type_Definition
+ | Iir_Kind_Array_Subtype_Definition =>
+ declare
+ Res : Iir_Value_Literal_Acc;
+ begin
+ Res := Create_Array_Bounds_From_Type
+ (Block, Aggregate_Type, True);
+ Fill_Array_Aggregate (Block, Aggregate, Res);
+ return Res;
+ end;
+ when Iir_Kind_Record_Type_Definition
+ | Iir_Kind_Record_Subtype_Definition =>
+ return Execute_Record_Aggregate
+ (Block, Aggregate, Aggregate_Type);
+ when others =>
+ Error_Kind ("execute_aggregate", Aggregate_Type);
+ end case;
+ end Execute_Aggregate;
+
+ function Execute_Simple_Aggregate (Block: Block_Instance_Acc; Aggr : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Res : Iir_Value_Literal_Acc;
+ List : constant Iir_List := Get_Simple_Aggregate_List (Aggr);
+ begin
+ Res := Create_Array_Bounds_From_Type (Block, Get_Type (Aggr), True);
+ for I in Res.Val_Array.V'Range loop
+ Res.Val_Array.V (I) :=
+ Execute_Expression (Block, Get_Nth_Element (List, Natural (I - 1)));
+ end loop;
+ return Res;
+ end Execute_Simple_Aggregate;
+
+ -- Fill LENGTH elements of RES, starting at ORIG by steps of STEP.
+ -- Use expressions from (BLOCK, AGGREGATE) to fill the elements.
+ -- EL_TYPE is the type of the array element.
+ procedure Execute_Name_Array_Aggregate
+ (Block : Block_Instance_Acc;
+ Aggregate : Iir;
+ Res : Iir_Value_Literal_Acc;
+ Orig : Iir_Index32;
+ Step : Iir_Index32;
+ Dim : Iir_Index32;
+ Nbr_Dim : Iir_Index32;
+ El_Type : Iir)
+ is
+ Value : Iir;
+ Bound : Iir_Value_Literal_Acc;
+
+ procedure Set_Elem (Pos : Iir_Index32)
+ is
+ Val : Iir_Value_Literal_Acc;
+ Is_Sig : Boolean;
+ begin
+ if Dim = Nbr_Dim then
+ -- VALUE is an expression (which may be an aggregate, but not
+ -- a sub-aggregate.
+ Execute_Name_With_Base (Block, Value, null, Val, Is_Sig);
+ Res.Val_Array.V (1 + Orig + Pos * Step) := Val;
+ else
+ -- VALUE is a sub-aggregate.
+ Execute_Name_Array_Aggregate
+ (Block, Value, Res,
+ Orig + Pos * Step,
+ Step / Res.Bounds.D (Dim + 1).Length,
+ Dim + 1, Nbr_Dim, El_Type);
+ end if;
+ end Set_Elem;
+
+ Assoc : Iir;
+ Pos : Iir_Index32;
+ begin
+ Assoc := Get_Association_Choices_Chain (Aggregate);
+ Bound := Res.Bounds.D (Dim);
+ Pos := 0;
+ while Assoc /= Null_Iir loop
+ Value := Get_Associated_Expr (Assoc);
+ case Get_Kind (Assoc) is
+ when Iir_Kind_Choice_By_None =>
+ null;
+ when Iir_Kind_Choice_By_Expression =>
+ declare
+ Expr_Pos: Iir_Value_Literal_Acc;
+ Val : constant Iir := Get_Expression (Assoc);
+ begin
+ Expr_Pos := Execute_Expression (Block, Val);
+ Pos := Get_Index_Offset (Expr_Pos, Bound, Val);
+ end;
+ when others =>
+ raise Internal_Error;
+ end case;
+ Set_Elem (Pos);
+ Pos := Pos + 1;
+ Assoc := Get_Chain (Assoc);
+ end loop;
+ end Execute_Name_Array_Aggregate;
+
+ function Execute_Record_Name_Aggregate
+ (Block: Block_Instance_Acc;
+ Aggregate: Iir;
+ Aggregate_Type: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ List : constant Iir_List :=
+ Get_Elements_Declaration_List (Get_Base_Type (Aggregate_Type));
+ Res: Iir_Value_Literal_Acc;
+ Expr : Iir;
+ Pos : Iir_Index32;
+ El_Pos : Iir_Index32;
+ Is_Sig : Boolean;
+ Assoc: Iir;
+ begin
+ Res := Create_Record_Value (Iir_Index32 (Get_Nbr_Elements (List)));
+ Assoc := Get_Association_Choices_Chain (Aggregate);
+ Pos := 0;
+ loop
+ Expr := Get_Associated_Expr (Assoc);
+ if Expr = Null_Iir then
+ -- List of choices is not allowed.
+ raise Internal_Error;
+ end if;
+ case Get_Kind (Assoc) is
+ when Iir_Kind_Choice_By_None =>
+ El_Pos := Pos;
+ Pos := Pos + 1;
+ when Iir_Kind_Choice_By_Name =>
+ El_Pos := Get_Element_Position (Get_Name (Assoc));
+ when Iir_Kind_Choice_By_Others =>
+ raise Internal_Error;
+ when others =>
+ Error_Kind ("execute_record_name_aggregate", Assoc);
+ end case;
+ Execute_Name_With_Base
+ (Block, Expr, null, Res.Val_Record.V (1 + El_Pos), Is_Sig);
+ Assoc := Get_Chain (Assoc);
+ exit when Assoc = Null_Iir;
+ end loop;
+ return Res;
+ end Execute_Record_Name_Aggregate;
+
+ function Execute_Name_Aggregate
+ (Block: Block_Instance_Acc;
+ Aggregate: Iir;
+ Aggregate_Type: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ begin
+ case Get_Kind (Aggregate_Type) is
+ when Iir_Kind_Array_Type_Definition
+ | Iir_Kind_Array_Subtype_Definition =>
+ declare
+ Res : Iir_Value_Literal_Acc;
+ El_Type : constant Iir := Get_Element_Subtype (Aggregate_Type);
+ Index_List : constant Iir_List :=
+ Get_Index_Subtype_List (Aggregate_Type);
+ Nbr_Dim : constant Iir_Index32 :=
+ Iir_Index32 (Get_Nbr_Elements (Index_List));
+ Step : Iir_Index32;
+ begin
+ Res := Create_Array_Bounds_From_Type
+ (Block, Aggregate_Type, True);
+ Step := Get_Step_For_Dim (Res, 1);
+ Execute_Name_Array_Aggregate
+ (Block, Aggregate, Res, 0, Step, 1, Nbr_Dim, El_Type);
+ return Res;
+ end;
+ when Iir_Kind_Record_Type_Definition
+ | Iir_Kind_Record_Subtype_Definition =>
+ return Execute_Record_Name_Aggregate
+ (Block, Aggregate, Aggregate_Type);
+ when others =>
+ Error_Kind ("execute_name_aggregate", Aggregate_Type);
+ end case;
+ end Execute_Name_Aggregate;
+
+ -- Return the indexes range of dimension DIM for type or object PREFIX.
+ -- DIM starts at 1.
+ function Execute_Indexes
+ (Block: Block_Instance_Acc; Prefix: Iir; Dim : Iir_Int64)
+ return Iir_Value_Literal_Acc
+ is
+ begin
+ case Get_Kind (Prefix) is
+ when Iir_Kind_Type_Declaration
+ | Iir_Kind_Subtype_Declaration =>
+ declare
+ Index : Iir;
+ begin
+ Index := Get_Nth_Element
+ (Get_Index_Subtype_List (Get_Type (Prefix)),
+ Natural (Dim - 1));
+ return Execute_Bounds (Block, Index);
+ end;
+ when Iir_Kinds_Denoting_Name =>
+ return Execute_Indexes (Block, Get_Named_Entity (Prefix), Dim);
+ when Iir_Kind_Array_Type_Definition
+ | Iir_Kind_Array_Subtype_Definition =>
+ Error_Kind ("execute_indexes", Prefix);
+ when others =>
+ declare
+ Orig : Iir_Value_Literal_Acc;
+ begin
+ Orig := Execute_Name (Block, Prefix, True);
+ return Orig.Bounds.D (Iir_Index32 (Dim));
+ end;
+ end case;
+ end Execute_Indexes;
+
+ function Execute_Bounds (Block: Block_Instance_Acc; Prefix: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Bound : Iir_Value_Literal_Acc;
+ begin
+ case Get_Kind (Prefix) is
+ when Iir_Kind_Range_Expression =>
+ declare
+ Info : constant Sim_Info_Acc := Get_Info (Prefix);
+ begin
+ if Info = null then
+ Bound := Create_Range_Value
+ (Execute_Expression (Block, Get_Left_Limit (Prefix)),
+ Execute_Expression (Block, Get_Right_Limit (Prefix)),
+ Get_Direction (Prefix));
+ elsif Info.Kind = Kind_Object then
+ Bound := Get_Instance_For_Slot
+ (Block, Prefix).Objects (Info.Slot);
+ else
+ raise Internal_Error;
+ end if;
+ end;
+
+ when Iir_Kind_Subtype_Declaration =>
+ return Execute_Bounds (Block, Get_Type (Prefix));
+
+ when Iir_Kind_Integer_Subtype_Definition
+ | Iir_Kind_Floating_Subtype_Definition
+ | Iir_Kind_Enumeration_Subtype_Definition
+ | Iir_Kind_Enumeration_Type_Definition
+ | Iir_Kind_Physical_Subtype_Definition =>
+ -- FIXME: move this block before and avoid recursion.
+ return Execute_Bounds (Block, Get_Range_Constraint (Prefix));
+
+ when Iir_Kind_Range_Array_Attribute =>
+ declare
+ Prefix_Val : Iir_Value_Literal_Acc;
+ Dim : Iir_Int64;
+ begin
+ Dim := Get_Value (Get_Parameter (Prefix));
+ Prefix_Val := Execute_Indexes (Block, Get_Prefix (Prefix), Dim);
+ Bound := Prefix_Val;
+ end;
+ when Iir_Kind_Reverse_Range_Array_Attribute =>
+ declare
+ Dim : Iir_Int64;
+ begin
+ Dim := Get_Value (Get_Parameter (Prefix));
+ Bound := Execute_Indexes (Block, Get_Prefix (Prefix), Dim);
+ case Bound.Dir is
+ when Iir_To =>
+ Bound := Create_Range_Value
+ (Bound.Right, Bound.Left, Iir_Downto, Bound.Length);
+ when Iir_Downto =>
+ Bound := Create_Range_Value
+ (Bound.Right, Bound.Left, Iir_To, Bound.Length);
+ end case;
+ end;
+
+ when Iir_Kind_Floating_Type_Definition
+ | Iir_Kind_Integer_Type_Definition =>
+ return Execute_Bounds
+ (Block,
+ Get_Range_Constraint (Get_Type (Get_Type_Declarator (Prefix))));
+
+ when Iir_Kinds_Denoting_Name =>
+ return Execute_Bounds (Block, Get_Named_Entity (Prefix));
+
+ when others =>
+ -- Error_Kind ("execute_bounds", Get_Kind (Prefix));
+ declare
+ Prefix_Val: Iir_Value_Literal_Acc;
+ begin
+ Prefix_Val := Execute_Expression (Block, Prefix);
+ Bound := Prefix_Val.Bounds.D (1);
+ end;
+ end case;
+ if not Bound.Dir'Valid then
+ raise Internal_Error;
+ end if;
+ return Bound;
+ end Execute_Bounds;
+
+ -- Perform type conversion as desribed in LRM93 7.3.5
+ function Execute_Type_Conversion (Block: Block_Instance_Acc;
+ Conv : Iir_Type_Conversion;
+ Val : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc
+ is
+ Target_Type : constant Iir := Get_Type (Conv);
+ Res: Iir_Value_Literal_Acc;
+ begin
+ Res := Val;
+ case Get_Kind (Target_Type) is
+ when Iir_Kind_Integer_Type_Definition
+ | Iir_Kind_Integer_Subtype_Definition =>
+ case Res.Kind is
+ when Iir_Value_I64 =>
+ null;
+ when Iir_Value_F64 =>
+ if Res.F64 > Ghdl_F64 (Iir_Int64'Last) or
+ Res.F64 < Ghdl_F64 (Iir_Int64'First)
+ then
+ Error_Msg_Constraint (Conv);
+ end if;
+ Res := Create_I64_Value (Ghdl_I64 (Res.F64));
+ when Iir_Value_B1
+ | Iir_Value_E32
+ | Iir_Value_Range
+ | Iir_Value_Array
+ | Iir_Value_Signal
+ | Iir_Value_Record
+ | Iir_Value_Access
+ | Iir_Value_File
+ | Iir_Value_Protected
+ | Iir_Value_Quantity
+ | Iir_Value_Terminal =>
+ -- These values are not of abstract numeric type.
+ raise Internal_Error;
+ end case;
+ when Iir_Kind_Floating_Type_Definition
+ | Iir_Kind_Floating_Subtype_Definition =>
+ case Res.Kind is
+ when Iir_Value_F64 =>
+ null;
+ when Iir_Value_I64 =>
+ Res := Create_F64_Value (Ghdl_F64 (Res.I64));
+ when Iir_Value_B1
+ | Iir_Value_E32
+ | Iir_Value_Range
+ | Iir_Value_Array
+ | Iir_Value_Signal
+ | Iir_Value_Record
+ | Iir_Value_Access
+ | Iir_Value_File
+ | Iir_Value_Protected
+ | Iir_Value_Quantity
+ | Iir_Value_Terminal =>
+ -- These values are not of abstract numeric type.
+ raise Internal_Error;
+ end case;
+ when Iir_Kind_Enumeration_Type_Definition
+ | Iir_Kind_Enumeration_Subtype_Definition =>
+ -- must be same type.
+ null;
+ when Iir_Kind_Array_Type_Definition =>
+ -- LRM93 7.3.5
+ -- if the type mark denotes an unconstrained array type and the
+ -- operand is not a null array, then for each index position, the
+ -- bounds of the result are obtained by converting the bounds of
+ -- the operand to the corresponding index type of the target type.
+ -- FIXME: what is bound conversion ??
+ null;
+ when Iir_Kind_Array_Subtype_Definition =>
+ -- LRM93 7.3.5
+ -- If the type mark denotes a constrained array subtype, then the
+ -- bounds of the result are those imposed by the type mark.
+ Implicit_Array_Conversion (Block, Res, Target_Type, Conv);
+ when others =>
+ Error_Kind ("execute_type_conversion", Target_Type);
+ end case;
+ Check_Constraints (Block, Res, Target_Type, Conv);
+ return Res;
+ end Execute_Type_Conversion;
+
+ -- Decrement VAL.
+ -- May raise a constraint error using EXPR.
+ function Execute_Dec (Val : Iir_Value_Literal_Acc; Expr : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Res : Iir_Value_Literal_Acc;
+ begin
+ case Val.Kind is
+ when Iir_Value_B1 =>
+ if Val.B1 = False then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Res := Create_B1_Value (False);
+ when Iir_Value_E32 =>
+ if Val.E32 = 0 then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Res := Create_E32_Value (Val.E32 - 1);
+ when Iir_Value_I64 =>
+ if Val.I64 = Ghdl_I64'First then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Res := Create_I64_Value (Val.I64 - 1);
+ when others =>
+ raise Internal_Error;
+ end case;
+ return Res;
+ end Execute_Dec;
+
+ -- Increment VAL.
+ -- May raise a constraint error using EXPR.
+ function Execute_Inc (Val : Iir_Value_Literal_Acc; Expr : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Res : Iir_Value_Literal_Acc;
+ begin
+ case Val.Kind is
+ when Iir_Value_B1 =>
+ if Val.B1 = True then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Res := Create_B1_Value (True);
+ when Iir_Value_E32 =>
+ if Val.E32 = Ghdl_E32'Last then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Res := Create_E32_Value (Val.E32 + 1);
+ when Iir_Value_I64 =>
+ if Val.I64 = Ghdl_I64'Last then
+ Error_Msg_Constraint (Expr);
+ end if;
+ Res := Create_I64_Value (Val.I64 + 1);
+ when others =>
+ raise Internal_Error;
+ end case;
+ return Res;
+ end Execute_Inc;
+
+ function Execute_Expression_With_Type
+ (Block: Block_Instance_Acc;
+ Expr: Iir;
+ Expr_Type : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Res : Iir_Value_Literal_Acc;
+ begin
+ if Get_Kind (Expr) = Iir_Kind_Aggregate
+ and then not Is_Fully_Constrained_Type (Get_Type (Expr))
+ then
+ return Execute_Aggregate (Block, Expr, Expr_Type);
+ else
+ Res := Execute_Expression (Block, Expr);
+ Implicit_Array_Conversion (Block, Res, Expr_Type, Expr);
+ Check_Constraints (Block, Res, Expr_Type, Expr);
+ return Res;
+ end if;
+ end Execute_Expression_With_Type;
+
+ function Execute_Signal_Init_Value (Block : Block_Instance_Acc; Expr : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Base : constant Iir := Get_Object_Prefix (Expr);
+ Info : constant Sim_Info_Acc := Get_Info (Base);
+ Bblk : Block_Instance_Acc;
+ Base_Val : Iir_Value_Literal_Acc;
+ Res : Iir_Value_Literal_Acc;
+ Is_Sig : Boolean;
+ begin
+ Bblk := Get_Instance_By_Scope_Level (Block, Info.Scope_Level);
+ Base_Val := Bblk.Objects (Info.Slot + 1);
+ Execute_Name_With_Base (Block, Expr, Base_Val, Res, Is_Sig);
+ pragma Assert (Is_Sig);
+ return Res;
+ end Execute_Signal_Init_Value;
+
+ procedure Execute_Name_With_Base (Block: Block_Instance_Acc;
+ Expr: Iir;
+ Base : Iir_Value_Literal_Acc;
+ Res : out Iir_Value_Literal_Acc;
+ Is_Sig : out Boolean)
+ is
+ Slot_Block: Block_Instance_Acc;
+ begin
+ -- Default value
+ Is_Sig := False;
+
+ case Get_Kind (Expr) is
+ when Iir_Kind_Signal_Interface_Declaration
+ | Iir_Kind_Signal_Declaration
+ | Iir_Kind_Guard_Signal_Declaration
+ | Iir_Kind_Stable_Attribute
+ | Iir_Kind_Quiet_Attribute
+ | Iir_Kind_Delayed_Attribute
+ | Iir_Kind_Transaction_Attribute =>
+ Is_Sig := True;
+ if Base /= null then
+ Res := Base;
+ else
+ Slot_Block := Get_Instance_For_Slot (Block, Expr);
+ Res := Slot_Block.Objects (Get_Info (Expr).Slot);
+ end if;
+
+ when Iir_Kind_Object_Alias_Declaration =>
+ pragma Assert (Base = null);
+ -- FIXME: add a flag ?
+ case Get_Kind (Get_Object_Prefix (Expr)) is
+ when Iir_Kind_Signal_Declaration
+ | Iir_Kind_Signal_Interface_Declaration
+ | Iir_Kind_Guard_Signal_Declaration =>
+ Is_Sig := True;
+ when others =>
+ Is_Sig := False;
+ end case;
+ Slot_Block := Get_Instance_For_Slot (Block, Expr);
+ Res := Slot_Block.Objects (Get_Info (Expr).Slot);
+
+ when Iir_Kind_Constant_Interface_Declaration
+ | Iir_Kind_Constant_Declaration
+ | Iir_Kind_Variable_Interface_Declaration
+ | Iir_Kind_Variable_Declaration
+ | Iir_Kind_File_Interface_Declaration
+ | Iir_Kind_File_Declaration
+ | Iir_Kind_Attribute_Value
+ | Iir_Kind_Iterator_Declaration
+ | Iir_Kind_Terminal_Declaration
+ | Iir_Kinds_Quantity_Declaration =>
+ if Base /= null then
+ Res := Base;
+ else
+ declare
+ Info : constant Sim_Info_Acc := Get_Info (Expr);
+ begin
+ Slot_Block :=
+ Get_Instance_By_Scope_Level (Block, Info.Scope_Level);
+ Res := Slot_Block.Objects (Info.Slot);
+ end;
+ end if;
+
+ when Iir_Kind_Indexed_Name =>
+ declare
+ Prefix: Iir;
+ Index_List: Iir_List;
+ Index: Iir;
+ Nbr_Dimensions: Iir_Index32;
+ Value: Iir_Value_Literal_Acc;
+ Pfx: Iir_Value_Literal_Acc;
+ Pos, Off : Iir_Index32;
+ begin
+ Prefix := Get_Prefix (Expr);
+ Index_List := Get_Index_List (Expr);
+ Nbr_Dimensions := Iir_Index32 (Get_Nbr_Elements (Index_List));
+ Execute_Name_With_Base (Block, Prefix, Base, Pfx, Is_Sig);
+ for I in 1 .. Nbr_Dimensions loop
+ Index := Get_Nth_Element (Index_List, Natural (I - 1));
+ Value := Execute_Expression (Block, Index);
+ Off := Get_Index_Offset (Value, Pfx.Bounds.D (I), Expr);
+ if I = 1 then
+ Pos := Off;
+ else
+ Pos := Pos * Pfx.Bounds.D (I).Length + Off;
+ end if;
+ end loop;
+ Res := Pfx.Val_Array.V (1 + Pos);
+ -- FIXME: free PFX.
+ end;
+
+ when Iir_Kind_Slice_Name =>
+ declare
+ Prefix: Iir;
+ Prefix_Array: Iir_Value_Literal_Acc;
+
+ Srange : Iir_Value_Literal_Acc;
+ Index_Order : Order;
+ -- Lower and upper bounds of the slice.
+ Low, High: Iir_Index32;
+ begin
+ Srange := Execute_Bounds (Block, Get_Suffix (Expr));
+
+ Prefix := Get_Prefix (Expr);
+
+ Execute_Name_With_Base
+ (Block, Prefix, Base, Prefix_Array, Is_Sig);
+ if Prefix_Array = null then
+ raise Internal_Error;
+ end if;
+
+ -- LRM93 6.5
+ -- It is an error if the direction of the discrete range is not
+ -- the same as that of the index range of the array denoted by
+ -- the prefix of the slice name.
+ if Srange.Dir /= Prefix_Array.Bounds.D (1).Dir then
+ Error_Msg_Exec ("slice direction mismatch", Expr);
+ end if;
+
+ -- LRM93 6.5
+ -- It is an error if either of the bounds of the
+ -- discrete range does not belong to the index range of the
+ -- prefixing array, unless the slice is a null slice.
+ Index_Order := Compare_Value (Srange.Left, Srange.Right);
+ if (Srange.Dir = Iir_To and Index_Order = Greater)
+ or (Srange.Dir = Iir_Downto and Index_Order = Less)
+ then
+ -- Null slice.
+ Low := 1;
+ High := 0;
+ else
+ Low := Get_Index_Offset
+ (Srange.Left, Prefix_Array.Bounds.D (1), Expr);
+ High := Get_Index_Offset
+ (Srange.Right, Prefix_Array.Bounds.D (1), Expr);
+ end if;
+ Res := Create_Array_Value (High - Low + 1, 1);
+ Res.Bounds.D (1) := Srange;
+ for I in Low .. High loop
+ Res.Val_Array.V (1 + I - Low) :=
+ Prefix_Array.Val_Array.V (1 + I);
+ end loop;
+ end;
+
+ when Iir_Kind_Selected_Element =>
+ declare
+ Prefix: Iir_Value_Literal_Acc;
+ Pos: Iir_Index32;
+ begin
+ Execute_Name_With_Base
+ (Block, Get_Prefix (Expr), Base, Prefix, Is_Sig);
+ Pos := Get_Element_Position (Get_Selected_Element (Expr));
+ Res := Prefix.Val_Record.V (Pos + 1);
+ end;
+
+ when Iir_Kind_Dereference
+ | Iir_Kind_Implicit_Dereference =>
+ declare
+ Prefix: Iir_Value_Literal_Acc;
+ begin
+ Prefix := Execute_Name (Block, Get_Prefix (Expr));
+ Res := Prefix.Val_Access;
+ if Res = null then
+ Error_Msg_Exec ("deferencing null access", Expr);
+ end if;
+ end;
+
+ when Iir_Kinds_Denoting_Name
+ | Iir_Kind_Attribute_Name =>
+ Execute_Name_With_Base
+ (Block, Get_Named_Entity (Expr), Base, Res, Is_Sig);
+
+ when Iir_Kind_Function_Call =>
+ -- A prefix can be an expression
+ if Base /= null then
+ raise Internal_Error;
+ end if;
+ Res := Execute_Expression (Block, Expr);
+
+ when Iir_Kind_Aggregate =>
+ Res := Execute_Name_Aggregate (Block, Expr, Get_Type (Expr));
+ -- FIXME: is_sig ?
+
+ when others =>
+ Error_Kind ("execute_name_with_base", Expr);
+ end case;
+ end Execute_Name_With_Base;
+
+ function Execute_Name (Block: Block_Instance_Acc;
+ Expr: Iir;
+ Ref : Boolean := False)
+ return Iir_Value_Literal_Acc
+ is
+ Res: Iir_Value_Literal_Acc;
+ Is_Sig : Boolean;
+ begin
+ Execute_Name_With_Base (Block, Expr, null, Res, Is_Sig);
+ if not Is_Sig or else Ref then
+ return Res;
+ else
+ return Execute_Signal_Value (Res);
+ end if;
+ end Execute_Name;
+
+ function Execute_Image_Attribute (Block: Block_Instance_Acc; Expr: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Val : Iir_Value_Literal_Acc;
+ Attr_Type : constant Iir := Get_Type (Get_Prefix (Expr));
+ begin
+ Val := Execute_Expression (Block, Get_Parameter (Expr));
+ return String_To_Iir_Value
+ (Execute_Image_Attribute (Val, Attr_Type));
+ end Execute_Image_Attribute;
+
+ function Execute_Value_Attribute (Block: Block_Instance_Acc;
+ Str_Val : Iir_Value_Literal_Acc;
+ Expr: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ use Grt_Interface;
+ use Name_Table;
+ pragma Unreferenced (Block);
+
+ Expr_Type : constant Iir := Get_Type (Expr);
+ Res : Iir_Value_Literal_Acc;
+
+ Str_Bnd : aliased Std_String_Bound := Build_Bound (Str_Val);
+ Str_Str : aliased Std_String_Uncons (1 .. Str_Bnd.Dim_1.Length);
+ Str : aliased Std_String := (To_Std_String_Basep (Str_Str'Address),
+ To_Std_String_Boundp (Str_Bnd'Address));
+ begin
+ Set_Std_String_From_Iir_Value (Str, Str_Val);
+ case Get_Kind (Expr_Type) is
+ when Iir_Kind_Integer_Type_Definition
+ | Iir_Kind_Integer_Subtype_Definition =>
+ Res := Create_I64_Value
+ (Grt.Values.Ghdl_Value_I64 (Str'Unrestricted_Access));
+ when Iir_Kind_Floating_Type_Definition
+ | Iir_Kind_Floating_Subtype_Definition =>
+ Res := Create_F64_Value
+ (Grt.Values.Ghdl_Value_F64 (Str'Unrestricted_Access));
+ when Iir_Kind_Physical_Type_Definition
+ | Iir_Kind_Physical_Subtype_Definition =>
+ declare
+ Is_Real : Boolean;
+ Lit_Pos : Ghdl_Index_Type;
+ Lit_End : Ghdl_Index_Type;
+ Unit_Pos : Ghdl_Index_Type;
+ Unit_Len : Ghdl_Index_Type;
+ Mult : Ghdl_I64;
+ Unit : Iir;
+ Unit_Id : Name_Id;
+ begin
+ Grt.Values.Ghdl_Value_Physical_Split
+ (Str'Unrestricted_Access,
+ Is_Real, Lit_Pos, Lit_End, Unit_Pos);
+
+ -- Find unit.
+ Unit_Len := 0;
+ Unit_Pos := Unit_Pos + 1; -- From 0 based to 1 based
+ for I in Unit_Pos .. Str_Bnd.Dim_1.Length loop
+ exit when Grt.Values.Is_Whitespace (Str_Str (I));
+ Unit_Len := Unit_Len + 1;
+ Str_Str (I) := Grt.Values.To_LC (Str_Str (I));
+ end loop;
+
+ Unit := Get_Primary_Unit (Expr_Type);
+ while Unit /= Null_Iir loop
+ Unit_Id := Get_Identifier (Unit);
+ exit when Get_Name_Length (Unit_Id) = Natural (Unit_Len)
+ and then Image (Unit_Id) =
+ String (Str_Str (Unit_Pos .. Unit_Pos + Unit_Len - 1));
+ Unit := Get_Chain (Unit);
+ end loop;
+
+ if Unit = Null_Iir then
+ Error_Msg_Exec ("incorrect unit name", Expr);
+ end if;
+ Mult := Ghdl_I64 (Get_Value (Get_Physical_Unit_Value (Unit)));
+
+ Str_Bnd.Dim_1.Length := Lit_End;
+ if Is_Real then
+ Res := Create_I64_Value
+ (Ghdl_I64
+ (Grt.Values.Ghdl_Value_F64 (Str'Unrestricted_Access)
+ * Ghdl_F64 (Mult)));
+ else
+ Res := Create_I64_Value
+ (Grt.Values.Ghdl_Value_I64 (Str'Unrestricted_Access)
+ * Mult);
+ end if;
+ end;
+ when Iir_Kind_Enumeration_Type_Definition
+ | Iir_Kind_Enumeration_Subtype_Definition =>
+ declare
+ Lit_Start : Ghdl_Index_Type;
+ Lit_End : Ghdl_Index_Type;
+ Enums : constant Iir_List :=
+ Get_Enumeration_Literal_List (Get_Base_Type (Expr_Type));
+ Enum : Iir;
+ Enum_Id : Name_Id;
+ begin
+ -- Remove leading and trailing blanks
+ for I in Str_Str'Range loop
+ if not Grt.Values.Is_Whitespace (Str_Str (I)) then
+ Lit_Start := I;
+ exit;
+ end if;
+ end loop;
+ for I in reverse Lit_Start .. Str_Str'Last loop
+ if not Grt.Values.Is_Whitespace (Str_Str (I)) then
+ Lit_End := I;
+ exit;
+ end if;
+ end loop;
+
+ -- Convert to lower case.
+ for I in Lit_Start .. Lit_End loop
+ Str_Str (I) := Grt.Values.To_LC (Str_Str (I));
+ end loop;
+
+ for I in Natural loop
+ Enum := Get_Nth_Element (Enums, I);
+ if Enum = Null_Iir then
+ Error_Msg_Exec ("incorrect unit name", Expr);
+ end if;
+ Enum_Id := Get_Identifier (Enum);
+ exit when (Get_Name_Length (Enum_Id) =
+ Natural (Lit_End - Lit_Start + 1))
+ and then (Image (Enum_Id) =
+ String (Str_Str (Lit_Start .. Lit_End)));
+ end loop;
+
+ return Create_Enum_Value
+ (Natural (Get_Enum_Pos (Enum)), Expr_Type);
+ end;
+ when others =>
+ Error_Kind ("value_attribute", Expr_Type);
+ end case;
+ return Res;
+ end Execute_Value_Attribute;
+
+ function Execute_Path_Instance_Name_Attribute
+ (Block : Block_Instance_Acc; Attr : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ use Evaluation;
+ use Grt.Vstrings;
+ use Name_Table;
+
+ Name : constant Path_Instance_Name_Type :=
+ Get_Path_Instance_Name_Suffix (Attr);
+ Instance : Block_Instance_Acc;
+ Rstr : Rstring;
+ Is_Instance : constant Boolean :=
+ Get_Kind (Attr) = Iir_Kind_Instance_Name_Attribute;
+ begin
+ if Name.Path_Instance = Null_Iir then
+ return String_To_Iir_Value (Name.Suffix);
+ end if;
+
+ Instance := Get_Instance_By_Scope_Level
+ (Block, Get_Info (Name.Path_Instance).Frame_Scope_Level);
+
+ loop
+ case Get_Kind (Instance.Label) is
+ when Iir_Kind_Entity_Declaration =>
+ if Instance.Parent = null then
+ Prepend (Rstr, Image (Get_Identifier (Instance.Label)));
+ exit;
+ end if;
+ when Iir_Kind_Architecture_Body =>
+ if Is_Instance then
+ Prepend (Rstr, ')');
+ Prepend (Rstr, Image (Get_Identifier (Instance.Label)));
+ Prepend (Rstr, '(');
+ end if;
+
+ if Is_Instance or else Instance.Parent = null then
+ Prepend
+ (Rstr,
+ Image (Get_Identifier (Get_Entity (Instance.Label))));
+ end if;
+ if Instance.Parent = null then
+ Prepend (Rstr, ':');
+ exit;
+ else
+ Instance := Instance.Parent;
+ end if;
+ when Iir_Kind_Block_Statement =>
+ Prepend (Rstr, Image (Get_Label (Instance.Label)));
+ Prepend (Rstr, ':');
+ Instance := Instance.Parent;
+ when Iir_Kind_Iterator_Declaration =>
+ declare
+ Val : Iir_Value_Literal_Acc;
+ begin
+ Val := Execute_Name (Instance, Instance.Label);
+ Prepend (Rstr, ')');
+ Prepend (Rstr, Execute_Image_Attribute
+ (Val, Get_Type (Instance.Label)));
+ Prepend (Rstr, '(');
+ end;
+ Instance := Instance.Parent;
+ when Iir_Kind_Generate_Statement =>
+ Prepend (Rstr, Image (Get_Label (Instance.Label)));
+ Prepend (Rstr, ':');
+ Instance := Instance.Parent;
+ when Iir_Kind_Component_Instantiation_Statement =>
+ if Is_Instance then
+ Prepend (Rstr, '@');
+ end if;
+ Prepend (Rstr, Image (Get_Label (Instance.Label)));
+ Prepend (Rstr, ':');
+ Instance := Instance.Parent;
+ when others =>
+ Error_Kind ("Execute_Path_Instance_Name_Attribute",
+ Instance.Label);
+ end case;
+ end loop;
+ declare
+ Str1 : String (1 .. Length (Rstr));
+ Len1 : Natural;
+ begin
+ Copy (Rstr, Str1, Len1);
+ Free (Rstr);
+ return String_To_Iir_Value (Str1 & ':' & Name.Suffix);
+ end;
+ end Execute_Path_Instance_Name_Attribute;
+
+ -- For 'Last_Event and 'Last_Active: convert the absolute last time to
+ -- a relative delay.
+ function To_Relative_Time (T : Ghdl_I64) return Iir_Value_Literal_Acc is
+ A : Ghdl_I64;
+ begin
+ if T = -Ghdl_I64'Last then
+ A := Ghdl_I64'Last;
+ else
+ A := Ghdl_I64 (Grt.Types.Current_Time) - T;
+ end if;
+ return Create_I64_Value (A);
+ end To_Relative_Time;
+
+ -- Evaluate an expression.
+ function Execute_Expression (Block: Block_Instance_Acc; Expr: Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Res: Iir_Value_Literal_Acc;
+ begin
+ case Get_Kind (Expr) is
+ when Iir_Kind_Signal_Interface_Declaration
+ | Iir_Kind_Signal_Declaration
+ | Iir_Kind_Guard_Signal_Declaration
+ | Iir_Kind_Stable_Attribute
+ | Iir_Kind_Quiet_Attribute
+ | Iir_Kind_Delayed_Attribute
+ | Iir_Kind_Transaction_Attribute
+ | Iir_Kind_Object_Alias_Declaration =>
+ Res := Execute_Name (Block, Expr);
+ return Res;
+
+ when Iir_Kind_Constant_Interface_Declaration
+ | Iir_Kind_Constant_Declaration
+ | Iir_Kind_Variable_Interface_Declaration
+ | Iir_Kind_Variable_Declaration
+ | Iir_Kind_File_Interface_Declaration
+ | Iir_Kind_File_Declaration
+ | Iir_Kind_Attribute_Value
+ | Iir_Kind_Iterator_Declaration
+ | Iir_Kind_Indexed_Name
+ | Iir_Kind_Slice_Name
+ | Iir_Kind_Selected_Element
+ | Iir_Kind_Dereference
+ | Iir_Kind_Implicit_Dereference =>
+ return Execute_Name (Block, Expr);
+
+ when Iir_Kinds_Denoting_Name
+ | Iir_Kind_Attribute_Name =>
+ return Execute_Expression (Block, Get_Named_Entity (Expr));
+
+ when Iir_Kind_Aggregate =>
+ return Execute_Aggregate (Block, Expr, Get_Type (Expr));
+ when Iir_Kind_Simple_Aggregate =>
+ return Execute_Simple_Aggregate (Block, Expr);
+
+ when Iir_Kinds_Dyadic_Operator
+ | Iir_Kinds_Monadic_Operator =>
+ declare
+ Imp : Iir;
+ begin
+ Imp := Get_Implementation (Expr);
+ if Get_Kind (Imp) = Iir_Kind_Function_Declaration then
+ return Execute_Function_Call (Block, Expr, Imp);
+ else
+ if Get_Kind (Expr) in Iir_Kinds_Dyadic_Operator then
+ Res := Execute_Implicit_Function
+ (Block, Expr, Get_Left (Expr), Get_Right (Expr),
+ Get_Type (Expr));
+ else
+ Res := Execute_Implicit_Function
+ (Block, Expr, Get_Operand (Expr), Null_Iir,
+ Get_Type (Expr));
+ end if;
+ return Res;
+ end if;
+ end;
+
+ when Iir_Kind_Function_Call =>
+ declare
+ Imp : constant Iir :=
+ Get_Named_Entity (Get_Implementation (Expr));
+ Assoc : Iir;
+ Args : Iir_Array (0 .. 1);
+ begin
+ if Get_Kind (Imp) = Iir_Kind_Function_Declaration then
+ return Execute_Function_Call (Block, Expr, Imp);
+ else
+ Assoc := Get_Parameter_Association_Chain (Expr);
+ if Assoc /= Null_Iir then
+ Args (0) := Get_Actual (Assoc);
+ Assoc := Get_Chain (Assoc);
+ else
+ Args (0) := Null_Iir;
+ end if;
+ if Assoc /= Null_Iir then
+ Args (1) := Get_Actual (Assoc);
+ else
+ Args (1) := Null_Iir;
+ end if;
+ return Execute_Implicit_Function
+ (Block, Expr, Args (0), Args (1), Get_Type (Expr));
+ end if;
+ end;
+
+ when Iir_Kind_Integer_Literal =>
+ declare
+ Lit_Type : constant Iir := Get_Base_Type (Get_Type (Expr));
+ Lit : constant Iir_Int64 := Get_Value (Expr);
+ begin
+ case Get_Info (Lit_Type).Scalar_Mode is
+ when Iir_Value_I64 =>
+ return Create_I64_Value (Ghdl_I64 (Lit));
+ when others =>
+ raise Internal_Error;
+ end case;
+ end;
+
+ when Iir_Kind_Floating_Point_Literal =>
+ return Create_F64_Value (Ghdl_F64 (Get_Fp_Value (Expr)));
+
+ when Iir_Kind_Enumeration_Literal =>
+ declare
+ Lit_Type : constant Iir := Get_Base_Type (Get_Type (Expr));
+ Lit : constant Iir_Int32 := Get_Enum_Pos (Expr);
+ begin
+ case Get_Info (Lit_Type).Scalar_Mode is
+ when Iir_Value_B1 =>
+ return Create_B1_Value (Ghdl_B1'Val (Lit));
+ when Iir_Value_E32 =>
+ return Create_E32_Value (Ghdl_E32 (Lit));
+ when others =>
+ raise Internal_Error;
+ end case;
+ end;
+
+ when Iir_Kind_Physical_Int_Literal
+ | Iir_Kind_Physical_Fp_Literal
+ | Iir_Kind_Unit_Declaration =>
+ return Create_I64_Value
+ (Ghdl_I64 (Evaluation.Get_Physical_Value (Expr)));
+
+ when Iir_Kind_String_Literal
+ | Iir_Kind_Bit_String_Literal =>
+ return String_To_Enumeration_Array (Block, Expr);
+
+ when Iir_Kind_Null_Literal =>
+ return Null_Lit;
+
+ when Iir_Kind_Overflow_Literal =>
+ Error_Msg_Constraint (Expr);
+ return null;
+
+ when Iir_Kind_Parenthesis_Expression =>
+ return Execute_Expression (Block, Get_Expression (Expr));
+
+ when Iir_Kind_Type_Conversion =>
+ return Execute_Type_Conversion
+ (Block, Expr,
+ Execute_Expression (Block, Get_Expression (Expr)));
+
+ when Iir_Kind_Qualified_Expression =>
+ Res := Execute_Expression_With_Type
+ (Block, Get_Expression (Expr), Get_Type (Get_Type_Mark (Expr)));
+ return Res;
+
+ when Iir_Kind_Allocator_By_Expression =>
+ Res := Execute_Expression (Block, Get_Expression (Expr));
+ Res := Unshare_Heap (Res);
+ return Create_Access_Value (Res);
+
+ when Iir_Kind_Allocator_By_Subtype =>
+ Res := Create_Value_For_Type
+ (Block,
+ Get_Type_Of_Subtype_Indication (Get_Subtype_Indication (Expr)),
+ True);
+ Res := Unshare_Heap (Res);
+ return Create_Access_Value (Res);
+
+ when Iir_Kind_Left_Type_Attribute =>
+ Res := Execute_Bounds (Block, Get_Prefix (Expr));
+ return Execute_Left_Limit (Res);
+
+ when Iir_Kind_Right_Type_Attribute =>
+ Res := Execute_Bounds (Block, Get_Prefix (Expr));
+ return Execute_Right_Limit (Res);
+
+ when Iir_Kind_High_Type_Attribute =>
+ Res := Execute_Bounds (Block, Get_Prefix (Expr));
+ return Execute_High_Limit (Res);
+
+ when Iir_Kind_Low_Type_Attribute =>
+ Res := Execute_Bounds (Block, Get_Prefix (Expr));
+ return Execute_Low_Limit (Res);
+
+ when Iir_Kind_High_Array_Attribute =>
+ Res := Execute_Indexes
+ (Block, Get_Prefix (Expr), Get_Value (Get_Parameter (Expr)));
+ return Execute_High_Limit (Res);
+
+ when Iir_Kind_Low_Array_Attribute =>
+ Res := Execute_Indexes
+ (Block, Get_Prefix (Expr), Get_Value (Get_Parameter (Expr)));
+ return Execute_Low_Limit (Res);
+
+ when Iir_Kind_Left_Array_Attribute =>
+ Res := Execute_Indexes
+ (Block, Get_Prefix (Expr), Get_Value (Get_Parameter (Expr)));
+ return Execute_Left_Limit (Res);
+
+ when Iir_Kind_Right_Array_Attribute =>
+ Res := Execute_Indexes
+ (Block, Get_Prefix (Expr), Get_Value (Get_Parameter (Expr)));
+ return Execute_Right_Limit (Res);
+
+ when Iir_Kind_Length_Array_Attribute =>
+ Res := Execute_Indexes
+ (Block, Get_Prefix (Expr), Get_Value (Get_Parameter (Expr)));
+ return Execute_Length (Res);
+
+ when Iir_Kind_Ascending_Array_Attribute =>
+ Res := Execute_Indexes
+ (Block, Get_Prefix (Expr), Get_Value (Get_Parameter (Expr)));
+ return Boolean_To_Lit (Res.Dir = Iir_To);
+
+ when Iir_Kind_Event_Attribute =>
+ Res := Execute_Name (Block, Get_Prefix (Expr), True);
+ return Boolean_To_Lit (Execute_Event_Attribute (Res));
+
+ when Iir_Kind_Active_Attribute =>
+ Res := Execute_Name (Block, Get_Prefix (Expr), True);
+ return Boolean_To_Lit (Execute_Active_Attribute (Res));
+
+ when Iir_Kind_Driving_Attribute =>
+ Res := Execute_Name (Block, Get_Prefix (Expr), True);
+ return Boolean_To_Lit (Execute_Driving_Attribute (Res));
+
+ when Iir_Kind_Last_Value_Attribute =>
+ Res := Execute_Name (Block, Get_Prefix (Expr), True);
+ return Execute_Last_Value_Attribute (Res);
+
+ when Iir_Kind_Driving_Value_Attribute =>
+ Res := Execute_Name (Block, Get_Prefix (Expr), True);
+ return Execute_Driving_Value_Attribute (Res);
+
+ when Iir_Kind_Last_Event_Attribute =>
+ Res := Execute_Name (Block, Get_Prefix (Expr), True);
+ return To_Relative_Time (Execute_Last_Event_Attribute (Res));
+
+ when Iir_Kind_Last_Active_Attribute =>
+ Res := Execute_Name (Block, Get_Prefix (Expr), True);
+ return To_Relative_Time (Execute_Last_Active_Attribute (Res));
+
+ when Iir_Kind_Val_Attribute =>
+ declare
+ Prefix_Type: constant Iir := Get_Type (Get_Prefix (Expr));
+ Base_Type : constant Iir := Get_Base_Type (Prefix_Type);
+ Mode : constant Iir_Value_Kind :=
+ Get_Info (Base_Type).Scalar_Mode;
+ begin
+ Res := Execute_Expression (Block, Get_Parameter (Expr));
+ case Mode is
+ when Iir_Value_I64 =>
+ null;
+ when Iir_Value_E32 =>
+ Res := Create_E32_Value (Ghdl_E32 (Res.I64));
+ when Iir_Value_B1 =>
+ Res := Create_B1_Value (Ghdl_B1'Val (Res.I64));
+ when others =>
+ Error_Kind ("execute_expression(val attribute)",
+ Prefix_Type);
+ end case;
+ Check_Constraints (Block, Res, Prefix_Type, Expr);
+ return Res;
+ end;
+
+ when Iir_Kind_Pos_Attribute =>
+ declare
+ N_Res: Iir_Value_Literal_Acc;
+ Prefix_Type: constant Iir := Get_Type (Get_Prefix (Expr));
+ Base_Type : constant Iir := Get_Base_Type (Prefix_Type);
+ Mode : constant Iir_Value_Kind :=
+ Get_Info (Base_Type).Scalar_Mode;
+ begin
+ Res := Execute_Expression (Block, Get_Parameter (Expr));
+ case Mode is
+ when Iir_Value_I64 =>
+ null;
+ when Iir_Value_B1 =>
+ N_Res := Create_I64_Value (Ghdl_B1'Pos (Res.B1));
+ Res := N_Res;
+ when Iir_Value_E32 =>
+ N_Res := Create_I64_Value (Ghdl_I64 (Res.E32));
+ Res := N_Res;
+ when others =>
+ Error_Kind ("execute_expression(pos attribute)",
+ Base_Type);
+ end case;
+ Check_Constraints (Block, Res, Get_Type (Expr), Expr);
+ return Res;
+ end;
+
+ when Iir_Kind_Succ_Attribute =>
+ Res := Execute_Expression (Block, Get_Parameter (Expr));
+ Res := Execute_Inc (Res, Expr);
+ Check_Constraints (Block, Res, Get_Type (Expr), Expr);
+ return Res;
+
+ when Iir_Kind_Pred_Attribute =>
+ Res := Execute_Expression (Block, Get_Parameter (Expr));
+ Res := Execute_Dec (Res, Expr);
+ Check_Constraints (Block, Res, Get_Type (Expr), Expr);
+ return Res;
+
+ when Iir_Kind_Leftof_Attribute =>
+ declare
+ Bound : Iir_Value_Literal_Acc;
+ begin
+ Res := Execute_Expression (Block, Get_Parameter (Expr));
+ Bound := Execute_Bounds
+ (Block, Get_Type (Get_Prefix (Expr)));
+ case Bound.Dir is
+ when Iir_To =>
+ Res := Execute_Dec (Res, Expr);
+ when Iir_Downto =>
+ Res := Execute_Inc (Res, Expr);
+ end case;
+ Check_Constraints (Block, Res, Get_Type (Expr), Expr);
+ return Res;
+ end;
+
+ when Iir_Kind_Rightof_Attribute =>
+ declare
+ Bound : Iir_Value_Literal_Acc;
+ begin
+ Res := Execute_Expression (Block, Get_Parameter (Expr));
+ Bound := Execute_Bounds
+ (Block, Get_Type (Get_Prefix (Expr)));
+ case Bound.Dir is
+ when Iir_Downto =>
+ Res := Execute_Dec (Res, Expr);
+ when Iir_To =>
+ Res := Execute_Inc (Res, Expr);
+ end case;
+ Check_Constraints (Block, Res, Get_Type (Expr), Expr);
+ return Res;
+ end;
+
+ when Iir_Kind_Image_Attribute =>
+ return Execute_Image_Attribute (Block, Expr);
+
+ when Iir_Kind_Value_Attribute =>
+ Res := Execute_Expression (Block, Get_Parameter (Expr));
+ return Execute_Value_Attribute (Block, Res, Expr);
+
+ when Iir_Kind_Path_Name_Attribute
+ | Iir_Kind_Instance_Name_Attribute =>
+ return Execute_Path_Instance_Name_Attribute (Block, Expr);
+
+ when others =>
+ Error_Kind ("execute_expression", Expr);
+ end case;
+ end Execute_Expression;
+
+ procedure Execute_Dyadic_Association
+ (Out_Block: Block_Instance_Acc;
+ In_Block: Block_Instance_Acc;
+ Expr : Iir;
+ Inter_Chain: Iir)
+ is
+ Inter: Iir;
+ Val: Iir_Value_Literal_Acc;
+ begin
+ Inter := Inter_Chain;
+ for I in 0 .. 1 loop
+ if I = 0 then
+ Val := Execute_Expression (Out_Block, Get_Left (Expr));
+ else
+ Val := Execute_Expression (Out_Block, Get_Right (Expr));
+ end if;
+ Implicit_Array_Conversion (In_Block, Val, Get_Type (Inter), Expr);
+ Check_Constraints (In_Block, Val, Get_Type (Inter), Expr);
+
+ Elaboration.Create_Object (In_Block, Inter);
+ In_Block.Objects (Get_Info (Inter).Slot) :=
+ Unshare (Val, Instance_Pool);
+ Inter := Get_Chain (Inter);
+ end loop;
+ end Execute_Dyadic_Association;
+
+ procedure Execute_Monadic_Association
+ (Out_Block: Block_Instance_Acc;
+ In_Block: Block_Instance_Acc;
+ Expr : Iir;
+ Inter: Iir)
+ is
+ Val: Iir_Value_Literal_Acc;
+ begin
+ Val := Execute_Expression (Out_Block, Get_Operand (Expr));
+ Implicit_Array_Conversion (In_Block, Val, Get_Type (Inter), Expr);
+ Check_Constraints (In_Block, Val, Get_Type (Inter), Expr);
+
+ Elaboration.Create_Object (In_Block, Inter);
+ In_Block.Objects (Get_Info (Inter).Slot) :=
+ Unshare (Val, Instance_Pool);
+ end Execute_Monadic_Association;
+
+ -- Create a block instance for subprogram IMP.
+ function Create_Subprogram_Instance (Instance : Block_Instance_Acc;
+ Imp : Iir)
+ return Block_Instance_Acc
+ is
+ Func_Info : constant Sim_Info_Acc := Get_Info (Imp);
+
+ subtype Block_Type is Block_Instance_Type (Func_Info.Nbr_Objects);
+ function To_Block_Instance_Acc is new
+ Ada.Unchecked_Conversion (System.Address, Block_Instance_Acc);
+ function Alloc_Block_Instance is new
+ Alloc_On_Pool_Addr (Block_Type);
+
+ Up_Block: Block_Instance_Acc;
+ Res : Block_Instance_Acc;
+ begin
+ Up_Block := Get_Instance_By_Scope_Level
+ (Instance, Func_Info.Frame_Scope_Level - 1);
+
+ Res := To_Block_Instance_Acc
+ (Alloc_Block_Instance
+ (Instance_Pool,
+ Block_Instance_Type'(Max_Objs => Func_Info.Nbr_Objects,
+ Scope_Level => Func_Info.Frame_Scope_Level,
+ Up_Block => Up_Block,
+ Label => Imp,
+ Stmt => Null_Iir,
+ Parent => Instance,
+ Children => null,
+ Brother => null,
+ Marker => Empty_Marker,
+ Objects => (others => null),
+ Elab_Objects => 0,
+ In_Wait_Flag => False,
+ Actuals_Ref => null,
+ Result => null)));
+ return Res;
+ end Create_Subprogram_Instance;
+
+ -- Destroy a dynamic block_instance.
+ procedure Execute_Subprogram_Call_Final (Instance : Block_Instance_Acc)
+ is
+ Subprg_Body : constant Iir := Get_Subprogram_Body (Instance.Label);
+ begin
+ Finalize_Declarative_Part
+ (Instance, Get_Declaration_Chain (Subprg_Body));
+ end Execute_Subprogram_Call_Final;
+
+ function Execute_Function_Body (Instance : Block_Instance_Acc; Func : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Subprg_Body : constant Iir := Get_Subprogram_Body (Func);
+ Res : Iir_Value_Literal_Acc;
+ begin
+ Current_Process.Instance := Instance;
+
+ Elaborate_Declarative_Part
+ (Instance, Get_Declaration_Chain (Subprg_Body));
+
+ -- execute statements
+ Instance.Stmt := Get_Sequential_Statement_Chain (Subprg_Body);
+ Execute_Sequential_Statements (Current_Process);
+ pragma Assert (Current_Process.Instance = Instance);
+
+ if Instance.Result = null then
+ Error_Msg_Exec
+ ("function scope exited without a return statement", Func);
+ end if;
+
+ -- Free variables, slots...
+ -- Need to copy the return value, because it can contains values from
+ -- arguments.
+ Res := Instance.Result;
+
+ Current_Process.Instance := Instance.Parent;
+ Execute_Subprogram_Call_Final (Instance);
+
+ return Res;
+ end Execute_Function_Body;
+
+ function Execute_Assoc_Function_Conversion
+ (Block : Block_Instance_Acc; Func : Iir; Val : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc
+ is
+ Inter : Iir;
+ Instance : Block_Instance_Acc;
+ Res : Iir_Value_Literal_Acc;
+ Marker : Mark_Type;
+ begin
+ Mark (Marker, Instance_Pool.all);
+
+ -- Create an instance for this function.
+ Instance := Create_Subprogram_Instance (Block, Func);
+
+ Inter := Get_Interface_Declaration_Chain (Func);
+ Elaboration.Create_Object (Instance, Inter);
+ -- FIXME: implicit conversion
+ Instance.Objects (Get_Info (Inter).Slot) := Val;
+
+ Res := Execute_Function_Body (Instance, Func);
+ Res := Unshare (Res, Expr_Pool'Access);
+ Release (Marker, Instance_Pool.all);
+ return Res;
+ end Execute_Assoc_Function_Conversion;
+
+ function Execute_Assoc_Conversion
+ (Block : Block_Instance_Acc; Conv : Iir; Val : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc
+ is
+ Ent : Iir;
+ begin
+ case Get_Kind (Conv) is
+ when Iir_Kind_Function_Call =>
+ -- FIXME: shouldn't CONV always be a denoting_name ?
+ return Execute_Assoc_Function_Conversion
+ (Block, Get_Named_Entity (Get_Implementation (Conv)), Val);
+ when Iir_Kind_Type_Conversion =>
+ -- FIXME: shouldn't CONV always be a denoting_name ?
+ return Execute_Type_Conversion (Block, Conv, Val);
+ when Iir_Kinds_Denoting_Name =>
+ Ent := Get_Named_Entity (Conv);
+ if Get_Kind (Ent) = Iir_Kind_Function_Declaration then
+ return Execute_Assoc_Function_Conversion (Block, Ent, Val);
+ elsif Get_Kind (Ent) in Iir_Kinds_Type_Declaration then
+ return Execute_Type_Conversion (Block, Ent, Val);
+ else
+ Error_Kind ("execute_assoc_conversion(1)", Ent);
+ end if;
+ when others =>
+ Error_Kind ("execute_assoc_conversion(2)", Conv);
+ end case;
+ end Execute_Assoc_Conversion;
+
+ -- Establish correspondance for association list ASSOC_LIST from block
+ -- instance OUT_BLOCK for subprogram of block SUBPRG_BLOCK.
+ procedure Execute_Association
+ (Out_Block: Block_Instance_Acc;
+ Subprg_Block: Block_Instance_Acc;
+ Assoc_Chain: Iir)
+ is
+ Nbr_Assoc : constant Natural := Get_Chain_Length (Assoc_Chain);
+ Assoc: Iir;
+ Actual : Iir;
+ Inter: Iir;
+ Formal : Iir;
+ Conv : Iir;
+ Val: Iir_Value_Literal_Acc;
+ Assoc_Idx : Iir_Index32;
+ Last_Individual : Iir_Value_Literal_Acc;
+ Mode : Iir_Mode;
+ Marker : Mark_Type;
+ begin
+ Subprg_Block.Actuals_Ref := null;
+ Mark (Marker, Expr_Pool);
+
+ Assoc := Assoc_Chain;
+ Assoc_Idx := 1;
+ while Assoc /= Null_Iir loop
+ Formal := Get_Formal (Assoc);
+ Inter := Get_Association_Interface (Assoc);
+
+ -- Extract the actual value.
+ case Get_Kind (Assoc) is
+ when Iir_Kind_Association_Element_Open =>
+ -- Not allowed in individual association.
+ pragma Assert (Formal = Inter);
+ pragma Assert (Get_Whole_Association_Flag (Assoc));
+ Actual := Get_Default_Value (Inter);
+ when Iir_Kind_Association_Element_By_Expression =>
+ Actual := Get_Actual (Assoc);
+ when Iir_Kind_Association_Element_By_Individual =>
+ -- FIXME: signals ?
+ pragma Assert
+ (Get_Kind (Inter) /= Iir_Kind_Signal_Interface_Declaration);
+ Last_Individual := Create_Value_For_Type
+ (Out_Block, Get_Actual_Type (Assoc), False);
+ Last_Individual := Unshare (Last_Individual, Instance_Pool);
+
+ Elaboration.Create_Object (Subprg_Block, Inter);
+ Subprg_Block.Objects (Get_Info (Inter).Slot) := Last_Individual;
+ goto Continue;
+ when others =>
+ Error_Kind ("execute_association(1)", Assoc);
+ end case;
+
+ -- Compute actual value.
+ case Get_Kind (Inter) is
+ when Iir_Kind_Constant_Interface_Declaration
+ | Iir_Kind_File_Interface_Declaration =>
+ Val := Execute_Expression (Out_Block, Actual);
+ Implicit_Array_Conversion
+ (Subprg_Block, Val, Get_Type (Formal), Assoc);
+ Check_Constraints (Subprg_Block, Val, Get_Type (Formal), Assoc);
+ when Iir_Kind_Signal_Interface_Declaration =>
+ Val := Execute_Name (Out_Block, Actual, True);
+ Implicit_Array_Conversion
+ (Subprg_Block, Val, Get_Type (Formal), Assoc);
+ when Iir_Kind_Variable_Interface_Declaration =>
+ Mode := Get_Mode (Inter);
+ if Mode = Iir_In_Mode then
+ -- FIXME: Ref ?
+ Val := Execute_Expression (Out_Block, Actual);
+ else
+ Val := Execute_Name (Out_Block, Actual, False);
+ end if;
+
+ -- FIXME: by value for scalars ?
+
+ -- Keep ref for back-copy
+ if Mode /= Iir_In_Mode then
+ if Subprg_Block.Actuals_Ref = null then
+ declare
+ subtype Actuals_Ref_Type is
+ Value_Array (Iir_Index32 (Nbr_Assoc));
+ function To_Value_Array_Acc is new
+ Ada.Unchecked_Conversion (System.Address,
+ Value_Array_Acc);
+ function Alloc_Actuals_Ref is new
+ Alloc_On_Pool_Addr (Actuals_Ref_Type);
+
+ begin
+ Subprg_Block.Actuals_Ref := To_Value_Array_Acc
+ (Alloc_Actuals_Ref
+ (Instance_Pool,
+ Actuals_Ref_Type'(Len => Iir_Index32 (Nbr_Assoc),
+ V => (others => null))));
+ end;
+ end if;
+ Subprg_Block.Actuals_Ref.V (Assoc_Idx) :=
+ Unshare_Bounds (Val, Instance_Pool);
+ end if;
+
+ if Mode = Iir_Out_Mode then
+ if Get_Out_Conversion (Assoc) /= Null_Iir then
+ -- For an OUT variable using an out conversion, don't
+ -- associate with the actual, create a temporary value.
+ Val := Create_Value_For_Type
+ (Out_Block, Get_Type (Formal), True);
+ elsif Get_Kind (Get_Type (Formal)) in
+ Iir_Kinds_Scalar_Type_Definition
+ then
+ -- These are passed by value. Must be reset.
+ Val := Create_Value_For_Type
+ (Out_Block, Get_Type (Formal), True);
+ end if;
+ else
+ if Get_Kind (Assoc) =
+ Iir_Kind_Association_Element_By_Expression
+ then
+ Conv := Get_In_Conversion (Assoc);
+ if Conv /= Null_Iir then
+ Val := Execute_Assoc_Conversion
+ (Subprg_Block, Conv, Val);
+ end if;
+ end if;
+
+ -- FIXME: check constraints ?
+ end if;
+
+ Implicit_Array_Conversion
+ (Subprg_Block, Val, Get_Type (Formal), Assoc);
+
+ when others =>
+ Error_Kind ("execute_association(2)", Inter);
+ end case;
+
+ if Get_Whole_Association_Flag (Assoc) then
+ case Get_Kind (Inter) is
+ when Iir_Kind_Constant_Interface_Declaration
+ | Iir_Kind_Variable_Interface_Declaration
+ | Iir_Kind_File_Interface_Declaration =>
+ -- FIXME: Arguments are passed by copy.
+ Elaboration.Create_Object (Subprg_Block, Inter);
+ Subprg_Block.Objects (Get_Info (Inter).Slot) :=
+ Unshare (Val, Instance_Pool);
+ when Iir_Kind_Signal_Interface_Declaration =>
+ Elaboration.Create_Signal (Subprg_Block, Inter);
+ Subprg_Block.Objects (Get_Info (Inter).Slot) :=
+ Unshare_Bounds (Val, Instance_Pool);
+ when others =>
+ Error_Kind ("execute_association", Inter);
+ end case;
+ else
+ declare
+ Targ : Iir_Value_Literal_Acc;
+ Is_Sig : Boolean;
+ begin
+ Execute_Name_With_Base
+ (Subprg_Block, Formal, Last_Individual, Targ, Is_Sig);
+ Store (Targ, Val);
+ end;
+ end if;
+
+ << Continue >> null;
+ Assoc := Get_Chain (Assoc);
+ Assoc_Idx := Assoc_Idx + 1;
+ end loop;
+
+ Release (Marker, Expr_Pool);
+ end Execute_Association;
+
+ procedure Execute_Back_Association (Instance : Block_Instance_Acc)
+ is
+ Proc : Iir;
+ Assoc: Iir;
+ Inter: Iir;
+ Formal : Iir;
+ Assoc_Idx : Iir_Index32;
+ begin
+ Proc := Get_Procedure_Call (Instance.Parent.Stmt);
+ Assoc := Get_Parameter_Association_Chain (Proc);
+ Assoc_Idx := 1;
+ while Assoc /= Null_Iir loop
+ if Get_Kind (Assoc) /= Iir_Kind_Association_Element_By_Individual then
+ Formal := Get_Formal (Assoc);
+ Inter := Get_Association_Interface (Assoc);
+ case Get_Kind (Inter) is
+ when Iir_Kind_Variable_Interface_Declaration =>
+ if Get_Mode (Inter) /= Iir_In_Mode
+ and then Get_Kind (Get_Type (Inter)) /=
+ Iir_Kind_File_Type_Definition
+ then
+ -- For out/inout variable interface, the value must
+ -- be copied (FIXME: unless when passed by reference ?).
+ declare
+ Targ : constant Iir_Value_Literal_Acc :=
+ Instance.Actuals_Ref.V (Assoc_Idx);
+ Base : constant Iir_Value_Literal_Acc :=
+ Instance.Objects (Get_Info (Inter).Slot);
+ Val : Iir_Value_Literal_Acc;
+ Conv : Iir;
+ Is_Sig : Boolean;
+ Expr_Mark : Mark_Type;
+ begin
+ Mark (Expr_Mark, Expr_Pool);
+
+ -- Extract for individual association.
+ Execute_Name_With_Base
+ (Instance, Formal, Base, Val, Is_Sig);
+ Conv := Get_Out_Conversion (Assoc);
+ if Conv /= Null_Iir then
+ Val := Execute_Assoc_Conversion
+ (Instance, Conv, Val);
+ -- FIXME: free val ?
+ end if;
+ Store (Targ, Val);
+
+ Release (Expr_Mark, Expr_Pool);
+ end;
+ end if;
+ when Iir_Kind_File_Interface_Declaration =>
+ null;
+ when Iir_Kind_Signal_Interface_Declaration
+ | Iir_Kind_Constant_Interface_Declaration =>
+ null;
+ when others =>
+ Error_Kind ("execute_back_association", Inter);
+ end case;
+ end if;
+ Assoc := Get_Chain (Assoc);
+ Assoc_Idx := Assoc_Idx + 1;
+ end loop;
+ end Execute_Back_Association;
+
+ -- When a subprogram of a protected type is called, a link to the object
+ -- must be passed. This procedure modifies the up_link of SUBPRG_BLOCK to
+ -- point to the block of the object (extracted from CALL and BLOCK).
+ -- This change doesn't modify the parent (so that the activation chain is
+ -- not changed).
+ procedure Adjust_Up_Link_For_Protected_Object
+ (Block: Block_Instance_Acc; Call: Iir; Subprg_Block : Block_Instance_Acc)
+ is
+ Meth_Obj : constant Iir := Get_Method_Object (Call);
+ Obj : Iir_Value_Literal_Acc;
+ Obj_Block : Block_Instance_Acc;
+ begin
+ if Meth_Obj /= Null_Iir then
+ Obj := Execute_Name (Block, Meth_Obj, True);
+ Obj_Block := Protected_Table.Table (Obj.Prot);
+ Subprg_Block.Up_Block := Obj_Block;
+ end if;
+ end Adjust_Up_Link_For_Protected_Object;
+
+ function Execute_Foreign_Function_Call
+ (Block: Block_Instance_Acc; Expr : Iir; Imp : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ pragma Unreferenced (Block);
+ begin
+ case Get_Identifier (Imp) is
+ when Std_Names.Name_Get_Resolution_Limit =>
+ return Create_I64_Value
+ (Ghdl_I64
+ (Evaluation.Get_Physical_Value (Std_Package.Time_Base)));
+ when others =>
+ Error_Msg_Exec ("unsupported foreign function call", Expr);
+ end case;
+ return null;
+ end Execute_Foreign_Function_Call;
+
+ -- BLOCK is the block instance in which the function call appears.
+ function Execute_Function_Call
+ (Block: Block_Instance_Acc; Expr: Iir; Imp : Iir)
+ return Iir_Value_Literal_Acc
+ is
+ Inter_Chain : constant Iir := Get_Interface_Declaration_Chain (Imp);
+ Subprg_Block: Block_Instance_Acc;
+ Assoc_Chain: Iir;
+ Res : Iir_Value_Literal_Acc;
+ begin
+ Mark (Block.Marker, Instance_Pool.all);
+
+ Subprg_Block := Create_Subprogram_Instance (Block, Imp);
+
+ case Get_Kind (Expr) is
+ when Iir_Kind_Function_Call =>
+ Adjust_Up_Link_For_Protected_Object (Block, Expr, Subprg_Block);
+ Assoc_Chain := Get_Parameter_Association_Chain (Expr);
+ Execute_Association (Block, Subprg_Block, Assoc_Chain);
+ -- No out/inout interface for functions.
+ pragma Assert (Subprg_Block.Actuals_Ref = null);
+ when Iir_Kinds_Dyadic_Operator =>
+ Execute_Dyadic_Association
+ (Block, Subprg_Block, Expr, Inter_Chain);
+ when Iir_Kinds_Monadic_Operator =>
+ Execute_Monadic_Association
+ (Block, Subprg_Block, Expr, Inter_Chain);
+ when others =>
+ Error_Kind ("execute_subprogram_call_init", Expr);
+ end case;
+
+ if Get_Foreign_Flag (Imp) then
+ Res := Execute_Foreign_Function_Call (Subprg_Block, Expr, Imp);
+ else
+ Res := Execute_Function_Body (Subprg_Block, Imp);
+ end if;
+
+ -- Unfortunately, we don't know where the result has been allocated,
+ -- so copy it before releasing the instance pool.
+ Res := Unshare (Res, Expr_Pool'Access);
+
+ Release (Block.Marker, Instance_Pool.all);
+
+ return Res;
+ end Execute_Function_Call;
+
+ -- Slide an array VALUE using bounds from REF_VALUE. Do not modify
+ -- VALUE if not an array.
+ procedure Implicit_Array_Conversion (Value : in out Iir_Value_Literal_Acc;
+ Ref_Value : Iir_Value_Literal_Acc;
+ Expr : Iir)
+ is
+ Res : Iir_Value_Literal_Acc;
+ begin
+ if Value.Kind /= Iir_Value_Array then
+ return;
+ end if;
+ Res := Create_Array_Value (Value.Bounds.Nbr_Dims);
+ Res.Val_Array := Value.Val_Array;
+ for I in Value.Bounds.D'Range loop
+ if Value.Bounds.D (I).Length /= Ref_Value.Bounds.D (I).Length then
+ Error_Msg_Constraint (Expr);
+ return;
+ end if;
+ Res.Bounds.D (I) := Ref_Value.Bounds.D (I);
+ end loop;
+ Value := Res;
+ end Implicit_Array_Conversion;
+
+ procedure Implicit_Array_Conversion (Instance : Block_Instance_Acc;
+ Value : in out Iir_Value_Literal_Acc;
+ Ref_Type : Iir;
+ Expr : Iir)
+ is
+ Ref_Value : Iir_Value_Literal_Acc;
+ begin
+ -- Do array conversion only if REF_TYPE is a constrained array type
+ -- definition.
+ if Value.Kind /= Iir_Value_Array then
+ return;
+ end if;
+ if Get_Constraint_State (Ref_Type) /= Fully_Constrained then
+ return;
+ end if;
+ Ref_Value := Create_Array_Bounds_From_Type (Instance, Ref_Type, True);
+ for I in Value.Bounds.D'Range loop
+ if Value.Bounds.D (I).Length /= Ref_Value.Bounds.D (I).Length then
+ Error_Msg_Constraint (Expr);
+ return;
+ end if;
+ end loop;
+ Ref_Value.Val_Array.V := Value.Val_Array.V;
+ Value := Ref_Value;
+ end Implicit_Array_Conversion;
+
+ procedure Check_Array_Constraints
+ (Instance: Block_Instance_Acc;
+ Value: Iir_Value_Literal_Acc;
+ Def: Iir;
+ Expr: Iir)
+ is
+ Index_List: Iir_List;
+ Element_Subtype: Iir;
+ New_Bounds : Iir_Value_Literal_Acc;
+ begin
+ -- Nothing to check for unconstrained arrays.
+ if not Get_Index_Constraint_Flag (Def) then
+ return;
+ end if;
+
+ Index_List := Get_Index_Subtype_List (Def);
+ for I in Value.Bounds.D'Range loop
+ New_Bounds := Execute_Bounds
+ (Instance, Get_Nth_Element (Index_List, Natural (I - 1)));
+ if not Is_Equal (Value.Bounds.D (I), New_Bounds) then
+ Error_Msg_Constraint (Expr);
+ return;
+ end if;
+ end loop;
+
+ if Boolean'(False) then
+ Index_List := Get_Index_List (Def);
+ Element_Subtype := Get_Element_Subtype (Def);
+ for I in Value.Val_Array.V'Range loop
+ Check_Constraints
+ (Instance, Value.Val_Array.V (I), Element_Subtype, Expr);
+ end loop;
+ end if;
+ end Check_Array_Constraints;
+
+ -- Check DEST and SRC are array compatible.
+ procedure Check_Array_Match
+ (Instance: Block_Instance_Acc;
+ Dest: Iir_Value_Literal_Acc;
+ Src : Iir_Value_Literal_Acc;
+ Expr: Iir)
+ is
+ pragma Unreferenced (Instance);
+ begin
+ for I in Dest.Bounds.D'Range loop
+ if Dest.Bounds.D (I).Length /= Src.Bounds.D (I).Length then
+ Error_Msg_Constraint (Expr);
+ exit;
+ end if;
+ end loop;
+ end Check_Array_Match;
+ pragma Unreferenced (Check_Array_Match);
+
+ procedure Check_Constraints
+ (Instance: Block_Instance_Acc;
+ Value: Iir_Value_Literal_Acc;
+ Def: Iir;
+ Expr: Iir)
+ is
+ Base_Type : constant Iir := Get_Base_Type (Def);
+ High, Low: Iir_Value_Literal_Acc;
+ Bound : Iir_Value_Literal_Acc;
+ begin
+ case Get_Kind (Def) is
+ when Iir_Kind_Integer_Subtype_Definition
+ | Iir_Kind_Floating_Subtype_Definition
+ | Iir_Kind_Enumeration_Subtype_Definition
+ | Iir_Kind_Physical_Subtype_Definition
+ | Iir_Kind_Enumeration_Type_Definition =>
+ Bound := Execute_Bounds (Instance, Def);
+ if Bound.Dir = Iir_To then
+ High := Bound.Right;
+ Low := Bound.Left;
+ else
+ High := Bound.Left;
+ Low := Bound.Right;
+ end if;
+ case Get_Info (Base_Type).Scalar_Mode is
+ when Iir_Value_I64 =>
+ if Value.I64 in Low.I64 .. High.I64 then
+ return;
+ end if;
+ when Iir_Value_E32 =>
+ if Value.E32 in Low.E32 .. High.E32 then
+ return;
+ end if;
+ when Iir_Value_F64 =>
+ if Value.F64 in Low.F64 .. High.F64 then
+ return;
+ end if;
+ when Iir_Value_B1 =>
+ if Value.B1 in Low.B1 .. High.B1 then
+ return;
+ end if;
+ when others =>
+ raise Internal_Error;
+ end case;
+ when Iir_Kind_Array_Subtype_Definition
+ | Iir_Kind_Array_Type_Definition =>
+ Check_Array_Constraints (Instance, Value, Def, Expr);
+ return;
+ when Iir_Kind_Record_Type_Definition
+ | Iir_Kind_Record_Subtype_Definition =>
+ declare
+ El: Iir_Element_Declaration;
+ List : Iir_List;
+ begin
+ List := Get_Elements_Declaration_List (Get_Base_Type (Def));
+ for I in Natural loop
+ El := Get_Nth_Element (List, I);
+ exit when El = Null_Iir;
+ Check_Constraints
+ (Instance,
+ Value.Val_Record.V (Get_Element_Position (El) + 1),
+ Get_Type (El),
+ Expr);
+ end loop;
+ end;
+ return;
+ when Iir_Kind_Integer_Type_Definition =>
+ return;
+ when Iir_Kind_Floating_Type_Definition =>
+ return;
+ when Iir_Kind_Physical_Type_Definition =>
+ return;
+ when Iir_Kind_Access_Type_Definition
+ | Iir_Kind_Access_Subtype_Definition =>
+ return;
+ when Iir_Kind_File_Type_Definition =>
+ return;
+ when others =>
+ Error_Kind ("check_constraints", Def);
+ end case;
+ Error_Msg_Constraint (Expr);
+ end Check_Constraints;
+
+ function Execute_Resolution_Function
+ (Block: Block_Instance_Acc; Imp : Iir; Arr : Iir_Value_Literal_Acc)
+ return Iir_Value_Literal_Acc
+ is
+ Inter : Iir;
+ Instance : Block_Instance_Acc;
+ begin
+ -- Create a frame for this function.
+ Instance := Create_Subprogram_Instance (Block, Imp);
+
+ Inter := Get_Interface_Declaration_Chain (Imp);
+ Elaboration.Create_Object (Instance, Inter);
+ Instance.Objects (Get_Info (Inter).Slot) := Arr;
+
+ return Execute_Function_Body (Instance, Imp);
+ end Execute_Resolution_Function;
+
+ procedure Execute_Signal_Assignment
+ (Instance: Block_Instance_Acc;
+ Stmt: Iir_Signal_Assignment_Statement)
+ is
+ Wf : constant Iir_Waveform_Element := Get_Waveform_Chain (Stmt);
+ Nbr_We : constant Natural := Get_Chain_Length (Wf);
+
+ Transactions : Transaction_Type (Nbr_We);
+
+ We: Iir_Waveform_Element;
+ Res: Iir_Value_Literal_Acc;
+ Rdest: Iir_Value_Literal_Acc;
+ Targ_Type : Iir;
+ Marker : Mark_Type;
+ begin
+ Mark (Marker, Expr_Pool);
+
+ Rdest := Execute_Name (Instance, Get_Target (Stmt), True);
+ Targ_Type := Get_Type (Get_Target (Stmt));
+
+ -- Disconnection statement.
+ if Wf = Null_Iir then
+ Disconnect_Signal (Rdest);
+ Release (Marker, Expr_Pool);
+ return;
+ end if;
+
+ Transactions.Stmt := Stmt;
+
+ -- LRM93 8.4.1
+ -- Evaluation of a waveform consists of the evaluation of each waveform
+ -- elements in the waveform.
+ We := Wf;
+ for I in Transactions.Els'Range loop
+ declare
+ Trans : Transaction_El_Type renames Transactions.Els (I);
+ begin
+ if Get_Time (We) /= Null_Iir then
+ Res := Execute_Expression (Instance, Get_Time (We));
+ -- LRM93 8.4.1
+ -- It is an error if the time expression in a waveform element
+ -- evaluates to a negative value.
+ if Res.I64 < 0 then
+ Error_Msg_Exec ("time value is negative", Get_Time (We));
+ end if;
+ Trans.After := Std_Time (Res.I64);
+ else
+ -- LRM93 8.4.1
+ -- If the after clause of a waveform element is not present,
+ -- then an implicit "after 0 ns" is assumed.
+ Trans.After := 0;
+ end if;
+
+ -- LRM93 8.4.1
+ -- It is an error if the sequence of new transactions is not in
+ -- ascending order with respect to time.
+ if I > 1
+ and then Trans.After <= Transactions.Els (I - 1).After
+ then
+ Error_Msg_Exec
+ ("sequence not in ascending order with respect to time", We);
+ end if;
+
+ if Get_Kind (Get_We_Value (We)) = Iir_Kind_Null_Literal then
+ -- null transaction.
+ Trans.Value := null;
+ else
+ -- LRM93 8.4.1
+ -- For the first form of waveform element, the value component
+ -- of the transaction is determined by the value expression in
+ -- the waveform element.
+ Trans.Value := Execute_Expression_With_Type
+ (Instance, Get_We_Value (We), Targ_Type);
+ end if;
+ end;
+ We := Get_Chain (We);
+ end loop;
+ pragma Assert (We = Null_Iir);
+
+ case Get_Delay_Mechanism (Stmt) is
+ when Iir_Transport_Delay =>
+ Transactions.Reject := 0;
+ when Iir_Inertial_Delay =>
+ -- LRM93 8.4
+ -- or, in the case that a pulse rejection limit is specified,
+ -- a pulse whose duration is shorter than that limit will not
+ -- be transmitted.
+ -- Every inertially delayed signal assignment has a pulse
+ -- rejection limit.
+ if Get_Reject_Time_Expression (Stmt) /= Null_Iir then
+ -- LRM93 8.4
+ -- If the delay mechanism specifies inertial delay, and if the
+ -- reserved word reject followed by a time expression is
+ -- present, then the time expression specifies the pulse
+ -- rejection limit.
+ Res := Execute_Expression
+ (Instance, Get_Reject_Time_Expression (Stmt));
+ -- LRM93 8.4
+ -- It is an error if the pulse rejection limit for any
+ -- inertially delayed signal assignement statement is either
+ -- negative ...
+ if Res.I64 < 0 then
+ Error_Msg_Exec ("reject time negative", Stmt);
+ end if;
+ -- LRM93 8.4
+ -- ... or greather than the time expression associated with
+ -- the first waveform element.
+ Transactions.Reject := Std_Time (Res.I64);
+ if Transactions.Reject > Transactions.Els (1).After then
+ Error_Msg_Exec
+ ("reject time greather than time expression", Stmt);
+ end if;
+ else
+ -- LRM93 8.4
+ -- In all other cases, the pulse rejection limit is the time
+ -- expression associated ith the first waveform element.
+ Transactions.Reject := Transactions.Els (1).After;
+ end if;
+ end case;
+
+ -- FIXME: slice Transactions to remove transactions after end of time.
+ Assign_Value_To_Signal (Instance, Rdest, Transactions);
+
+ Release (Marker, Expr_Pool);
+ end Execute_Signal_Assignment;
+
+ procedure Assign_Simple_Value_To_Object
+ (Instance: Block_Instance_Acc;
+ Dest: Iir_Value_Literal_Acc;
+ Dest_Type: Iir;
+ Value: Iir_Value_Literal_Acc;
+ Stmt: Iir)
+ is
+ begin
+ if Dest.Kind /= Value.Kind then
+ raise Internal_Error; -- literal kind mismatch.
+ end if;
+
+ Check_Constraints (Instance, Value, Dest_Type, Stmt);
+
+ Store (Dest, Value);
+ end Assign_Simple_Value_To_Object;
+
+ procedure Assign_Array_Value_To_Object
+ (Instance: Block_Instance_Acc;
+ Target: Iir_Value_Literal_Acc;
+ Target_Type: Iir;
+ Depth: Natural;
+ Value: Iir_Value_Literal_Acc;
+ Stmt: Iir)
+ is
+ Element_Type: Iir;
+ begin
+ if Target.Val_Array.Len /= Value.Val_Array.Len then
+ -- Dimension mismatch.
+ raise Program_Error;
+ end if;
+ if Depth = Get_Nbr_Elements (Get_Index_List (Target_Type)) then
+ Element_Type := Get_Element_Subtype (Target_Type);
+ for I in Target.Val_Array.V'Range loop
+ Assign_Value_To_Object (Instance,
+ Target.Val_Array.V (I),
+ Element_Type,
+ Value.Val_Array.V (I),
+ Stmt);
+ end loop;
+ else
+ for I in Target.Val_Array.V'Range loop
+ Assign_Array_Value_To_Object (Instance,
+ Target.Val_Array.V (I),
+ Target_Type,
+ Depth + 1,
+ Value.Val_Array.V (I),
+ Stmt);
+ end loop;
+ end if;
+ end Assign_Array_Value_To_Object;
+
+ procedure Assign_Record_Value_To_Object
+ (Instance: Block_Instance_Acc;
+ Target: Iir_Value_Literal_Acc;
+ Target_Type: Iir;
+ Value: Iir_Value_Literal_Acc;
+ Stmt: Iir)
+ is
+ Element_Type: Iir;
+ List : Iir_List;
+ Element: Iir_Element_Declaration;
+ Pos : Iir_Index32;
+ begin
+ if Target.Val_Record.Len /= Value.Val_Record.Len then
+ -- Dimension mismatch.
+ raise Program_Error;
+ end if;
+ List := Get_Elements_Declaration_List (Target_Type);
+ for I in Natural loop
+ Element := Get_Nth_Element (List, I);
+ exit when Element = Null_Iir;
+ Element_Type := Get_Type (Element);
+ Pos := Get_Element_Position (Element);
+ Assign_Value_To_Object (Instance,
+ Target.Val_Record.V (1 + Pos),
+ Element_Type,
+ Value.Val_Record.V (1 + Pos),
+ Stmt);
+ end loop;
+ end Assign_Record_Value_To_Object;
+
+ procedure Assign_Value_To_Object
+ (Instance: Block_Instance_Acc;
+ Target: Iir_Value_Literal_Acc;
+ Target_Type: Iir;
+ Value: Iir_Value_Literal_Acc;
+ Stmt: Iir)
+ is
+ begin
+ case Target.Kind is
+ when Iir_Value_Array =>
+ Assign_Array_Value_To_Object
+ (Instance, Target, Target_Type, 1, Value, Stmt);
+ when Iir_Value_Record =>
+ Assign_Record_Value_To_Object
+ (Instance, Target, Target_Type, Value, Stmt);
+ when Iir_Value_Scalars
+ | Iir_Value_Access =>
+ Assign_Simple_Value_To_Object
+ (Instance, Target, Target_Type, Value, Stmt);
+ when Iir_Value_File
+ | Iir_Value_Signal
+ | Iir_Value_Protected
+ | Iir_Value_Range
+ | Iir_Value_Quantity
+ | Iir_Value_Terminal =>
+ raise Internal_Error;
+ end case;
+ end Assign_Value_To_Object;
+
+ -- Display a message when an assertion has failed.
+ -- REPORT is the value (string) to display, or null to use default message.
+ -- SEVERITY is the severity or null to use default (error).
+ -- STMT is used to display location.
+ procedure Execute_Failed_Assertion (Report : String;
+ Severity : Natural;
+ Stmt: Iir) is
+ begin
+ -- LRM93 8.2
+ -- The error message consists of at least:
+
+ -- 4: name of the design unit containing the assertion.
+ Disp_Iir_Location (Stmt);
+
+ -- 1: an indication that this message is from an assertion.
+ Put (Standard_Error, "(assertion ");
+
+ -- 2: the value of the severity level.
+ case Severity is
+ when 0 =>
+ Put (Standard_Error, "note");
+ when 1 =>
+ Put (Standard_Error, "warning");
+ when 2 =>
+ Put (Standard_Error, "error");
+ when 3 =>
+ Put (Standard_Error, "failure");
+ when others =>
+ Error_Internal (Null_Iir, "execute_failed_assertion");
+ end case;
+ if Disp_Time_Before_Values then
+ Put (Standard_Error, " at ");
+ Grt.Astdio.Put_Time (Grt.Stdio.stderr, Current_Time);
+ end if;
+ Put (Standard_Error, "): ");
+
+ -- 3: the value of the message string.
+ Put_Line (Standard_Error, Report);
+
+ -- Stop execution if the severity is too high.
+ if Severity >= Grt.Options.Severity_Level then
+ Debug (Reason_Assert);
+ Grt.Errors.Fatal_Error;
+ end if;
+ end Execute_Failed_Assertion;
+
+ procedure Execute_Failed_Assertion (Report : Iir_Value_Literal_Acc;
+ Severity : Natural;
+ Stmt: Iir) is
+ begin
+ if Report /= null then
+ declare
+ Msg : String (1 .. Natural (Report.Val_Array.Len));
+ begin
+ for I in Report.Val_Array.V'Range loop
+ Msg (Positive (I)) :=
+ Character'Val (Report.Val_Array.V (I).E32);
+ end loop;
+ Execute_Failed_Assertion (Msg, Severity, Stmt);
+ end;
+ else
+ -- The default value for the message string is:
+ -- "Assertion violation.".
+ -- Does the message string include quotes ?
+ Execute_Failed_Assertion ("Assertion violation.", Severity, Stmt);
+ end if;
+ end Execute_Failed_Assertion;
+
+ procedure Execute_Report_Statement
+ (Instance: Block_Instance_Acc; Stmt: Iir; Default_Severity : Natural)
+ is
+ Expr: Iir;
+ Report, Severity_Lit: Iir_Value_Literal_Acc;
+ Severity : Natural;
+ Marker : Mark_Type;
+ begin
+ Mark (Marker, Expr_Pool);
+ Expr := Get_Report_Expression (Stmt);
+ if Expr /= Null_Iir then
+ Report := Execute_Expression (Instance, Expr);
+ else
+ Report := null;
+ end if;
+ Expr := Get_Severity_Expression (Stmt);
+ if Expr /= Null_Iir then
+ Severity_Lit := Execute_Expression (Instance, Expr);
+ Severity := Natural'Val (Severity_Lit.E32);
+ else
+ Severity := Default_Severity;
+ end if;
+ Execute_Failed_Assertion (Report, Severity, Stmt);
+ Release (Marker, Expr_Pool);
+ end Execute_Report_Statement;
+
+ function Is_In_Choice
+ (Instance: Block_Instance_Acc;
+ Choice: Iir;
+ Expr: Iir_Value_Literal_Acc)
+ return Boolean
+ is
+ Res : Boolean;
+ begin
+ case Get_Kind (Choice) is
+ when Iir_Kind_Choice_By_Others =>
+ return True;
+ when Iir_Kind_Choice_By_Expression =>
+ declare
+ Expr1: Iir_Value_Literal_Acc;
+ begin
+ Expr1 := Execute_Expression
+ (Instance, Get_Choice_Expression (Choice));
+ Res := Is_Equal (Expr, Expr1);
+ return Res;
+ end;
+ when Iir_Kind_Choice_By_Range =>
+ declare
+ A_Range : Iir_Value_Literal_Acc;
+ begin
+ A_Range := Execute_Bounds
+ (Instance, Get_Choice_Range (Choice));
+ Res := Is_In_Range (Expr, A_Range);
+ end;
+ return Res;
+ when others =>
+ Error_Kind ("is_in_choice", Choice);
+ end case;
+ end Is_In_Choice;
+
+ -- Return TRUE iff VAL is in the range defined by BOUNDS.
+ function Is_In_Range (Val : Iir_Value_Literal_Acc;
+ Bounds : Iir_Value_Literal_Acc)
+ return Boolean
+ is
+ Max, Min : Iir_Value_Literal_Acc;
+ begin
+ case Bounds.Dir is
+ when Iir_To =>
+ Min := Bounds.Left;
+ Max := Bounds.Right;
+ when Iir_Downto =>
+ Min := Bounds.Right;
+ Max := Bounds.Left;
+ end case;
+
+ case Val.Kind is
+ when Iir_Value_E32 =>
+ return Val.E32 >= Min.E32 and Val.E32 <= Max.E32;
+ when Iir_Value_B1 =>
+ return Val.B1 >= Min.B1 and Val.B1 <= Max.B1;
+ when Iir_Value_I64 =>
+ return Val.I64 >= Min.I64 and Val.I64 <= Max.I64;
+ when others =>
+ raise Internal_Error;
+ return False;
+ end case;
+ end Is_In_Range;
+
+ -- Increment or decrement VAL according to BOUNDS.DIR.
+ -- FIXME: use increment ?
+ procedure Update_Loop_Index (Val : Iir_Value_Literal_Acc;
+ Bounds : Iir_Value_Literal_Acc)
+ is
+ begin
+ case Val.Kind is
+ when Iir_Value_E32 =>
+ case Bounds.Dir is
+ when Iir_To =>
+ Val.E32 := Val.E32 + 1;
+ when Iir_Downto =>
+ Val.E32 := Val.E32 - 1;
+ end case;
+ when Iir_Value_B1 =>
+ case Bounds.Dir is
+ when Iir_To =>
+ Val.B1 := True;
+ when Iir_Downto =>
+ Val.B1 := False;
+ end case;
+ when Iir_Value_I64 =>
+ case Bounds.Dir is
+ when Iir_To =>
+ Val.I64 := Val.I64 + 1;
+ when Iir_Downto =>
+ Val.I64 := Val.I64 - 1;
+ end case;
+ when others =>
+ raise Internal_Error;
+ end case;
+ end Update_Loop_Index;
+
+ procedure Finalize_For_Loop_Statement (Instance : Block_Instance_Acc;
+ Stmt : Iir)
+ is
+ begin
+ Destroy_Iterator_Declaration
+ (Instance, Get_Parameter_Specification (Stmt));
+ end Finalize_For_Loop_Statement;
+
+ procedure Finalize_Loop_Statement (Instance : Block_Instance_Acc;
+ Stmt : Iir)
+ is
+ begin
+ if Get_Kind (Stmt) = Iir_Kind_For_Loop_Statement then
+ Finalize_For_Loop_Statement (Instance, Stmt);
+ end if;
+ end Finalize_Loop_Statement;
+
+ procedure Execute_For_Loop_Statement (Proc : Process_State_Acc)
+ is
+ Instance : constant Block_Instance_Acc := Proc.Instance;
+ Stmt : constant Iir_For_Loop_Statement := Instance.Stmt;
+ Iterator : constant Iir := Get_Parameter_Specification (Stmt);
+ Bounds : Iir_Value_Literal_Acc;
+ Index : Iir_Value_Literal_Acc;
+ Stmt_Chain : Iir;
+ Is_Nul : Boolean;
+ Marker : Mark_Type;
+ begin
+ -- Elaborate the iterator (and its type).
+ Elaborate_Declaration (Instance, Iterator);
+
+ -- Extract bounds.
+ Mark (Marker, Expr_Pool);
+ Bounds := Execute_Bounds (Instance, Get_Type (Iterator));
+ Index := Instance.Objects (Get_Info (Iterator).Slot);
+ Store (Index, Bounds.Left);
+ Is_Nul := Is_Nul_Range (Bounds);
+ Release (Marker, Expr_Pool);
+
+ if Is_Nul then
+ -- Loop is complete.
+ Finalize_For_Loop_Statement (Instance, Stmt);
+ Update_Next_Statement (Proc);
+ else
+ Stmt_Chain := Get_Sequential_Statement_Chain (Stmt);
+ if Stmt_Chain = Null_Iir then
+ -- Nothing to do for an empty loop.
+ Finalize_For_Loop_Statement (Instance, Stmt);
+ Update_Next_Statement (Proc);
+ else
+ Instance.Stmt := Stmt_Chain;
+ end if;
+ end if;
+ end Execute_For_Loop_Statement;
+
+ -- This function is called when there is no more statements to execute
+ -- in the statement list of a for_loop. Returns FALSE in case of end of
+ -- loop.
+ function Finish_For_Loop_Statement (Instance : Block_Instance_Acc)
+ return Boolean
+ is
+ Iterator : constant Iir := Get_Parameter_Specification (Instance.Stmt);
+ Bounds : Iir_Value_Literal_Acc;
+ Index : Iir_Value_Literal_Acc;
+ Marker : Mark_Type;
+ begin
+ -- FIXME: avoid allocation.
+ Mark (Marker, Expr_Pool);
+ Bounds := Execute_Bounds (Instance, Get_Type (Iterator));
+ Index := Instance.Objects (Get_Info (Iterator).Slot);
+
+ if Is_Equal (Index, Bounds.Right) then
+ -- Loop is complete.
+ Release (Marker, Expr_Pool);
+ Finalize_For_Loop_Statement (Instance, Instance.Stmt);
+ return False;
+ else
+ -- Update the loop index.
+ Update_Loop_Index (Index, Bounds);
+
+ Release (Marker, Expr_Pool);
+
+ -- start the loop again.
+ Instance.Stmt := Get_Sequential_Statement_Chain (Instance.Stmt);
+ return True;
+ end if;
+ end Finish_For_Loop_Statement;
+
+ -- Evaluate boolean condition COND. If COND is Null_Iir, returns true.
+ function Execute_Condition (Instance : Block_Instance_Acc;
+ Cond : Iir) return Boolean
+ is
+ V : Iir_Value_Literal_Acc;
+ Res : Boolean;
+ Marker : Mark_Type;
+ begin
+ if Cond = Null_Iir then
+ return True;
+ end if;
+
+ Mark (Marker, Expr_Pool);
+ V := Execute_Expression (Instance, Cond);
+ Res := V.B1 = True;
+ Release (Marker, Expr_Pool);
+ return Res;
+ end Execute_Condition;
+
+ -- Start a while loop statement, or return FALSE if the loop is not
+ -- executed.
+ procedure Execute_While_Loop_Statement (Proc : Process_State_Acc)
+ is
+ Instance: constant Block_Instance_Acc := Proc.Instance;
+ Stmt : constant Iir := Instance.Stmt;
+ Cond : Boolean;
+ begin
+ Cond := Execute_Condition (Instance, Get_Condition (Stmt));
+ if Cond then
+ Init_Sequential_Statements (Proc, Stmt);
+ else
+ Update_Next_Statement (Proc);
+ end if;
+ end Execute_While_Loop_Statement;
+
+ -- This function is called when there is no more statements to execute
+ -- in the statement list of a while loop. Returns FALSE iff loop is
+ -- completed.
+ function Finish_While_Loop_Statement (Instance : Block_Instance_Acc)
+ return Boolean
+ is
+ Cond : Boolean;
+ begin
+ Cond := Execute_Condition (Instance, Get_Condition (Instance.Stmt));
+
+ if Cond then
+ -- start the loop again.
+ Instance.Stmt := Get_Sequential_Statement_Chain (Instance.Stmt);
+ return True;
+ else
+ -- Loop is complete.
+ return False;
+ end if;
+ end Finish_While_Loop_Statement;
+
+ -- Return TRUE if the loop must be executed again
+ function Finish_Loop_Statement (Instance : Block_Instance_Acc;
+ Stmt : Iir) return Boolean is
+ begin
+ Instance.Stmt := Stmt;
+ case Get_Kind (Stmt) is
+ when Iir_Kind_While_Loop_Statement =>
+ return Finish_While_Loop_Statement (Instance);
+ when Iir_Kind_For_Loop_Statement =>
+ return Finish_For_Loop_Statement (Instance);
+ when others =>
+ Error_Kind ("finish_loop_statement", Stmt);
+ end case;
+ end Finish_Loop_Statement;
+
+ -- Return FALSE if the next statement should be executed (possibly
+ -- updated).
+ procedure Execute_Exit_Next_Statement (Proc : Process_State_Acc;
+ Is_Exit : Boolean)
+ is
+ Instance : constant Block_Instance_Acc := Proc.Instance;
+ Stmt : constant Iir := Instance.Stmt;
+ Label : constant Iir := Get_Named_Entity (Get_Loop_Label (Stmt));
+ Cond : Boolean;
+ Parent : Iir;
+ begin
+ Cond := Execute_Condition (Instance, Get_Condition (Stmt));
+ if not Cond then
+ Update_Next_Statement (Proc);
+ return;
+ end if;
+
+ Parent := Stmt;
+ loop
+ Parent := Get_Parent (Parent);
+ case Get_Kind (Parent) is
+ when Iir_Kind_For_Loop_Statement
+ | Iir_Kind_While_Loop_Statement =>
+ if Label = Null_Iir or else Label = Parent then
+ -- Target is this statement.
+ if Is_Exit then
+ Finalize_Loop_Statement (Instance, Parent);
+ Instance.Stmt := Parent;
+ Update_Next_Statement (Proc);
+ elsif not Finish_Loop_Statement (Instance, Parent) then
+ Update_Next_Statement (Proc);
+ else
+ Init_Sequential_Statements (Proc, Parent);
+ end if;
+ return;
+ else
+ Finalize_Loop_Statement (Instance, Parent);
+ end if;
+ when others =>
+ null;
+ end case;
+ end loop;
+ end Execute_Exit_Next_Statement;
+
+ procedure Execute_Case_Statement (Proc : Process_State_Acc)
+ is
+ Instance : constant Block_Instance_Acc := Proc.Instance;
+ Stmt : constant Iir := Instance.Stmt;
+ Value: Iir_Value_Literal_Acc;
+ Assoc: Iir;
+ Stmt_Chain : Iir;
+ Marker : Mark_Type;
+ begin
+ Mark (Marker, Expr_Pool);
+
+ Value := Execute_Expression (Instance, Get_Expression (Stmt));
+ Assoc := Get_Case_Statement_Alternative_Chain (Stmt);
+
+ while Assoc /= Null_Iir loop
+ if not Get_Same_Alternative_Flag (Assoc) then
+ Stmt_Chain := Get_Associated_Chain (Assoc);
+ end if;
+
+ if Is_In_Choice (Instance, Assoc, Value) then
+ if Stmt_Chain = Null_Iir then
+ Update_Next_Statement (Proc);
+ else
+ Instance.Stmt := Stmt_Chain;
+ end if;
+ Release (Marker, Expr_Pool);
+ return;
+ end if;
+
+ Assoc := Get_Chain (Assoc);
+ end loop;
+ -- FIXME: infinite loop???
+ Error_Msg_Exec ("no choice for expression", Stmt);
+ raise Internal_Error;
+ end Execute_Case_Statement;
+
+ procedure Execute_Call_Statement (Proc : Process_State_Acc)
+ is
+ Instance : constant Block_Instance_Acc := Proc.Instance;
+ Stmt : constant Iir := Instance.Stmt;
+ Call : constant Iir := Get_Procedure_Call (Stmt);
+ Imp : constant Iir := Get_Named_Entity (Get_Implementation (Call));
+ Subprg_Instance : Block_Instance_Acc;
+ Assoc_Chain: Iir;
+ Subprg_Body : Iir;
+ begin
+ if Get_Kind (Imp) = Iir_Kind_Implicit_Procedure_Declaration then
+ Execute_Implicit_Procedure (Instance, Call);
+ Update_Next_Statement (Proc);
+ elsif Get_Foreign_Flag (Imp) then
+ Execute_Foreign_Procedure (Instance, Call);
+ Update_Next_Statement (Proc);
+ else
+ Mark (Instance.Marker, Instance_Pool.all);
+ Subprg_Instance := Create_Subprogram_Instance (Instance, Imp);
+ Adjust_Up_Link_For_Protected_Object
+ (Instance, Call, Subprg_Instance);
+ Assoc_Chain := Get_Parameter_Association_Chain (Call);
+ Execute_Association (Instance, Subprg_Instance, Assoc_Chain);
+
+ Current_Process.Instance := Subprg_Instance;
+ Subprg_Body := Get_Subprogram_Body (Imp);
+ Elaborate_Declarative_Part
+ (Subprg_Instance, Get_Declaration_Chain (Subprg_Body));
+
+ Init_Sequential_Statements (Proc, Subprg_Body);
+ end if;
+ end Execute_Call_Statement;
+
+ procedure Finish_Procedure_Frame (Proc : Process_State_Acc)
+ is
+ Old_Instance : constant Block_Instance_Acc := Proc.Instance;
+ begin
+ Execute_Back_Association (Old_Instance);
+ Proc.Instance := Old_Instance.Parent;
+ Execute_Subprogram_Call_Final (Old_Instance);
+ Release (Proc.Instance.Marker, Instance_Pool.all);
+ end Finish_Procedure_Frame;
+
+ procedure Execute_If_Statement
+ (Proc : Process_State_Acc; Stmt: Iir_Wait_Statement)
+ is
+ Clause: Iir;
+ Cond: Boolean;
+ begin
+ Clause := Stmt;
+ loop
+ Cond := Execute_Condition (Proc.Instance, Get_Condition (Clause));
+ if Cond then
+ Init_Sequential_Statements (Proc, Clause);
+ return;
+ end if;
+ Clause := Get_Else_Clause (Clause);
+ exit when Clause = Null_Iir;
+ end loop;
+ Update_Next_Statement (Proc);
+ end Execute_If_Statement;
+
+ procedure Execute_Variable_Assignment
+ (Proc : Process_State_Acc; Stmt : Iir)
+ is
+ Instance : constant Block_Instance_Acc := Proc.Instance;
+ Target : constant Iir := Get_Target (Stmt);
+ Target_Type : constant Iir := Get_Type (Target);
+ Expr : constant Iir := Get_Expression (Stmt);
+ Expr_Type : constant Iir := Get_Type (Expr);
+ Target_Val: Iir_Value_Literal_Acc;
+ Res : Iir_Value_Literal_Acc;
+ Marker : Mark_Type;
+ begin
+ Mark (Marker, Expr_Pool);
+ Target_Val := Execute_Expression (Instance, Target);
+
+ -- If the type of the target is not static and the value is
+ -- an aggregate, then the aggregate may be contrained by the
+ -- target.
+ if Get_Kind (Expr) = Iir_Kind_Aggregate
+ and then Get_Type_Staticness (Expr_Type) < Locally
+ and then Get_Kind (Expr_Type)
+ in Iir_Kinds_Array_Type_Definition
+ then
+ Res := Copy_Array_Bound (Target_Val);
+ Fill_Array_Aggregate (Instance, Expr, Res);
+ else
+ Res := Execute_Expression (Instance, Expr);
+ end if;
+ if Get_Kind (Target_Type) in Iir_Kinds_Array_Type_Definition then
+ -- Note: target_type may be dynamic (slice case), so
+ -- check_constraints is not called.
+ Implicit_Array_Conversion (Res, Target_Val, Stmt);
+ else
+ Check_Constraints (Instance, Res, Target_Type, Stmt);
+ end if;
+
+ -- Note: we need to unshare before copying to avoid
+ -- overwrites (in assignments like: v (1 to 4) := v (3 to 6)).
+ -- FIXME: improve that handling (detect overlaps before).
+ Store (Target_Val, Unshare (Res, Expr_Pool'Access));
+
+ Release (Marker, Expr_Pool);
+ end Execute_Variable_Assignment;
+
+ function Execute_Return_Statement (Proc : Process_State_Acc)
+ return Boolean
+ is
+ Res : Iir_Value_Literal_Acc;
+ Instance : constant Block_Instance_Acc := Proc.Instance;
+ Stmt : constant Iir := Instance.Stmt;
+ Expr : constant Iir := Get_Expression (Stmt);
+ begin
+ if Expr /= Null_Iir then
+ Res := Execute_Expression (Instance, Expr);
+ Implicit_Array_Conversion (Instance, Res, Get_Type (Stmt), Stmt);
+ Check_Constraints (Instance, Res, Get_Type (Stmt), Stmt);
+ Instance.Result := Res;
+ end if;
+
+ case Get_Kind (Instance.Label) is
+ when Iir_Kind_Procedure_Declaration =>
+ Finish_Procedure_Frame (Proc);
+ Update_Next_Statement (Proc);
+ return False;
+ when Iir_Kind_Function_Declaration =>
+ return True;
+ when others =>
+ raise Internal_Error;
+ end case;
+ end Execute_Return_Statement;
+
+ procedure Finish_Sequential_Statements
+ (Proc : Process_State_Acc; Complex_Stmt : Iir)
+ is
+ Instance : Block_Instance_Acc := Proc.Instance;
+ Stmt : Iir;
+ begin
+ Stmt := Complex_Stmt;
+ loop
+ Instance.Stmt := Stmt;
+ case Get_Kind (Stmt) is
+ when Iir_Kind_For_Loop_Statement =>
+ if Finish_For_Loop_Statement (Instance) then
+ return;
+ end if;
+ when Iir_Kind_While_Loop_Statement =>
+ if Finish_While_Loop_Statement (Instance) then
+ return;
+ end if;
+ when Iir_Kind_Case_Statement
+ | Iir_Kind_If_Statement =>
+ null;
+ when Iir_Kind_Sensitized_Process_Statement =>
+ Instance.Stmt := Null_Iir;
+ return;
+ when Iir_Kind_Process_Statement =>
+ -- Start again.
+ Instance.Stmt := Get_Sequential_Statement_Chain (Stmt);
+ return;
+ when Iir_Kind_Procedure_Body =>
+ Finish_Procedure_Frame (Proc);
+ Instance := Proc.Instance;
+ when Iir_Kind_Function_Body =>
+ Error_Msg_Exec ("missing return statement in function", Stmt);
+ when others =>
+ Error_Kind ("execute_next_statement", Stmt);
+ end case;
+ Stmt := Get_Chain (Instance.Stmt);
+ if Stmt /= Null_Iir then
+ Instance.Stmt := Stmt;
+ return;
+ end if;
+ Stmt := Get_Parent (Instance.Stmt);
+ end loop;
+ end Finish_Sequential_Statements;
+
+ procedure Init_Sequential_Statements
+ (Proc : Process_State_Acc; Complex_Stmt : Iir)
+ is
+ Stmt : Iir;
+ begin
+ Stmt := Get_Sequential_Statement_Chain (Complex_Stmt);
+ if Stmt /= Null_Iir then
+ Proc.Instance.Stmt := Stmt;
+ else
+ Finish_Sequential_Statements (Proc, Complex_Stmt);
+ end if;
+ end Init_Sequential_Statements;
+
+ procedure Update_Next_Statement (Proc : Process_State_Acc)
+ is
+ Instance : constant Block_Instance_Acc := Proc.Instance;
+ Stmt : Iir;
+ begin
+ Stmt := Get_Chain (Instance.Stmt);
+ if Stmt /= Null_Iir then
+ Instance.Stmt := Stmt;
+ return;
+ end if;
+ Finish_Sequential_Statements (Proc, Get_Parent (Instance.Stmt));
+ end Update_Next_Statement;
+
+ procedure Execute_Sequential_Statements (Proc : Process_State_Acc)
+ is
+ Instance : Block_Instance_Acc;
+ Stmt: Iir;
+ begin
+ loop
+ Instance := Proc.Instance;
+ Stmt := Instance.Stmt;
+
+ -- End of process or subprogram.
+ exit when Stmt = Null_Iir;
+
+ if Trace_Statements then
+ declare
+ Name : Name_Id;
+ Line : Natural;
+ Col : Natural;
+ begin
+ Files_Map.Location_To_Position
+ (Get_Location (Stmt), Name, Line, Col);
+ Put_Line ("Execute statement at "
+ & Name_Table.Image (Name)
+ & Natural'Image (Line));
+ end;
+ end if;
+
+ if Flag_Need_Debug then
+ Debug (Reason_Break);
+ end if;
+
+ -- execute statement STMT.
+ case Get_Kind (Stmt) is
+ when Iir_Kind_Null_Statement =>
+ Update_Next_Statement (Proc);
+
+ when Iir_Kind_If_Statement =>
+ Execute_If_Statement (Proc, Stmt);
+
+ when Iir_Kind_Signal_Assignment_Statement =>
+ Execute_Signal_Assignment (Instance, Stmt);
+ Update_Next_Statement (Proc);
+
+ when Iir_Kind_Assertion_Statement =>
+ declare
+ Res : Boolean;
+ begin
+ Res := Execute_Condition
+ (Instance, Get_Assertion_Condition (Stmt));
+ if not Res then
+ Execute_Report_Statement (Instance, Stmt, 2);
+ end if;
+ end;
+ Update_Next_Statement (Proc);
+
+ when Iir_Kind_Report_Statement =>
+ Execute_Report_Statement (Instance, Stmt, 0);
+ Update_Next_Statement (Proc);
+
+ when Iir_Kind_Variable_Assignment_Statement =>
+ Execute_Variable_Assignment (Proc, Stmt);
+ Update_Next_Statement (Proc);
+
+ when Iir_Kind_Return_Statement =>
+ if Execute_Return_Statement (Proc) then
+ return;
+ end if;
+
+ when Iir_Kind_For_Loop_Statement =>
+ Execute_For_Loop_Statement (Proc);
+
+ when Iir_Kind_While_Loop_Statement =>
+ Execute_While_Loop_Statement (Proc);
+
+ when Iir_Kind_Case_Statement =>
+ Execute_Case_Statement (Proc);
+
+ when Iir_Kind_Wait_Statement =>
+ if Execute_Wait_Statement (Instance, Stmt) then
+ return;
+ end if;
+ Update_Next_Statement (Proc);
+
+ when Iir_Kind_Procedure_Call_Statement =>
+ Execute_Call_Statement (Proc);
+
+ when Iir_Kind_Exit_Statement =>
+ Execute_Exit_Next_Statement (Proc, True);
+ when Iir_Kind_Next_Statement =>
+ Execute_Exit_Next_Statement (Proc, False);
+
+ when others =>
+ Error_Kind ("execute_sequential_statements", Stmt);
+ end case;
+ end loop;
+ end Execute_Sequential_Statements;
+end Execution;