-- 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 Errorout; use Errorout; with Trans_Analyzes; with Types; use Types; with Debugger; use Debugger; with Simulation.AMS.Debugger; with Areapools; use Areapools; with Grt.Stacks; with Grt.Signals; with Grt.Processes; with Grt.Main; with Grt.Errors; with Grt.Rtis; package body Simulation is function Value_To_Iir_Value (Mode : Mode_Type; Val : Value_Union) return Iir_Value_Literal_Acc is begin case Mode is when Mode_B2 => return Create_B2_Value (Val.B2); when Mode_E32 => return Create_E32_Value (Val.E32); when Mode_I64 => return Create_I64_Value (Val.I64); when Mode_F64 => return Create_F64_Value (Val.F64); when others => raise Internal_Error; -- FIXME end case; end Value_To_Iir_Value; procedure Iir_Value_To_Value (Src : Iir_Value_Literal_Acc; Dst : out Value_Union) is begin case Src.Kind is when Iir_Value_B2 => Dst.B2 := Src.B2; when Iir_Value_E32 => Dst.E32 := Src.E32; when Iir_Value_I64 => Dst.I64 := Src.I64; when Iir_Value_F64 => Dst.F64 := Src.F64; when others => raise Internal_Error; -- FIXME end case; end Iir_Value_To_Value; type Read_Signal_Flag_Enum is (Read_Signal_Event, Read_Signal_Active, -- In order to reuse the same code (that returns immediately if the -- attribute is true), we use not driving. Read_Signal_Not_Driving); function Read_Signal_Flag (Lit: Iir_Value_Literal_Acc; Kind : Read_Signal_Flag_Enum) return Boolean is begin case Lit.Kind is when Iir_Value_Array => for I in Lit.Val_Array.V'Range loop if Read_Signal_Flag (Lit.Val_Array.V (I), Kind) then return True; end if; end loop; return False; when Iir_Value_Record => for I in Lit.Val_Record.V'Range loop if Read_Signal_Flag (Lit.Val_Record.V (I), Kind) then return True; end if; end loop; return False; when Iir_Value_Signal => case Kind is when Read_Signal_Event => return Lit.Sig.Event; when Read_Signal_Active => return Lit.Sig.Active; when Read_Signal_Not_Driving => if Grt.Signals.Ghdl_Signal_Driving (Lit.Sig) = True then return False; else return True; end if; end case; when others => raise Internal_Error; end case; end Read_Signal_Flag; function Execute_Event_Attribute (Lit: Iir_Value_Literal_Acc) return Boolean is begin return Read_Signal_Flag (Lit, Read_Signal_Event); end Execute_Event_Attribute; function Execute_Active_Attribute (Lit: Iir_Value_Literal_Acc) return Boolean is begin return Read_Signal_Flag (Lit, Read_Signal_Active); end Execute_Active_Attribute; function Execute_Driving_Attribute (Lit: Iir_Value_Literal_Acc) return Boolean is begin return not Read_Signal_Flag (Lit, Read_Signal_Not_Driving); end Execute_Driving_Attribute; type Read_Signal_Value_Enum is (Read_Signal_Last_Value, -- For conversion functions. Read_Signal_Driving_Value, Read_Signal_Effective_Value, -- 'Driving_Value Read_Signal_Driver_Value); function Execute_Read_Signal_Value (Sig: Iir_Value_Literal_Acc; Attr : Read_Signal_Value_Enum) return Iir_Value_Literal_Acc is Res: Iir_Value_Literal_Acc; begin case Sig.Kind is when Iir_Value_Array => Res := Copy_Array_Bound (Sig); for I in Sig.Val_Array.V'Range loop Res.Val_Array.V (I) := Execute_Read_Signal_Value (Sig.Val_Array.V (I), Attr); end loop; return Res; when Iir_Value_Record => Res := Create_Record_Value (Sig.Val_Record.Len); for I in Sig.Val_Record.V'Range loop Res.Val_Record.V (I) := Execute_Read_Signal_Value (Sig.Val_Record.V (I), Attr); end loop; return Res; when Iir_Value_Signal => case Attr is when Read_Signal_Last_Value => return Value_To_Iir_Value (Sig.Sig.Mode, Sig.Sig.Last_Value); when Read_Signal_Driver_Value => case Sig.Sig.Mode is when Mode_F64 => return Create_F64_Value (Grt.Signals.Ghdl_Signal_Driving_Value_F64 (Sig.Sig)); when Mode_I64 => return Create_I64_Value (Grt.Signals.Ghdl_Signal_Driving_Value_I64 (Sig.Sig)); when Mode_E32 => return Create_E32_Value (Grt.Signals.Ghdl_Signal_Driving_Value_E32 (Sig.Sig)); when Mode_B2 => return Create_B2_Value (Grt.Signals.Ghdl_Signal_Driving_Value_B2 (Sig.Sig)); when others => raise Internal_Error; end case; when Read_Signal_Effective_Value => return Value_To_Iir_Value (Sig.Sig.Mode, Sig.Sig.Value); when Read_Signal_Driving_Value => return Value_To_Iir_Value (Sig.Sig.Mode, Sig.Sig.Driving_Value); end case; when others => raise Internal_Error; end case; end Execute_Read_Signal_Value; type Write_Signal_Enum is (Write_Signal_Driving_Value, Write_Signal_Effective_Value); procedure Execute_Write_Signal (Sig: Iir_Value_Literal_Acc; Val : Iir_Value_Literal_Acc; Attr : Write_Signal_Enum) is begin case Sig.Kind is when Iir_Value_Array => pragma Assert (Val.Kind = Iir_Value_Array); pragma Assert (Sig.Val_Array.Len = Val.Val_Array.Len); for I in Sig.Val_Array.V'Range loop Execute_Write_Signal (Sig.Val_Array.V (I), Val.Val_Array.V (I), Attr); end loop; when Iir_Value_Record => pragma Assert (Val.Kind = Iir_Value_Record); pragma Assert (Sig.Val_Record.Len = Val.Val_Record.Len); for I in Sig.Val_Record.V'Range loop Execute_Write_Signal (Sig.Val_Record.V (I), Val.Val_Record.V (I), Attr); end loop; when Iir_Value_Signal => pragma Assert (Val.Kind in Iir_Value_Scalars); case Attr is when Write_Signal_Driving_Value => Iir_Value_To_Value (Val, Sig.Sig.Driving_Value); when Write_Signal_Effective_Value => Iir_Value_To_Value (Val, Sig.Sig.Value); end case; when others => raise Internal_Error; end case; end Execute_Write_Signal; function Execute_Last_Value_Attribute (Indirect: Iir_Value_Literal_Acc) return Iir_Value_Literal_Acc is begin return Execute_Read_Signal_Value (Indirect, Read_Signal_Last_Value); end Execute_Last_Value_Attribute; function Execute_Driving_Value_Attribute (Indirect: Iir_Value_Literal_Acc) return Iir_Value_Literal_Acc is begin return Execute_Read_Signal_Value (Indirect, Read_Signal_Driver_Value); end Execute_Driving_Value_Attribute; type Signal_Read_Last_Type is (Read_Last_Event, Read_Last_Active); -- Return the Last_Event absolute time. function Execute_Read_Signal_Last (Indirect: Iir_Value_Literal_Acc; Kind : Signal_Read_Last_Type) return Ghdl_I64 is Res: Ghdl_I64; begin case Indirect.Kind is when Iir_Value_Array => Res := Ghdl_I64'First; for I in Indirect.Val_Array.V'Range loop Res := Ghdl_I64'Max (Res, Execute_Read_Signal_Last (Indirect.Val_Array.V (I), Kind)); end loop; return Res; when Iir_Value_Signal => case Kind is when Read_Last_Event => return Ghdl_I64 (Indirect.Sig.Last_Event); when Read_Last_Active => return Ghdl_I64 (Indirect.Sig.Last_Active); end case; when others => raise Internal_Error; end case; end Execute_Read_Signal_Last; function Execute_Last_Event_Attribute (Indirect: Iir_Value_Literal_Acc) return Ghdl_I64 is begin return Execute_Read_Signal_Last (Indirect, Read_Last_Event); end Execute_Last_Event_Attribute; function Execute_Last_Active_Attribute (Indirect: Iir_Value_Literal_Acc) return Ghdl_I64 is begin return Execute_Read_Signal_Last (Indirect, Read_Last_Active); end Execute_Last_Active_Attribute; function Execute_Signal_Value (Indirect: Iir_Value_Literal_Acc) return Iir_Value_Literal_Acc is Res: Iir_Value_Literal_Acc; begin case Indirect.Kind is when Iir_Value_Array => Res := Copy_Array_Bound (Indirect); for I in Indirect.Val_Array.V'Range loop Res.Val_Array.V (I) := Execute_Signal_Value (Indirect.Val_Array.V (I)); end loop; return Res; when Iir_Value_Record => Res := Create_Record_Value (Indirect.Val_Record.Len); for I in Indirect.Val_Record.V'Range loop Res.Val_Record.V (I) := Execute_Signal_Value (Indirect.Val_Record.V (I)); end loop; return Res; when Iir_Value_Signal => return Value_To_Iir_Value (Indirect.Sig.Mode, Indirect.Sig.Value); when others => raise Internal_Error; end case; end Execute_Signal_Value; procedure Assign_Value_To_Array_Signal (Instance: Block_Instance_Acc; Target: Iir_Value_Literal_Acc; Transactions: Transaction_Type) is Sub_Trans : Transaction_Type (Transactions.Len); begin Sub_Trans.Stmt := Transactions.Stmt; Sub_Trans.Reject := Transactions.Reject; for J in Target.Val_Array.V'Range loop for K in Transactions.Els'Range loop declare T : Transaction_El_Type renames Transactions.Els (K); S : Transaction_El_Type renames Sub_Trans.Els (K); begin S.After := T.After; if T.Value = null then S.Value := null; else S.Value := T.Value.Val_Array.V (J); end if; end; end loop; Assign_Value_To_Signal (Instance, Target.Val_Array.V (J), Sub_Trans); end loop; end Assign_Value_To_Array_Signal; procedure Assign_Value_To_Record_Signal (Instance: Block_Instance_Acc; Target: Iir_Value_Literal_Acc; Transactions: Transaction_Type) is Sub_Trans : Transaction_Type (Transactions.Len); begin Sub_Trans.Stmt := Transactions.Stmt; Sub_Trans.Reject := Transactions.Reject; for J in Target.Val_Record.V'Range loop for K in Transactions.Els'Range loop declare T : Transaction_El_Type renames Transactions.Els (K); S : Transaction_El_Type renames Sub_Trans.Els (K); begin S.After := T.After; if T.Value = null then S.Value := null; else S.Value := T.Value.Val_Record.V (J); end if; end; end loop; Assign_Value_To_Signal (Instance, Target.Val_Record.V (J), Sub_Trans); end loop; end Assign_Value_To_Record_Signal; procedure Assign_Value_To_Scalar_Signal (Instance: Block_Instance_Acc; Target: Iir_Value_Literal_Acc; Transactions: Transaction_Type) is pragma Unreferenced (Instance); use Grt.Signals; begin declare El : Transaction_El_Type renames Transactions.Els (1); begin if El.Value = null then Ghdl_Signal_Start_Assign_Null (Target.Sig, Transactions.Reject, El.After); if Transactions.Els'Last /= 1 then raise Internal_Error; end if; return; end if; -- FIXME: null transaction, check constraints. case Iir_Value_Scalars (El.Value.Kind) is when Iir_Value_B2 => Ghdl_Signal_Start_Assign_B2 (Target.Sig, Transactions.Reject, El.Value.B2, El.After); when Iir_Value_E32 => Ghdl_Signal_Start_Assign_E32 (Target.Sig, Transactions.Reject, El.Value.E32, El.After); when Iir_Value_I64 => Ghdl_Signal_Start_Assign_I64 (Target.Sig, Transactions.Reject, El.Value.I64, El.After); when Iir_Value_F64 => Ghdl_Signal_Start_Assign_F64 (Target.Sig, Transactions.Reject, El.Value.F64, El.After); end case; end; for I in 2 .. Transactions.Els'Last loop declare El : Transaction_El_Type renames Transactions.Els (I); begin case Iir_Value_Scalars (El.Value.Kind) is when Iir_Value_B2 => Ghdl_Signal_Next_Assign_B2 (Target.Sig, El.Value.B2, El.After); when Iir_Value_E32 => Ghdl_Signal_Next_Assign_E32 (Target.Sig, El.Value.E32, El.After); when Iir_Value_I64 => Ghdl_Signal_Next_Assign_I64 (Target.Sig, El.Value.I64, El.After); when Iir_Value_F64 => Ghdl_Signal_Next_Assign_F64 (Target.Sig, El.Value.F64, El.After); end case; end; end loop; end Assign_Value_To_Scalar_Signal; procedure Assign_Value_To_Signal (Instance: Block_Instance_Acc; Target: Iir_Value_Literal_Acc; Transaction: Transaction_Type) is begin case Target.Kind is when Iir_Value_Array => Assign_Value_To_Array_Signal (Instance, Target, Transaction); when Iir_Value_Record => Assign_Value_To_Record_Signal (Instance, Target, Transaction); when Iir_Value_Signal => Assign_Value_To_Scalar_Signal (Instance, Target, Transaction); when Iir_Value_Scalars | Iir_Value_Range | Iir_Value_File | Iir_Value_Access | Iir_Value_Protected | Iir_Value_Quantity | Iir_Value_Terminal => raise Internal_Error; end case; end Assign_Value_To_Signal; procedure Disconnect_Signal (Sig : Iir_Value_Literal_Acc) is begin case Sig.Kind is when Iir_Value_Array => for I in Sig.Val_Array.V'Range loop Disconnect_Signal (Sig.Val_Array.V (I)); end loop; when Iir_Value_Record => for I in Sig.Val_Array.V'Range loop Disconnect_Signal (Sig.Val_Record.V (I)); end loop; when Iir_Value_Signal => Grt.Signals.Ghdl_Signal_Disconnect (Sig.Sig); when others => raise Internal_Error; end case; end Disconnect_Signal; -- Call Ghdl_Process_Wait_Add_Sensitivity for each scalar subelement of -- SIG. procedure Wait_Add_Sensitivity (Sig: Iir_Value_Literal_Acc) is begin case Sig.Kind is when Iir_Value_Signal => Grt.Processes.Ghdl_Process_Wait_Add_Sensitivity (Sig.Sig); when Iir_Value_Array => for I in Sig.Val_Array.V'Range loop Wait_Add_Sensitivity (Sig.Val_Array.V (I)); end loop; when Iir_Value_Record => for I in Sig.Val_Record.V'Range loop Wait_Add_Sensitivity (Sig.Val_Record.V (I)); end loop; when others => raise Internal_Error; end case; end Wait_Add_Sensitivity; -- Return true if the process should be suspended. function Execute_Wait_Statement (Instance : Block_Instance_Acc; Stmt: Iir_Wait_Statement) return Boolean is Expr: Iir; El : Iir; List: Iir_List; Res: Iir_Value_Literal_Acc; Status : Boolean; Marker : Mark_Type; begin if not Instance.In_Wait_Flag then Mark (Marker, Expr_Pool); -- LRM93 8.1 -- The execution of a wait statement causes the time expression to -- be evaluated to determine the timeout interval. Expr := Get_Timeout_Clause (Stmt); if Expr /= Null_Iir then Res := Execute_Expression (Instance, Expr); Grt.Processes.Ghdl_Process_Wait_Set_Timeout (Std_Time (Res.I64)); end if; -- LRM93 8.1 -- The suspended process may also resume as a result of an event -- occuring on any signal in the sensitivity set of the wait -- statement. List := Get_Sensitivity_List (Stmt); if List /= Null_Iir_List then for J in Natural loop El := Get_Nth_Element (List, J); exit when El = Null_Iir; Wait_Add_Sensitivity (Execute_Name (Instance, El, True)); end loop; end if; -- LRM93 8.1 -- It also causes the execution of the corresponding process -- statement to be suspended. Grt.Processes.Ghdl_Process_Wait_Wait; Instance.In_Wait_Flag := True; Release (Marker, Expr_Pool); return True; else -- LRM93 8.1 -- The suspended process will resume, at the latest, immediately -- after the timeout interval has expired. if not Grt.Processes.Ghdl_Process_Wait_Has_Timeout then -- Compute the condition clause only if the timeout has not -- expired. -- LRM93 8.1 -- If such an event occurs, the condition in the condition clause -- is evaluated. -- -- if no condition clause appears, the condition clause until true -- is assumed. Status := Execute_Condition (Instance, Get_Condition_Clause (Stmt)); if not Status then -- LRM93 8.1 -- If the value of the condition is FALSE, the process will -- re-suspend. -- Such re-suspension does not involve the recalculation of -- the timeout interval. Grt.Processes.Ghdl_Process_Wait_Wait; return True; end if; end if; -- LRM93 8.1 -- If the value of the condition is TRUE, the process will resume. -- next statement. Grt.Processes.Ghdl_Process_Wait_Close; Instance.In_Wait_Flag := False; return False; end if; end Execute_Wait_Statement; function To_Instance_Acc is new Ada.Unchecked_Conversion (System.Address, Grt.Stacks.Instance_Acc); procedure Process_Executer (Self : Grt.Stacks.Instance_Acc); pragma Convention (C, Process_Executer); procedure Process_Executer (Self : Grt.Stacks.Instance_Acc) is function To_Process_State_Acc is new Ada.Unchecked_Conversion (Grt.Stacks.Instance_Acc, Process_State_Acc); Process : Process_State_Acc renames To_Process_State_Acc (Self); begin -- For debugger Current_Process := Process; Instance_Pool := Process.Pool'Access; if Trace_Simulation then Put (" run process: "); Disp_Instance_Name (Process.Top_Instance); Put_Line (" (" & Disp_Location (Process.Proc) & ")"); end if; Execute_Sequential_Statements (Process); -- Sanity checks. if not Is_Empty (Expr_Pool) then raise Internal_Error; end if; case Get_Kind (Process.Proc) is when Iir_Kind_Sensitized_Process_Statement => if Process.Instance.In_Wait_Flag then raise Internal_Error; end if; if Process.Instance.Stmt = Null_Iir then Process.Instance.Stmt := Get_Sequential_Statement_Chain (Process.Proc); end if; when Iir_Kind_Process_Statement => if not Process.Instance.In_Wait_Flag then raise Internal_Error; end if; when others => raise Internal_Error; end case; Instance_Pool := null; Current_Process := null; end Process_Executer; type Resolver_Read_Mode is (Read_Port, Read_Driver); function Resolver_Read_Value (Sig : Iir_Value_Literal_Acc; Mode : Resolver_Read_Mode; Index : Ghdl_Index_Type) return Iir_Value_Literal_Acc is use Grt.Signals; Val : Ghdl_Value_Ptr; Res : Iir_Value_Literal_Acc; begin case Sig.Kind is when Iir_Value_Array => Res := Copy_Array_Bound (Sig); for I in Sig.Val_Array.V'Range loop Res.Val_Array.V (I) := Resolver_Read_Value (Sig.Val_Array.V (I), Mode, Index); end loop; when Iir_Value_Record => Res := Create_Record_Value (Sig.Val_Record.Len); for I in Sig.Val_Record.V'Range loop Res.Val_Record.V (I) := Resolver_Read_Value (Sig.Val_Record.V (I), Mode, Index); end loop; when Iir_Value_Signal => case Mode is when Read_Port => Val := Ghdl_Signal_Read_Port (Sig.Sig, Index); when Read_Driver => Val := Ghdl_Signal_Read_Driver (Sig.Sig, Index); end case; Res := Value_To_Iir_Value (Sig.Sig.Mode, Val.all); when others => raise Internal_Error; end case; return Res; end Resolver_Read_Value; procedure Resolution_Proc (Instance_Addr : System.Address; Val : System.Address; Bool_Vec : System.Address; Vec_Len : Ghdl_Index_Type; Nbr_Drv : Ghdl_Index_Type; Nbr_Ports : Ghdl_Index_Type) is pragma Unreferenced (Val); Instance : Resolv_Instance_Type; pragma Import (Ada, Instance); for Instance'Address use Instance_Addr; type Bool_Array is array (1 .. Nbr_Drv) of Boolean; Vec : Bool_Array; pragma Import (Ada, Vec); for Vec'Address use Bool_Vec; Off : Iir_Index32; Arr : Iir_Value_Literal_Acc; Arr_Type : constant Iir := Get_Type (Get_Interface_Declaration_Chain (Instance.Func)); Res : Iir_Value_Literal_Acc; Len : constant Iir_Index32 := Iir_Index32 (Vec_Len + Nbr_Ports); Instance_Mark, Expr_Mark : Mark_Type; begin pragma Assert (Instance_Pool = null); Instance_Pool := Global_Pool'Access; Mark (Instance_Mark, Instance_Pool.all); Mark (Expr_Mark, Expr_Pool); Current_Process := No_Process; Arr := Create_Array_Value (Len, 1); Arr.Bounds.D (1) := Create_Bounds_From_Length (Instance.Block, Get_First_Element (Get_Index_Subtype_List (Arr_Type)), Len); -- First ports for I in 1 .. Nbr_Ports loop Arr.Val_Array.V (Iir_Index32 (I)) := Resolver_Read_Value (Instance.Sig, Read_Port, I - 1); end loop; -- Then drivers. Off := Iir_Index32 (Nbr_Ports) + 1; for I in 1 .. Nbr_Drv loop if Vec (I) then Arr.Val_Array.V (Off) := Resolver_Read_Value (Instance.Sig, Read_Driver, I - 1); Off := Off + 1; end if; end loop; -- Call resolution function. Res := Execute_Resolution_Function (Instance.Block, Instance.Func, Arr); -- Set driving value. Execute_Write_Signal (Instance.Sig, Res, Write_Signal_Driving_Value); Release (Instance_Mark, Instance_Pool.all); Release (Expr_Mark, Expr_Pool); Instance_Pool := null; end Resolution_Proc; type Convert_Mode is (Convert_In, Convert_Out); type Convert_Instance_Type is record Mode : Convert_Mode; Instance : Block_Instance_Acc; Func : Iir; Src : Iir_Value_Literal_Acc; Dst : Iir_Value_Literal_Acc; end record; type Convert_Instance_Acc is access Convert_Instance_Type; procedure Conversion_Proc (Data : System.Address) is Conv : Convert_Instance_Type; pragma Import (Ada, Conv); for Conv'Address use Data; Src : Iir_Value_Literal_Acc; Dst : Iir_Value_Literal_Acc; Expr_Mark : Mark_Type; begin pragma Assert (Instance_Pool = null); Instance_Pool := Global_Pool'Access; Mark (Expr_Mark, Expr_Pool); Current_Process := No_Process; case Conv.Mode is when Convert_In => Src := Execute_Read_Signal_Value (Conv.Src, Read_Signal_Effective_Value); when Convert_Out => Src := Execute_Read_Signal_Value (Conv.Src, Read_Signal_Driving_Value); end case; Dst := Execute_Assoc_Conversion (Conv.Instance, Conv.Func, Src); Check_Bounds (Conv.Dst, Dst, Conv.Func); case Conv.Mode is when Convert_In => Execute_Write_Signal (Conv.Dst, Dst, Write_Signal_Effective_Value); when Convert_Out => Execute_Write_Signal (Conv.Dst, Dst, Write_Signal_Driving_Value); end case; Release (Expr_Mark, Expr_Pool); Instance_Pool := null; end Conversion_Proc; function Guard_Func (Data : System.Address) return Ghdl_B2 is Guard : Guard_Instance_Type; pragma Import (Ada, Guard); for Guard'Address use Data; Val : Boolean; Prev_Instance_Pool : Areapool_Acc; begin pragma Assert (Instance_Pool = null or else Instance_Pool = Global_Pool'Access); Prev_Instance_Pool := Instance_Pool; Instance_Pool := Global_Pool'Access; Current_Process := No_Process; Val := Execute_Condition (Guard.Instance, Get_Guard_Expression (Guard.Guard)); Instance_Pool := Prev_Instance_Pool; return Ghdl_B2'Val (Boolean'Pos (Val)); end Guard_Func; -- Add a driver for signal designed by VAL (via index field) for instance -- INSTANCE of process PROC. -- FIXME: default value. procedure Add_Source (Instance: Block_Instance_Acc; Val: Iir_Value_Literal_Acc; Proc: Iir) is begin case Val.Kind is when Iir_Value_Signal => if Proc = Null_Iir then -- Can this happen ? raise Internal_Error; end if; Grt.Signals.Ghdl_Process_Add_Driver (Val.Sig); when Iir_Value_Array => for I in Val.Val_Array.V'Range loop Add_Source (Instance, Val.Val_Array.V (I), Proc); end loop; when Iir_Value_Record => for I in Val.Val_Record.V'Range loop Add_Source (Instance, Val.Val_Record.V (I), Proc); end loop; when others => raise Internal_Error; end case; end Add_Source; -- Add drivers for process PROC. -- Note: this is done recursively on the callees of PROC. procedure Elaborate_Drivers (Instance: Block_Instance_Acc; Proc: Iir) is Driver_List: Iir_List; El: Iir; Val: Iir_Value_Literal_Acc; Marker : Mark_Type; begin if Trace_Drivers then Ada.Text_IO.Put ("Drivers for "); Disp_Instance_Name (Instance); Ada.Text_IO.Put_Line (": " & Disp_Node (Proc)); end if; Driver_List := Trans_Analyzes.Extract_Drivers (Proc); -- Some processes have no driver list (assertion). if Driver_List = Null_Iir_List then return; end if; for I in Natural loop El := Get_Nth_Element (Driver_List, I); exit when El = Null_Iir; if Trace_Drivers then Put_Line (' ' & Disp_Node (El)); end if; Mark (Marker, Expr_Pool); Val := Execute_Name (Instance, El, True); Add_Source (Instance, Val, Proc); Release (Marker, Expr_Pool); end loop; end Elaborate_Drivers; -- Call Ghdl_Process_Add_Sensitivity for each scalar subelement of -- SIG. procedure Process_Add_Sensitivity (Sig: Iir_Value_Literal_Acc) is begin case Sig.Kind is when Iir_Value_Signal => Grt.Processes.Ghdl_Process_Add_Sensitivity (Sig.Sig); when Iir_Value_Array => for I in Sig.Val_Array.V'Range loop Process_Add_Sensitivity (Sig.Val_Array.V (I)); end loop; when Iir_Value_Record => for I in Sig.Val_Record.V'Range loop Process_Add_Sensitivity (Sig.Val_Record.V (I)); end loop; when others => raise Internal_Error; end case; end Process_Add_Sensitivity; procedure Create_Processes is use Grt.Processes; El : Iir; Instance : Block_Instance_Acc; Instance_Grt : Grt.Stacks.Instance_Acc; begin Processes_State := new Process_State_Array (1 .. Processes_Table.Last); for I in Processes_Table.First .. Processes_Table.Last loop Instance := Processes_Table.Table (I); El := Instance.Label; Instance_Pool := Processes_State (I).Pool'Access; Instance.Stmt := Get_Sequential_Statement_Chain (El); Processes_State (I).Top_Instance := Instance; Processes_State (I).Proc := El; Processes_State (I).Instance := Instance; Current_Process := Processes_State (I)'Access; Instance_Grt := To_Instance_Acc (Processes_State (I)'Address); case Get_Kind (El) is when Iir_Kind_Sensitized_Process_Statement => if Get_Postponed_Flag (El) then Ghdl_Postponed_Sensitized_Process_Register (Instance_Grt, Process_Executer'Access, null, System.Null_Address); else Ghdl_Sensitized_Process_Register (Instance_Grt, Process_Executer'Access, null, System.Null_Address); end if; -- Register sensitivity. declare Sig_List : Iir_List; Sig : Iir; Marker : Mark_Type; begin Sig_List := Get_Sensitivity_List (El); for J in Natural loop Sig := Get_Nth_Element (Sig_List, J); exit when Sig = Null_Iir; Mark (Marker, Expr_Pool); Process_Add_Sensitivity (Execute_Name (Instance, Sig, True)); Release (Marker, Expr_Pool); end loop; end; when Iir_Kind_Process_Statement => if Get_Postponed_Flag (El) then Ghdl_Postponed_Process_Register (Instance_Grt, Process_Executer'Access, null, System.Null_Address); else Ghdl_Process_Register (Instance_Grt, Process_Executer'Access, null, System.Null_Address); end if; when others => raise Internal_Error; end case; -- LRM93 §12.4.4 Other Concurrent Statements -- All other concurrent statements are either process -- statements or are statements for which there is an -- equivalent process statement. -- Elaboration of a process statement proceeds as follows: -- 1. The process declarative part is elaborated. Elaborate_Declarative_Part (Instance, Get_Declaration_Chain (El)); -- 2. The drivers required by the process statement -- are created. -- 3. The initial transaction defined by the default value -- associated with each scalar signal driven by the -- process statement is inserted into the corresponding -- driver. -- FIXME: do it for drivers in called subprograms too. Elaborate_Drivers (Instance, El); if not Is_Empty (Expr_Pool) then raise Internal_Error; end if; -- Elaboration of all concurrent signal assignment -- statements and concurrent assertion statements consists -- of the construction of the equivalent process statement -- followed by the elaboration of the equivalent process -- statement. -- [GHDL: this is done by canonicalize. ] -- FIXME: check passive statements, -- check no wait statement in sensitized processes. Instance_Pool := null; end loop; if Trace_Simulation then Disp_Signals_Value; end if; end Create_Processes; -- Configuration for the whole design Top_Config : Iir_Design_Unit; -- Elaborate the design procedure Ghdl_Elaborate; pragma Export (C, Ghdl_Elaborate, "__ghdl_ELABORATE"); procedure Set_Disconnection (Val : Iir_Value_Literal_Acc; Time : Iir_Value_Time) is begin case Val.Kind is when Iir_Value_Signal => Grt.Signals.Ghdl_Signal_Set_Disconnect (Val.Sig, Std_Time (Time)); when Iir_Value_Record => for I in Val.Val_Record.V'Range loop Set_Disconnection (Val.Val_Record.V (I), Time); end loop; when Iir_Value_Array => for I in Val.Val_Array.V'Range loop Set_Disconnection (Val.Val_Array.V (I), Time); end loop; when others => raise Internal_Error; end case; end Set_Disconnection; procedure Create_Disconnections is begin for I in Disconnection_Table.First .. Disconnection_Table.Last loop declare E : Disconnection_Entry renames Disconnection_Table.Table (I); begin Set_Disconnection (E.Sig, E.Time); end; end loop; end Create_Disconnections; type Connect_Mode is (Connect_Source, Connect_Effective); -- Add a driving value PORT to signal SIG, ie: PORT is a source for SIG. -- As a side effect, this connect the signal SIG with the port PORT. -- PORT is the formal, while SIG is the actual. procedure Connect (Sig: Iir_Value_Literal_Acc; Port: Iir_Value_Literal_Acc; Mode : Connect_Mode) is begin case Sig.Kind is when Iir_Value_Array => if Port.Kind /= Sig.Kind then raise Internal_Error; end if; if Sig.Val_Array.Len /= Port.Val_Array.Len then raise Internal_Error; end if; for I in Sig.Val_Array.V'Range loop Connect (Sig.Val_Array.V (I), Port.Val_Array.V (I), Mode); end loop; return; when Iir_Value_Record => if Port.Kind /= Sig.Kind then raise Internal_Error; end if; if Sig.Val_Record.Len /= Port.Val_Record.Len then raise Internal_Error; end if; for I in Sig.Val_Record.V'Range loop Connect (Sig.Val_Record.V (I), Port.Val_Record.V (I), Mode); end loop; return; when Iir_Value_Signal => case Port.Kind is when Iir_Value_Signal => -- Here, SIG and PORT are simple signals (not composite). -- PORT is a source for SIG. case Mode is when Connect_Source => Grt.Signals.Ghdl_Signal_Add_Source (Sig.Sig, Port.Sig); when Connect_Effective => Grt.Signals.Ghdl_Signal_Effective_Value (Port.Sig, Sig.Sig); end case; when Iir_Value_Access | Iir_Value_File | Iir_Value_Range | Iir_Value_Scalars -- FIXME: by value | Iir_Value_Record | Iir_Value_Array | Iir_Value_Protected | Iir_Value_Quantity | Iir_Value_Terminal => -- These cannot be driving value for a signal. raise Internal_Error; end case; when Iir_Value_E32 => if Mode = Connect_Source then raise Internal_Error; end if; Grt.Signals.Ghdl_Signal_Associate_E32 (Port.Sig, Sig.E32); when Iir_Value_I64 => if Mode = Connect_Source then raise Internal_Error; end if; Grt.Signals.Ghdl_Signal_Associate_I64 (Port.Sig, Sig.I64); when Iir_Value_B2 => if Mode = Connect_Source then raise Internal_Error; end if; Grt.Signals.Ghdl_Signal_Associate_B2 (Port.Sig, Sig.B2); when others => raise Internal_Error; end case; end Connect; function Get_Leftest_Signal (Val : Iir_Value_Literal_Acc) return Iir_Value_Literal_Acc is begin case Val.Kind is when Iir_Value_Signal => return Val; when Iir_Value_Array => return Get_Leftest_Signal (Val.Val_Array.V (1)); when Iir_Value_Record => return Get_Leftest_Signal (Val.Val_Record.V (1)); when others => raise Internal_Error; end case; end Get_Leftest_Signal; procedure Add_Conversion (Conv : Convert_Instance_Acc) is Src_Left : Grt.Signals.Ghdl_Signal_Ptr; Src_Len : Ghdl_Index_Type; Dst_Left : Grt.Signals.Ghdl_Signal_Ptr; Dst_Len : Ghdl_Index_Type; begin Conv.Src := Unshare_Bounds (Conv.Src, Instance_Pool); Conv.Dst := Unshare_Bounds (Conv.Dst, Instance_Pool); Src_Left := Get_Leftest_Signal (Conv.Src).Sig; Src_Len := Ghdl_Index_Type (Get_Nbr_Of_Scalars (Conv.Src)); Dst_Left := Get_Leftest_Signal (Conv.Dst).Sig; Dst_Len := Ghdl_Index_Type (Get_Nbr_Of_Scalars (Conv.Dst)); case Conv.Mode is when Convert_In => Grt.Signals.Ghdl_Signal_In_Conversion (Conversion_Proc'Address, Conv.all'Address, Src_Left, Src_Len, Dst_Left, Dst_Len); when Convert_Out => Grt.Signals.Ghdl_Signal_Out_Conversion (Conversion_Proc'Address, Conv.all'Address, Src_Left, Src_Len, Dst_Left, Dst_Len); end case; end Add_Conversion; function Create_Shadow_Signal (Sig : Iir_Value_Literal_Acc) return Iir_Value_Literal_Acc is begin case Sig.Kind is when Iir_Value_Signal => case Sig.Sig.Mode is when Mode_I64 => return Create_Signal_Value (Grt.Signals.Ghdl_Create_Signal_I64 (0, null, System.Null_Address)); when Mode_B2 => return Create_Signal_Value (Grt.Signals.Ghdl_Create_Signal_B2 (False, null, System.Null_Address)); when Mode_E32 => return Create_Signal_Value (Grt.Signals.Ghdl_Create_Signal_E32 (0, null, System.Null_Address)); when Mode_F64 => return Create_Signal_Value (Grt.Signals.Ghdl_Create_Signal_F64 (0.0, null, System.Null_Address)); when Mode_E8 | Mode_I32 => raise Internal_Error; end case; when Iir_Value_Array => declare Res : Iir_Value_Literal_Acc; begin Res := Unshare_Bounds (Sig, Instance_Pool); for I in Res.Val_Array.V'Range loop Res.Val_Array.V (I) := Create_Shadow_Signal (Sig.Val_Array.V (I)); end loop; return Res; end; when Iir_Value_Record => declare Res : Iir_Value_Literal_Acc; begin Res := Create_Record_Value (Sig.Val_Record.Len, Instance_Pool); for I in Res.Val_Record.V'Range loop Res.Val_Record.V (I) := Create_Shadow_Signal (Sig.Val_Record.V (I)); end loop; return Res; end; when Iir_Value_Scalars | Iir_Value_Access | Iir_Value_Range | Iir_Value_Protected | Iir_Value_Terminal | Iir_Value_Quantity | Iir_Value_File => raise Internal_Error; end case; end Create_Shadow_Signal; procedure Set_Connect (Formal_Instance : Block_Instance_Acc; Formal_Expr : Iir_Value_Literal_Acc; Local_Instance : Block_Instance_Acc; Local_Expr : Iir_Value_Literal_Acc; Assoc : Iir_Association_Element_By_Expression) is pragma Unreferenced (Formal_Instance); Formal : constant Iir := Get_Formal (Assoc); Inter : constant Iir := Get_Base_Name (Formal); begin if False and Trace_Elaboration then Put ("connect formal "); Put (Iir_Mode'Image (Get_Mode (Inter))); Put (" "); Disp_Iir_Value (Formal_Expr, Get_Type (Formal)); Put (" with actual "); Disp_Iir_Value (Local_Expr, Get_Type (Get_Actual (Assoc))); New_Line; end if; case Get_Mode (Inter) is when Iir_Out_Mode | Iir_Inout_Mode | Iir_Buffer_Mode | Iir_Linkage_Mode => -- FORMAL_EXPR is a source for LOCAL_EXPR. declare Out_Conv : constant Iir := Get_Out_Conversion (Assoc); Src : Iir_Value_Literal_Acc; begin if Out_Conv /= Null_Iir then Src := Create_Shadow_Signal (Local_Expr); Add_Conversion (new Convert_Instance_Type' (Mode => Convert_Out, Instance => Local_Instance, Func => Out_Conv, Src => Formal_Expr, Dst => Src)); else Src := Formal_Expr; end if; -- LRM93 §12.6.2 -- A signal is said to be active [...] if one of its source -- is active. Connect (Local_Expr, Src, Connect_Source); end; when Iir_In_Mode => null; when Iir_Unknown_Mode => raise Internal_Error; end case; case Get_Mode (Inter) is when Iir_In_Mode | Iir_Inout_Mode | Iir_Buffer_Mode | Iir_Linkage_Mode => declare In_Conv : constant Iir := Get_In_Conversion (Assoc); Src : Iir_Value_Literal_Acc; begin if In_Conv /= Null_Iir then Src := Create_Shadow_Signal (Formal_Expr); Add_Conversion (new Convert_Instance_Type' (Mode => Convert_In, Instance => Local_Instance, Func => Get_Implementation (In_Conv), Src => Local_Expr, Dst => Src)); else Src := Local_Expr; end if; Connect (Src, Formal_Expr, Connect_Effective); end; when Iir_Out_Mode => null; when Iir_Unknown_Mode => raise Internal_Error; end case; end Set_Connect; procedure Create_Connects is begin -- New signals may be created (because of conversions). Instance_Pool := Global_Pool'Access; for I in Connect_Table.First .. Connect_Table.Last loop declare E : Connect_Entry renames Connect_Table.Table (I); begin Set_Connect (E.Formal_Instance, E.Formal, E.Actual_Instance, E.Actual, E.Assoc); end; end loop; Instance_Pool := null; end Create_Connects; procedure Create_Guard_Signal (Instance : Block_Instance_Acc; Sig_Guard : Iir_Value_Literal_Acc; Guard : Iir) is procedure Add_Guard_Sensitivity (Sig : Iir_Value_Literal_Acc) is begin case Sig.Kind is when Iir_Value_Signal => Grt.Signals.Ghdl_Signal_Guard_Dependence (Sig.Sig); when Iir_Value_Array => for I in Sig.Val_Array.V'Range loop Add_Guard_Sensitivity (Sig.Val_Array.V (I)); end loop; when Iir_Value_Record => for I in Sig.Val_Record.V'Range loop Add_Guard_Sensitivity (Sig.Val_Record.V (I)); end loop; when others => raise Internal_Error; end case; end Add_Guard_Sensitivity; Dep_List : Iir_List; Dep : Iir; Data : Guard_Instance_Acc; begin Data := new Guard_Instance_Type'(Instance => Instance, Guard => Guard); Sig_Guard.Sig := Grt.Signals.Ghdl_Signal_Create_Guard (Data.all'Address, Guard_Func'Access); Dep_List := Get_Guard_Sensitivity_List (Guard); for I in Natural loop Dep := Get_Nth_Element (Dep_List, I); exit when Dep = Null_Iir; Add_Guard_Sensitivity (Execute_Name (Instance, Dep, True)); end loop; -- FIXME: free mem end Create_Guard_Signal; procedure Create_Implicit_Signal (Sig : Iir_Value_Literal_Acc; Time : Ghdl_I64; Prefix : Iir_Value_Literal_Acc; Kind : Signal_Type_Kind) is procedure Register_Prefix (Pfx : Iir_Value_Literal_Acc) is begin case Pfx.Kind is when Iir_Value_Signal => Grt.Signals.Ghdl_Signal_Attribute_Register_Prefix (Pfx.Sig); when Iir_Value_Array => for I in Pfx.Val_Array.V'Range loop Register_Prefix (Pfx.Val_Array.V (I)); end loop; when Iir_Value_Record => for I in Pfx.Val_Record.V'Range loop Register_Prefix (Pfx.Val_Record.V (I)); end loop; when others => raise Internal_Error; end case; end Register_Prefix; begin case Kind is when Implicit_Stable => Sig.Sig := Grt.Signals.Ghdl_Create_Stable_Signal (Std_Time (Time)); when Implicit_Quiet => Sig.Sig := Grt.Signals.Ghdl_Create_Quiet_Signal (Std_Time (Time)); when Implicit_Transaction => Sig.Sig := Grt.Signals.Ghdl_Create_Transaction_Signal; when others => raise Internal_Error; end case; Register_Prefix (Prefix); end Create_Implicit_Signal; procedure Create_Delayed_Signal (Sig : Iir_Value_Literal_Acc; Pfx : Iir_Value_Literal_Acc; Val : Std_Time) is begin case Pfx.Kind is when Iir_Value_Array => for I in Sig.Val_Array.V'Range loop Create_Delayed_Signal (Sig.Val_Array.V (I), Pfx.Val_Array.V (I), Val); end loop; when Iir_Value_Record => for I in Pfx.Val_Record.V'Range loop Create_Delayed_Signal (Sig.Val_Record.V (I), Pfx.Val_Array.V (I), Val); end loop; when Iir_Value_Signal => Sig.Sig := Grt.Signals.Ghdl_Create_Delayed_Signal (Pfx.Sig, Val); when others => raise Internal_Error; end case; end Create_Delayed_Signal; -- Create a new signal, using DEFAULT as initial value. -- Set its number. procedure Create_User_Signal (Block: Block_Instance_Acc; Signal: Iir; Sig : Iir_Value_Literal_Acc; Default : Iir_Value_Literal_Acc) is use Grt.Rtis; procedure Create_Signal (Lit: Iir_Value_Literal_Acc; Sig : Iir_Value_Literal_Acc; Sig_Type: Iir; Already_Resolved : Boolean) is Sub_Resolved : Boolean := Already_Resolved; Resolv_Func : Iir; Resolv_Instance : Resolv_Instance_Acc; begin if not Already_Resolved and then Get_Kind (Sig_Type) in Iir_Kinds_Subtype_Definition then Resolv_Func := Get_Resolution_Function (Sig_Type); else Resolv_Func := Null_Iir; end if; if Resolv_Func /= Null_Iir then Sub_Resolved := True; Resolv_Instance := new Resolv_Instance_Type' (Func => Get_Named_Entity (Resolv_Func), Block => Block, Sig => Sig); Grt.Signals.Ghdl_Signal_Create_Resolution (Resolution_Proc'Access, Resolv_Instance.all'Address, System.Null_Address, Ghdl_Index_Type (Get_Nbr_Of_Scalars (Lit))); end if; case Lit.Kind is when Iir_Value_Array => declare Sig_El_Type : constant Iir := Get_Element_Subtype (Get_Base_Type (Sig_Type)); begin for I in Lit.Val_Array.V'Range loop Create_Signal (Lit.Val_Array.V (I), Sig.Val_Array.V (I), Sig_El_Type, Sub_Resolved); end loop; end; when Iir_Value_Record => declare El : Iir_Element_Declaration; List : Iir_List; begin List := Get_Elements_Declaration_List (Get_Base_Type (Sig_Type)); for I in Lit.Val_Record.V'Range loop El := Get_Nth_Element (List, Natural (I - 1)); Create_Signal (Lit.Val_Record.V (I), Sig.Val_Record.V (I), Get_Type (El), Sub_Resolved); end loop; end; when Iir_Value_I64 => Sig.Sig := Grt.Signals.Ghdl_Create_Signal_I64 (Lit.I64, null, System.Null_Address); when Iir_Value_B2 => Sig.Sig := Grt.Signals.Ghdl_Create_Signal_B2 (Lit.B2, null, System.Null_Address); when Iir_Value_E32 => Sig.Sig := Grt.Signals.Ghdl_Create_Signal_E32 (Lit.E32, null, System.Null_Address); when Iir_Value_F64 => Sig.Sig := Grt.Signals.Ghdl_Create_Signal_F64 (Lit.F64, null, System.Null_Address); when Iir_Value_Signal | Iir_Value_Range | Iir_Value_File | Iir_Value_Access | Iir_Value_Protected | Iir_Value_Quantity | Iir_Value_Terminal => raise Internal_Error; end case; end Create_Signal; Sig_Type: constant Iir := Get_Type (Signal); Mode : Mode_Signal_Type; Kind : Kind_Signal_Type; type Iir_Mode_To_Mode_Signal_Type is array (Iir_Mode) of Mode_Signal_Type; Iir_Mode_To_Mode_Signal : constant Iir_Mode_To_Mode_Signal_Type := (Iir_Unknown_Mode => Mode_Signal, Iir_Linkage_Mode => Mode_Linkage, Iir_Buffer_Mode => Mode_Buffer, Iir_Out_Mode => Mode_Out, Iir_Inout_Mode => Mode_Inout, Iir_In_Mode => Mode_In); type Iir_Kind_To_Kind_Signal_Type is array (Iir_Signal_Kind) of Kind_Signal_Type; Iir_Kind_To_Kind_Signal : constant Iir_Kind_To_Kind_Signal_Type := (Iir_No_Signal_Kind => Kind_Signal_No, Iir_Register_Kind => Kind_Signal_Register, Iir_Bus_Kind => Kind_Signal_Bus); begin case Get_Kind (Signal) is when Iir_Kind_Signal_Interface_Declaration => Mode := Iir_Mode_To_Mode_Signal (Get_Mode (Signal)); when Iir_Kind_Signal_Declaration => Mode := Mode_Signal; when others => Error_Kind ("elaborate_signal", Signal); end case; Kind := Iir_Kind_To_Kind_Signal (Get_Signal_Kind (Signal)); Grt.Signals.Ghdl_Signal_Set_Mode (Mode, Kind, True); Create_Signal (Default, Sig, Sig_Type, False); end Create_User_Signal; procedure Create_Signals is begin for I in Signals_Table.First .. Signals_Table.Last loop declare E : Signal_Entry renames Signals_Table.Table (I); begin case E.Kind is when Guard_Signal => Create_Guard_Signal (E.Instance, E.Sig, E.Decl); when Implicit_Stable | Implicit_Quiet | Implicit_Transaction => Create_Implicit_Signal (E.Sig, E.Time, E.Prefix, E.Kind); when Implicit_Delayed => Create_Delayed_Signal (E.Sig, E.Prefix, Std_Time (E.Time)); when User_Signal => Create_User_Signal (E.Instance, E.Decl, E.Sig, E.Init); end case; end; end loop; end Create_Signals; procedure Ghdl_Elaborate is Entity: Iir_Entity_Declaration; -- Number of input ports of the top entity. In_Signals: Natural; El : Iir; begin Instance_Pool := Global_Pool'Access; Elaboration.Elaborate_Design (Top_Config); Entity := Get_Entity (Get_Library_Unit (Top_Config)); if not Is_Empty (Expr_Pool) then raise Internal_Error; end if; Instance_Pool := null; -- Be sure there is no IN ports in the top entity. El := Get_Port_Chain (Entity); In_Signals := 0; while El /= Null_Iir loop if Get_Mode (El) = Iir_In_Mode then In_Signals := In_Signals + 1; end if; El := Get_Chain (El); end loop; if In_Signals /= 0 then Error_Msg ("top entity should not have inputs signals"); -- raise Simulation_Error; end if; if Disp_Stats then Disp_Design_Stats; end if; if Disp_Ams then Simulation.AMS.Debugger.Disp_Characteristic_Expressions; end if; -- There is no inputs. -- All the simulation is done via time, so it must be displayed. Disp_Time_Before_Values := True; -- Initialisation. if Trace_Simulation then Put_Line ("Initialisation:"); end if; Create_Signals; Create_Connects; Create_Disconnections; Create_Processes; if Disp_Tree then Debugger.Disp_Instances_Tree; end if; if Flag_Interractive then Debug (Reason_Elab); end if; end Ghdl_Elaborate; procedure Simulation_Entity (Top_Conf : Iir_Design_Unit) is begin Top_Config := Top_Conf; Grt.Processes.One_Stack := True; Grt.Errors.Error_Hook := Debug_Error'Access; if Flag_Interractive then Debug (Reason_Start); end if; Grt.Main.Run; exception when Debugger_Quit => null; when Simulation_Finished => null; end Simulation_Entity; end Simulation;