diff options
author | Tristan Gingold <tgingold@free.fr> | 2017-11-24 06:21:01 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2017-11-24 06:21:01 +0100 |
commit | 49294a83ee67eef83180721c578f69855bf96cad (patch) | |
tree | 89d3eab1be8bcc27a64340a6d69ad71a2b51adea /src/vhdl/simulate/execution.adb | |
parent | 947d5b8876198dda1cf8e0c65a554e5dbd5e80f2 (diff) | |
download | ghdl-49294a83ee67eef83180721c578f69855bf96cad.tar.gz ghdl-49294a83ee67eef83180721c578f69855bf96cad.tar.bz2 ghdl-49294a83ee67eef83180721c578f69855bf96cad.zip |
Create the simul.ads package (for a namespace).
Diffstat (limited to 'src/vhdl/simulate/execution.adb')
-rw-r--r-- | src/vhdl/simulate/execution.adb | 4831 |
1 files changed, 0 insertions, 4831 deletions
diff --git a/src/vhdl/simulate/execution.adb b/src/vhdl/simulate/execution.adb deleted file mode 100644 index dc4792490..000000000 --- a/src/vhdl/simulate/execution.adb +++ /dev/null @@ -1,4831 +0,0 @@ --- 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 Flags; use Flags; -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; -with Grt.Lib; -with Grt.Strings; -with Sem_Inst; - -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 (Msg : String; - Report : String; - Severity : Natural; - Stmt: Iir); - - function Get_Instance_By_Scope - (Instance: Block_Instance_Acc; Scope: Scope_Type) - return Block_Instance_Acc is - begin - case Scope.Kind is - when Scope_Kind_Frame => - declare - Current : Block_Instance_Acc; - Last : Block_Instance_Acc; - begin - Current := Instance; - while Current /= null loop - if Current.Block_Scope = Scope then - return Current; - end if; - Last := Current; - Current := Current.Up_Block; - end loop; - if Scope.Depth = 0 - and then Last.Block_Scope.Kind = Scope_Kind_Package - then - -- For instantiated packages. - return Last; - end if; - raise Internal_Error; - end; - when Scope_Kind_Package => - -- Global scope (packages) - return Package_Instances (Scope.Pkg_Index); - when Scope_Kind_Component => - pragma Assert (Current_Component /= null); - return Current_Component; - when Scope_Kind_None => - raise Internal_Error; - when Scope_Kind_Pkg_Inst => - raise Internal_Error; - end case; - end Get_Instance_By_Scope; - - function Get_Instance_For_Slot (Instance: Block_Instance_Acc; Decl: Iir) - return Block_Instance_Acc is - begin - return Get_Instance_By_Scope (Instance, Get_Info (Decl).Obj_Scope); - end Get_Instance_For_Slot; - - procedure Create_Right_Bound_From_Length - (Bounds : Iir_Value_Literal_Acc; Len : Iir_Index32) - is - begin - pragma Assert (Bounds.Right = null); - - case Bounds.Left.Kind is - when Iir_Value_E32 => - declare - R : Ghdl_E32; - begin - case Bounds.Dir is - when Iir_To => - R := Bounds.Left.E32 + Ghdl_E32 (Len - 1); - when Iir_Downto => - R := Bounds.Left.E32 - Ghdl_E32 (Len - 1); - end case; - Bounds.Right := Create_E32_Value (R); - end; - when Iir_Value_I64 => - declare - R : Ghdl_I64; - begin - case Bounds.Dir is - when Iir_To => - R := Bounds.Left.I64 + Ghdl_I64 (Len - 1); - when Iir_Downto => - R := Bounds.Left.I64 - Ghdl_I64 (Len - 1); - end case; - Bounds.Right := Create_I64_Value (R); - end; - when others => - raise Internal_Error; - end case; - end Create_Right_Bound_From_Length; - - 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 - Create_Right_Bound_From_Length (Res, Len); - 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 Iir_Value_Enums (Mode) is - when Iir_Value_E8 => - return Create_E8_Value (Ghdl_E8 (Pos)); - when Iir_Value_E32 => - return Create_E32_Value (Ghdl_E32 (Pos)); - when Iir_Value_B1 => - return Create_B1_Value (Ghdl_B1'Val (Pos)); - 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_E8_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_Flist := - Get_Enumeration_Literal_List (Get_Base_Type (Expr_Type)); - Pos : Natural; - begin - case Iir_Value_Enums (Val.Kind) is - when Iir_Value_B1 => - Pos := Ghdl_B1'Pos (Val.B1); - when Iir_Value_E8 => - Pos := Ghdl_E8'Pos (Val.E8); - when Iir_Value_E32 => - Pos := Ghdl_E32'Pos (Val.E32); - 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_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_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 - (Block, Get_Info (Name.Path_Instance).Frame_Scope); - - 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_Body => - Prepend (Rstr, Image (Get_Label (Get_Parent (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; - - 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 Assert_Std_Ulogic_Dc (Loc : Iir) - is - use Grt.Std_Logic_1164; - begin - Execute_Failed_Assertion - ("assertion", - "STD_LOGIC_1164: '-' operand for matching ordering operator", - 1, Loc); - end Assert_Std_Ulogic_Dc; - - procedure Check_Std_Ulogic_Dc (Loc : Iir; V : Grt.Std_Logic_1164.Std_Ulogic) - is - use Grt.Std_Logic_1164; - begin - if V = '-' then - Assert_Std_Ulogic_Dc (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); - - Imp : constant Iir := Strip_Denoting_Name (Get_Implementation (Expr)); - Func : constant Iir_Predefined_Functions := - Get_Implicit_Definition (Imp); - - -- 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; - begin - -- 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; - - if Func = Iir_Predefined_Array_Array_Concat - and then Left.Val_Array.Len = 0 - then - if Flags.Vhdl_Std = Vhdl_87 then - -- LRM87 7.2.3 - -- [...], unless the left operand is a null array, in - -- which case the result of the concatenation is the - -- right operand. - return Right; - else - -- LRM93 7.2.4 - -- If both operands are null arrays, then the result of - -- the concatenation is the right operand. - if Right.Val_Array.Len = 0 then - return Right; - end if; - end if; - end if; - - if Flags.Vhdl_Std = Vhdl_87 - and then (Func = Iir_Predefined_Array_Array_Concat - or Func = Iir_Predefined_Array_Element_Concat) - then - -- LRM87 7.2.3 Adding Operators - -- The left bound if this result is the left bound of the - -- left operand, [...]. The direction of the result is the - -- direction of the left operand, unless the left operand - -- is a null array, in which case the direction of the - -- result is that of the right operand. - Result := Create_Array_Value (Len, 1); - Result.Bounds.D (1) := Create_Range_Value - (Left.Bounds.D (1).Left, null, Left.Bounds.D (1).Dir, Len); - Create_Right_Bound_From_Length (Result.Bounds.D (1), Len); - else - -- Create the array result. - Result := Create_Array_Value (Len, 1); - Result.Bounds.D (1) := Create_Bounds_From_Length - (Block, - Get_Nth_Element (Get_Index_Subtype_List (Res_Type), 0), - Len); - end if; - - -- 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 - | Iir_Predefined_Enum_Less => - Eval_Right; - Result := Boolean_To_Lit (Compare_Value (Left, Right) < Equal); - when Iir_Predefined_Integer_Greater - | Iir_Predefined_Physical_Greater - | Iir_Predefined_Enum_Greater => - Eval_Right; - Result := Boolean_To_Lit (Compare_Value (Left, Right) > Equal); - when Iir_Predefined_Integer_Less_Equal - | Iir_Predefined_Physical_Less_Equal - | Iir_Predefined_Enum_Less_Equal => - Eval_Right; - Result := Boolean_To_Lit (Compare_Value (Left, Right) <= Equal); - when Iir_Predefined_Integer_Greater_Equal - | Iir_Predefined_Physical_Greater_Equal - | Iir_Predefined_Enum_Greater_Equal => - Eval_Right; - Result := Boolean_To_Lit (Compare_Value (Left, Right) >= Equal); - - 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_Flist := - 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 - Image (Id); - if Nam_Buffer (1) = '\' then - -- Reformat extended identifiers for to_image. - pragma Assert (Nam_Buffer (Nam_Length) = '\'); - declare - Npos : Natural; - K : Natural; - C : Character; - begin - Npos := 1; - K := 2; - while K < Nam_Length loop - C := Nam_Buffer (K); - Nam_Buffer (Npos) := C; - Npos := Npos + 1; - if C = '\' then - K := K + 2; - else - K := K + 1; - end if; - end loop; - Nam_Length := Npos - 1; - end; - end if; - Result := - String_To_Iir_Value (Nam_Buffer (1 .. Nam_Length)); - end if; - end if; - end; - - when Iir_Predefined_Array_Char_To_String => - declare - Lits : constant Iir_Flist := - Get_Enumeration_Literal_List - (Get_Base_Type - (Get_Element_Subtype (Get_Type (Left_Param)))); - Str : String (1 .. Natural (Left.Bounds.D (1).Length)); - 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_Format; - 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).E8); - 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_E8_Value - (Std_Ulogic'Pos - (Match_Eq_Table (Std_Ulogic'Val (Left.E8), - Std_Ulogic'Val (Right.E8)))); - end; - when Iir_Predefined_Std_Ulogic_Match_Inequality => - Eval_Right; - declare - use Grt.Std_Logic_1164; - begin - Result := Create_E8_Value - (Std_Ulogic'Pos - (Not_Table (Match_Eq_Table (Std_Ulogic'Val (Left.E8), - Std_Ulogic'Val (Right.E8))))); - 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.E8); - R : constant Std_Ulogic := Std_Ulogic'Val (Right.E8); - 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_E8_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'; - Le, Re : Std_Ulogic; - Has_Match_Err : Boolean; - begin - Has_Match_Err := False; - for I in Left.Val_Array.V'Range loop - Le := Std_Ulogic'Val (Left.Val_Array.V (I).E8); - Re := Std_Ulogic'Val (Right.Val_Array.V (I).E8); - if (Le = '-' or Re = '-') and then not Has_Match_Err then - Assert_Std_Ulogic_Dc (Expr); - Has_Match_Err := True; - end if; - Res := And_Table (Res, Match_Eq_Table (Le, Re)); - end loop; - if Func = Iir_Predefined_Std_Ulogic_Array_Match_Inequality then - Res := Not_Table (Res); - end if; - Result := Create_E8_Value (Std_Ulogic'Pos (Res)); - end; - - when others => - Error_Msg_Elab (Expr, "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 := 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 := 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 => - Grt.Lib.Ghdl_Control_Simulation - (Args (0).B1, Args (1).B1, Std_Integer (Args (2).I64)); - -- Do not return. - when Std_Names.Name_Textio_Write_Real => - File_Operation.Textio_Write_Real - (Args (0), Args (1), Args (2).F64, Std_Integer (Args (3).I64)); - 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 Iir_Value_Discrete (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_E8 => - case Bounds.Dir is - when Iir_To => - if Index.E8 >= Left_Pos.E8 and then - Index.E8 <= Right_Pos.E8 - then - -- to - return Iir_Index32 (Index.E8 - Left_Pos.E8); - end if; - when Iir_Downto => - if Index.E8 <= Left_Pos.E8 and then - Index.E8 >= Right_Pos.E8 - then - -- downto - return Iir_Index32 (Left_Pos.E8 - Index.E8); - 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; - 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 - -- Only for constrained subtypes. - pragma Assert (Get_Kind (A_Type) /= Iir_Kind_Array_Type_Definition); - - Index_List : constant Iir_Flist := Get_Index_Subtype_List (A_Type); - Res : Iir_Value_Literal_Acc; - Len : Iir_Index32; - Bound : Iir_Value_Literal_Acc; - begin - 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 - pragma Assert (Get_Kind (Str) = Iir_Kind_String_Literal8); - Id : constant String8_Id := Get_String8_Id (Str); - Len : constant Iir_Index32 := Iir_Index32 (Get_String_Length (Str)); - - El_Btype : constant Iir := Get_Base_Type (El_Type); - - Lit: Iir_Value_Literal_Acc; - El : Iir_Value_Literal_Acc; - Element_Mode : Iir_Value_Scalars; - - Pos : Nat8; - begin - Element_Mode := Get_Info (El_Btype).Scalar_Mode; - - Lit := Create_Array_Value (Len, 1); - - for I in Lit.Val_Array.V'Range loop - -- FIXME: use literal from type ?? - Pos := Str_Table.Element_String8 (Id, Pos32 (I)); - case Element_Mode is - when Iir_Value_B1 => - El := Create_B1_Value (Ghdl_B1'Val (Pos)); - when Iir_Value_E8 => - El := Create_E8_Value (Ghdl_E8'Val (Pos)); - when Iir_Value_E32 => - El := Create_E32_Value (Ghdl_E32'Val (Pos)); - when others => - raise Internal_Error; - end case; - Lit.Val_Array.V (I) := El; - end loop; - - 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 - Array_Type: constant Iir := Get_Type (Str); - Index_Types : constant Iir_Flist := Get_Index_Subtype_List (Array_Type); - Res : Iir_Value_Literal_Acc; - begin - -- Array must be unidimensional. - pragma Assert (Get_Nbr_Elements (Index_Types) = 1); - - 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_Nth_Element (Index_Types, 0)); - 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_Literal8 => - 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_Null_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_Flist := 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_Flist := - 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_Named_Entity (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_Flist := 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_Flist := - 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 - El_Type : constant Iir := Get_Element_Subtype (Aggregate_Type); - Index_List : constant Iir_Flist := - Get_Index_Subtype_List (Aggregate_Type); - Nbr_Dim : constant Iir_Index32 := - Iir_Index32 (Get_Nbr_Elements (Index_List)); - Res : Iir_Value_Literal_Acc; - 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 for prefix of ATTR. - function Execute_Indexes (Block: Block_Instance_Acc; Attr : Iir) - return Iir_Value_Literal_Acc - is - Prefix : constant Iir := Strip_Denoting_Name (Get_Prefix (Attr)); - Dim : constant Natural := - Evaluation.Eval_Attribute_Parameter_Or_1 (Attr); - 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)), Dim - 1); - return Execute_Bounds (Block, Index); - end; - 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 => - Bound := Execute_Indexes (Block, Prefix); - when Iir_Kind_Reverse_Range_Array_Attribute => - Bound := Execute_Indexes (Block, Prefix); - 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; - - 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; - Val : Iir_Value_Literal_Acc; - Target_Type : Iir; - Loc : Iir) - return Iir_Value_Literal_Acc - is - 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 Iir_Value_Numerics (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 (Loc); - end if; - Res := Create_I64_Value (Ghdl_I64 (Res.F64)); - end case; - when Iir_Kind_Floating_Type_Definition - | Iir_Kind_Floating_Subtype_Definition => - case Iir_Value_Numerics (Res.Kind) is - when Iir_Value_F64 => - null; - when Iir_Value_I64 => - Res := Create_F64_Value (Ghdl_F64 (Res.I64)); - end case; - when Iir_Kind_Enumeration_Type_Definition - | Iir_Kind_Enumeration_Subtype_Definition => - -- Must be same type. - null; - when Iir_Kind_Physical_Type_Definition - | Iir_Kind_Physical_Subtype_Definition => - -- Same type. - null; - when Iir_Kind_Record_Type_Definition - | Iir_Kind_Record_Subtype_Definition => - -- Same type. - null; - when Iir_Kind_Array_Subtype_Definition - | 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. - -- - -- 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. - if Get_Constraint_State (Target_Type) = Fully_Constrained then - Implicit_Array_Conversion (Block, Res, Target_Type, Loc); - else - declare - Idx_List : constant Iir_Flist := - Get_Index_Subtype_List (Target_Type); - Idx_Type : Iir; - begin - Res := Create_Array_Value (Val.Bounds.Nbr_Dims); - Res.Val_Array := Val.Val_Array; - for I in Val.Bounds.D'Range loop - Idx_Type := Get_Index_Type (Idx_List, Natural (I - 1)); - Res.Bounds.D (I) := Create_Range_Value - (Left => Execute_Type_Conversion - (Block, Val.Bounds.D (I).Left, Idx_Type, Loc), - Right => Execute_Type_Conversion - (Block, Val.Bounds.D (I).Right, Idx_Type, Loc), - Dir => Val.Bounds.D (I).Dir, - Length => Val.Bounds.D (I).Length); - end loop; - end; - end if; - when others => - Error_Kind ("execute_type_conversion", Target_Type); - end case; - Check_Constraints (Block, Res, Target_Type, Loc); - 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 Iir_Value_Discrete (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_E8 => - if Val.E8 = 0 then - Error_Msg_Constraint (Expr); - end if; - Res := Create_E8_Value (Val.E8 - 1); - 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); - 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 Iir_Value_Discrete (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_E8 => - if Val.E8 = Ghdl_E8'Last then - Error_Msg_Constraint (Expr); - end if; - Res := Create_E8_Value (Val.E8 + 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); - 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, False); - 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 - if Get_Kind (Base) = Iir_Kind_Object_Alias_Declaration then - Bblk := Get_Instance_By_Scope (Block, Info.Obj_Scope); - Base_Val := Execute_Signal_Init_Value (Bblk, Get_Name (Base)); - else - Bblk := Get_Instance_By_Scope (Block, Info.Obj_Scope); - Base_Val := Bblk.Objects (Info.Slot + 1); - end if; - Execute_Name_With_Base (Block, Expr, Base_Val, Res, Is_Sig); - pragma Assert (Is_Sig); - return Res; - end Execute_Signal_Init_Value; - - -- Indexed element will be at Pfx.Val_Array.V (Pos + 1) - procedure Execute_Indexed_Name (Block: Block_Instance_Acc; - Expr: Iir; - Pfx : Iir_Value_Literal_Acc; - Pos : out Iir_Index32) - is - pragma Assert (Get_Kind (Expr) = Iir_Kind_Indexed_Name); - Index_List : constant Iir_Flist := Get_Index_List (Expr); - Nbr_Dimensions : constant Iir_Index32 := - Iir_Index32 (Get_Nbr_Elements (Index_List)); - Index: Iir; - Value: Iir_Value_Literal_Acc; - Off : Iir_Index32; - begin - 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; - end Execute_Indexed_Name; - - -- Indexed element will be at Pfx.Val_Array.V (Pos) - procedure Execute_Slice_Name (Prefix_Array: Iir_Value_Literal_Acc; - Srange : Iir_Value_Literal_Acc; - Low : out Iir_Index32; - High : out Iir_Index32; - Loc : Iir) - is - Index_Order : Order; - -- Lower and upper bounds of the slice. - begin - pragma Assert (Prefix_Array /= null); - - -- 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", Loc); - 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), Loc); - High := Get_Index_Offset - (Srange.Right, Prefix_Array.Bounds.D (1), Loc); - end if; - end Execute_Slice_Name; - - 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_Interface_Signal_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 => - -- FIXME: add a flag ? - Is_Sig := Is_Signal_Object (Expr); - 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_Interface_Constant_Declaration - | Iir_Kind_Constant_Declaration - | Iir_Kind_Interface_Variable_Declaration - | Iir_Kind_Variable_Declaration - | Iir_Kind_Interface_File_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 (Block, Info.Obj_Scope); - Res := Slot_Block.Objects (Info.Slot); - end; - end if; - - when Iir_Kind_Indexed_Name => - declare - Pfx : Iir_Value_Literal_Acc; - Pos : Iir_Index32; - begin - Execute_Name_With_Base - (Block, Get_Prefix (Expr), Base, Pfx, Is_Sig); - Execute_Indexed_Name (Block, Expr, Pfx, Pos); - Res := Pfx.Val_Array.V (Pos + 1); - end; - - when Iir_Kind_Slice_Name => - declare - Prefix_Array: Iir_Value_Literal_Acc; - Srange : Iir_Value_Literal_Acc; - Low, High: Iir_Index32; - begin - Execute_Name_With_Base - (Block, Get_Prefix (Expr), Base, Prefix_Array, Is_Sig); - - Srange := Execute_Bounds (Block, Get_Suffix (Expr)); - Execute_Slice_Name (Prefix_Array, Srange, Low, High, Expr); - - 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 Iir_Kind_Image_Attribute => - Res := Execute_Image_Attribute (Block, Expr); - - when Iir_Kind_Path_Name_Attribute - | Iir_Kind_Instance_Name_Attribute => - Res := Execute_Path_Instance_Name_Attribute (Block, Expr); - - 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_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.Strings.Is_Whitespace (Str_Str (I)); - Unit_Len := Unit_Len + 1; - Str_Str (I) := Grt.Strings.To_Lower (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 (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 - Enums : constant Iir_Flist := - Get_Enumeration_Literal_List (Get_Base_Type (Expr_Type)); - Lit_Start : Ghdl_Index_Type; - Lit_End : Ghdl_Index_Type; - Enum : Iir; - Lit_Id : Name_Id; - Enum_Id : Name_Id; - begin - -- Remove leading and trailing blanks - for I in Str_Str'Range loop - if not Grt.Strings.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.Strings.Is_Whitespace (Str_Str (I)) then - Lit_End := I; - exit; - end if; - end loop; - - if Str_Str (Lit_Start) = ''' - and then Str_Str (Lit_End) = ''' - and then Lit_End = Lit_Start + 2 - then - -- Enumeration literal. - Lit_Id := Get_Identifier (Str_Str (Lit_Start + 1)); - - for I in Natural loop - Enum := Get_Nth_Element (Enums, I); - exit when Enum = Null_Iir; - exit when Get_Identifier (Enum) = Lit_Id; - end loop; - else - -- Literal identifier. - -- Convert to lower case. - for I in Lit_Start .. Lit_End loop - Str_Str (I) := Grt.Strings.To_Lower (Str_Str (I)); - end loop; - - for I in Natural loop - Enum := Get_Nth_Element (Enums, I); - exit when Enum = Null_Iir; - 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; - end if; - - if Enum = Null_Iir then - Error_Msg_Exec - ("incorrect enumeration literal for 'value", Expr); - end if; - - 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; - - -- 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_Interface_Signal_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_Interface_Constant_Declaration - | Iir_Kind_Constant_Declaration - | Iir_Kind_Interface_Variable_Declaration - | Iir_Kind_Variable_Declaration - | Iir_Kind_Interface_File_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 : constant Iir := Get_Implementation (Expr); - begin - if Get_Implicit_Definition (Imp) in Iir_Predefined_Explicit 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_Implementation (Expr); - Assoc : Iir; - Args : Iir_Array (0 .. 1); - begin - if Get_Implicit_Definition (Imp) in Iir_Predefined_Explicit 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_E8 => - return Create_E8_Value (Ghdl_E8'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_Literal8 => - 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, Execute_Expression (Block, Get_Expression (Expr)), - Get_Type (Expr), 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)), - Init_Value_Default); - 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, Expr); - return Execute_High_Limit (Res); - - when Iir_Kind_Low_Array_Attribute => - Res := Execute_Indexes (Block, Expr); - return Execute_Low_Limit (Res); - - when Iir_Kind_Left_Array_Attribute => - Res := Execute_Indexes (Block, Expr); - return Execute_Left_Limit (Res); - - when Iir_Kind_Right_Array_Attribute => - Res := Execute_Indexes (Block, Expr); - return Execute_Right_Limit (Res); - - when Iir_Kind_Length_Array_Attribute => - Res := Execute_Indexes (Block, Expr); - return Execute_Length (Res); - - when Iir_Kind_Ascending_Array_Attribute => - Res := Execute_Indexes (Block, 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 Iir_Value_Discrete (Mode) is - when Iir_Value_I64 => - null; - when Iir_Value_E8 => - Res := Create_E8_Value (Ghdl_E8 (Res.I64)); - 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)); - 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 Iir_Value_Discrete (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_E8 => - N_Res := Create_I64_Value (Ghdl_I64 (Res.E8)); - Res := N_Res; - when Iir_Value_E32 => - N_Res := Create_I64_Value (Ghdl_I64 (Res.E32)); - Res := N_Res; - 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; - Prot_Obj : 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; - Up_Info : Sim_Info_Acc; - Res : Block_Instance_Acc; - - Origin : Iir; - Label : Iir; - begin - pragma Assert (Get_Kind (Imp) in Iir_Kinds_Subprogram_Declaration - or else Get_Kind (Imp) = Iir_Kind_Protected_Type_Body); - - if Prot_Obj /= null then - Up_Block := Prot_Obj; - Label := Imp; - else - Up_Info := Get_Info (Get_Parent (Imp)); - Up_Block := Get_Instance_By_Scope (Instance, Up_Info.Frame_Scope); - - Origin := Sem_Inst.Get_Origin (Imp); - if Origin /= Null_Iir then - -- Call to a subprogram of an instantiated package. - -- For a generic package, only the spec is instantiated, the body - -- is shared by all the instances. - - -- Execute code of the 'shared' body - Label := Origin; - - -- Get the real instance for package interface. - if Up_Info.Kind = Kind_Environment then - Up_Block := Environment_Table.Table - (Up_Block.Objects (Up_Info.Env_Slot).Environment); - end if; - else - Label := Imp; - end if; - end if; - - Res := To_Block_Instance_Acc - (Alloc_Block_Instance - (Instance_Pool, - Block_Instance_Type'(Max_Objs => Func_Info.Nbr_Objects, - Id => No_Block_Instance_Id, - Block_Scope => Get_Info (Label).Frame_Scope, - Up_Block => Up_Block, - Label => Label, - Stmt => Null_Iir, - Parent => Instance, - Children => null, - Brother => null, - Ports_Map => Null_Iir, - 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) - return Iir_Value_Literal_Acc - is - Subprg_Body : constant Iir := Get_Subprogram_Body (Instance.Label); - 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", - Instance.Label); - 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, null, 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); - 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_Implementation (Conv), Val); - when Iir_Kind_Type_Conversion => - -- FIXME: shouldn't CONV always be a denoting_name ? - return Execute_Type_Conversion (Block, Val, Get_Type (Conv), Conv); - when Iir_Kinds_Denoting_Name - | Iir_Kind_Function_Declaration => - Ent := Strip_Denoting_Name (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, Val, Get_Type (Ent), Ent); - 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; - - procedure Associate_By_Reference (Block : Block_Instance_Acc; - Formal : Iir; - Formal_Base : Iir_Value_Literal_Acc; - Actual : Iir_Value_Literal_Acc) - is - Prefix : constant Iir := Strip_Denoting_Name (Get_Prefix (Formal)); - Is_Sig : Boolean; - Pfx : Iir_Value_Literal_Acc; - Pos : Iir_Index32; - begin - if Get_Kind (Prefix) = Iir_Kind_Slice_Name then - -- That case is not handled correctly. - raise Program_Error; - end if; - Execute_Name_With_Base (Block, Prefix, Formal_Base, Pfx, Is_Sig); - - case Get_Kind (Formal) is - when Iir_Kind_Indexed_Name => - Execute_Indexed_Name (Block, Formal, Pfx, Pos); - Store (Pfx.Val_Array.V (Pos + 1), Actual); - when Iir_Kind_Slice_Name => - declare - Low, High : Iir_Index32; - Srange : Iir_Value_Literal_Acc; - begin - Srange := Execute_Bounds (Block, Get_Suffix (Formal)); - Execute_Slice_Name (Pfx, Srange, Low, High, Formal); - for I in 1 .. High - Low + 1 loop - Store (Pfx.Val_Array.V (Low + I), Actual.Val_Array.V (I)); - end loop; - end; - when Iir_Kind_Selected_Element => - Pos := Get_Element_Position (Get_Selected_Element (Formal)); - Store (Pfx.Val_Record.V (Pos + 1), Actual); - when others => - Error_Kind ("associate_by_reference", Formal); - end case; - end Associate_By_Reference; - - -- 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; - Inter_Chain : Iir; - Assoc_Chain : Iir) - is - Nbr_Assoc : constant Natural := Get_Chain_Length (Assoc_Chain); - Assoc: Iir; - Assoc_Inter : 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_Inter := Inter_Chain; - Assoc_Idx := 1; - while Assoc /= Null_Iir loop - Inter := Get_Association_Interface (Assoc, Assoc_Inter); - Formal := Get_Association_Formal (Assoc, Inter); - - -- 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 => - -- Directly create the whole value on the instance pool, as its - -- life is longer than the statement. - if Get_Kind (Inter) = Iir_Kind_Interface_Signal_Declaration then - Last_Individual := Create_Value_For_Type - (Out_Block, Get_Actual_Type (Assoc), Init_Value_Signal); - else - Last_Individual := Create_Value_For_Type - (Out_Block, Get_Actual_Type (Assoc), Init_Value_Any); - end if; - 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_Interface_Constant_Declaration - | Iir_Kind_Interface_File_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_Interface_Signal_Declaration => - Val := Execute_Name (Out_Block, Actual, True); - Implicit_Array_Conversion - (Subprg_Block, Val, Get_Type (Formal), Assoc); - when Iir_Kind_Interface_Variable_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_Formal_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), Init_Value_Default); - elsif Get_Kind (Get_Type (Formal)) in - Iir_Kinds_Scalar_Type_And_Subtype_Definition - then - -- These are passed by value. Must be reset. - Val := Create_Value_For_Type - (Out_Block, Get_Type (Formal), Init_Value_Default); - end if; - else - if Get_Kind (Assoc) = - Iir_Kind_Association_Element_By_Expression - then - Conv := Get_Actual_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_Interface_Constant_Declaration - | Iir_Kind_Interface_Variable_Declaration - | Iir_Kind_Interface_File_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_Interface_Signal_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 - Associate_By_Reference - (Subprg_Block, Formal, Last_Individual, Val); - end if; - - << Continue >> null; - Next_Association_Interface (Assoc, Assoc_Inter); - Assoc_Idx := Assoc_Idx + 1; - end loop; - - Release (Marker, Expr_Pool); - end Execute_Association; - - procedure Execute_Back_Association (Instance : Block_Instance_Acc) - is - Call : constant Iir := Get_Procedure_Call (Instance.Parent.Stmt); - Imp : constant Iir := Get_Implementation (Call); - Assoc : Iir; - Assoc_Inter : Iir; - Inter : Iir; - Formal : Iir; - Assoc_Idx : Iir_Index32; - begin - Assoc := Get_Parameter_Association_Chain (Call); - Assoc_Inter := Get_Interface_Declaration_Chain (Imp); - Assoc_Idx := 1; - while Assoc /= Null_Iir loop - if Get_Kind (Assoc) /= Iir_Kind_Association_Element_By_Individual then - Inter := Get_Association_Interface (Assoc, Assoc_Inter); - Formal := Get_Association_Formal (Assoc, Inter); - - case Get_Kind (Inter) is - when Iir_Kind_Interface_Variable_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_Formal_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_Interface_File_Declaration => - null; - when Iir_Kind_Interface_Signal_Declaration - | Iir_Kind_Interface_Constant_Declaration => - null; - when others => - Error_Kind ("execute_back_association", Inter); - end case; - end if; - Next_Association_Interface (Assoc, Assoc_Inter); - Assoc_Idx := Assoc_Idx + 1; - end loop; - end Execute_Back_Association; - - function Get_Protected_Object_Instance - (Block : Block_Instance_Acc; Call : Iir) return Block_Instance_Acc - is - Meth_Obj : constant Iir := Get_Method_Object (Call); - Obj : Iir_Value_Literal_Acc; - begin - if Meth_Obj = Null_Iir then - return null; - else - Obj := Execute_Name (Block, Meth_Obj, True); - return Protected_Table.Table (Obj.Prot); - end if; - end Get_Protected_Object_Instance; - - function Execute_Foreign_Function_Call - (Block: Block_Instance_Acc; Expr : Iir; Imp : Iir) - return Iir_Value_Literal_Acc - is - Res : Iir_Value_Literal_Acc; - begin - case Get_Identifier (Imp) is - when Std_Names.Name_Get_Resolution_Limit => - Res := Create_I64_Value - (Ghdl_I64 - (Evaluation.Get_Physical_Value (Std_Package.Time_Base))); - when Std_Names.Name_Textio_Read_Real => - Res := Create_F64_Value - (File_Operation.Textio_Read_Real (Block.Objects (1))); - when others => - Error_Msg_Exec ("unsupported foreign function call", Expr); - end case; - return Res; - 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; - Prot_Block : Block_Instance_Acc; - Assoc_Chain: Iir; - Res : Iir_Value_Literal_Acc; - begin - Mark (Block.Marker, Instance_Pool.all); - - case Get_Kind (Expr) is - when Iir_Kind_Function_Call => - Prot_Block := Get_Protected_Object_Instance (Block, Expr); - Subprg_Block := - Create_Subprogram_Instance (Block, Prot_Block, Imp); - Assoc_Chain := Get_Parameter_Association_Chain (Expr); - Execute_Association - (Block, Subprg_Block, Inter_Chain, Assoc_Chain); - -- No out/inout interface for functions. - pragma Assert (Subprg_Block.Actuals_Ref = null); - when Iir_Kinds_Dyadic_Operator => - Subprg_Block := Create_Subprogram_Instance (Block, null, Imp); - Execute_Dyadic_Association - (Block, Subprg_Block, Expr, Inter_Chain); - when Iir_Kinds_Monadic_Operator => - Subprg_Block := Create_Subprogram_Instance (Block, null, Imp); - 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); - 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_Flist; - 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 Iir_Value_Scalars (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_E8 => - if Value.E8 in Low.E8 .. High.E8 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; - 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 - List : constant Iir_Flist := - Get_Elements_Declaration_List (Get_Base_Type (Def)); - El : Iir_Element_Declaration; - begin - for I in Flist_First .. Flist_Last (List) loop - El := Get_Nth_Element (List, I); - 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, null, Imp); - - Inter := Get_Interface_Declaration_Chain (Imp); - Elaboration.Create_Object (Instance, Inter); - Instance.Objects (Get_Info (Inter).Slot) := Arr; - - return Execute_Function_Body (Instance); - 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; - - -- 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 (Msg : String; - 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. - Put (Standard_Error, Disp_Location (Stmt)); - - -- 1: an indication that this message is from an assertion. - Put (Standard_Error, '('); - Put (Standard_Error, Msg); - Put (Standard_Error, ' '); - - -- 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 - (Instance: Block_Instance_Acc; - Label : String; - Stmt : Iir; - Default_Msg : String; - 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.E8); - else - Severity := Default_Severity; - end if; - 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).E8); - end loop; - Execute_Failed_Assertion (Label, Msg, Severity, Stmt); - end; - else - Execute_Failed_Assertion (Label, Default_Msg, Severity, Stmt); - end if; - Release (Marker, Expr_Pool); - end Execute_Failed_Assertion; - - 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 Iir_Value_Discrete (Val.Kind) is - when Iir_Value_E8 => - return Val.E8 >= Min.E8 and Val.E8 <= Max.E8; - 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; - 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 Iir_Value_Discrete (Val.Kind) is - when Iir_Value_E8 => - case Bounds.Dir is - when Iir_To => - Val.E8 := Val.E8 + 1; - when Iir_Downto => - Val.E8 := Val.E8 - 1; - end case; - 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; - 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_Null_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_Implementation (Call); - Subprg_Instance : Block_Instance_Acc; - Prot_Block : Block_Instance_Acc; - Assoc_Chain: Iir; - Inter_Chain : Iir; - Subprg_Body : Iir; - begin - if Get_Implicit_Definition (Imp) in Iir_Predefined_Implicit 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); - Prot_Block := Get_Protected_Object_Instance (Instance, Call); - Subprg_Instance := - Create_Subprogram_Instance (Instance, Prot_Block, Imp); - Assoc_Chain := Get_Parameter_Association_Chain (Call); - Inter_Chain := Get_Interface_Declaration_Chain (Imp); - Execute_Association - (Instance, Subprg_Instance, Inter_Chain, 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_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_Simple_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_Failed_Assertion (Instance, "assertion", Stmt, - "Assertion violation.", 2); - end if; - end; - Update_Next_Statement (Proc); - - when Iir_Kind_Report_Statement => - Execute_Failed_Assertion (Instance, "report", Stmt, - "Assertion violation.", 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; |