diff options
author | Tristan Gingold <tgingold@free.fr> | 2022-09-25 06:34:09 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2022-09-25 11:43:28 +0200 |
commit | 27512f0110d640cd8631b8adfa4a83da72399c5c (patch) | |
tree | deef8b54599b0f0a4f3ba1e05238d987bfec4cba | |
parent | 548b2ff8d8e1e633853e3e4d25c5a6e0795cb3ee (diff) | |
download | ghdl-27512f0110d640cd8631b8adfa4a83da72399c5c.tar.gz ghdl-27512f0110d640cd8631b8adfa4a83da72399c5c.tar.bz2 ghdl-27512f0110d640cd8631b8adfa4a83da72399c5c.zip |
simul: gather disconnection specifications, create guard signal
-rw-r--r-- | src/simul/simul-vhdl_elab.adb | 109 | ||||
-rw-r--r-- | src/simul/simul-vhdl_elab.ads | 17 | ||||
-rw-r--r-- | src/simul/simul-vhdl_simul.adb | 98 | ||||
-rw-r--r-- | src/synth/elab-vhdl_stmts.adb | 6 |
4 files changed, 194 insertions, 36 deletions
diff --git a/src/simul/simul-vhdl_elab.adb b/src/simul/simul-vhdl_elab.adb index 1185b3cb7..0fd99b551 100644 --- a/src/simul/simul-vhdl_elab.adb +++ b/src/simul/simul-vhdl_elab.adb @@ -24,6 +24,7 @@ with Vhdl.Canon; with Synth.Vhdl_Stmts; with Synth.Vhdl_Decls; +with Synth.Vhdl_Expr; with Trans_Analyzes; with Simul.Vhdl_Debug; @@ -107,7 +108,7 @@ package body Simul.Vhdl_Elab is end; when Type_Record => declare - List : constant Iir_Flist := Get_Elements_Declaration_List + List : constant Node_Flist := Get_Elements_Declaration_List (Sig_Type); El : Iir_Element_Declaration; begin @@ -153,7 +154,7 @@ package body Simul.Vhdl_Elab is end if; E.Sig := null; - if E.Typ.W > 0 then + if E.Kind in Mode_Signal_User and then E.Typ.W > 0 then E.Nbr_Sources := new Nbr_Sources_Array'(0 .. E.Typ.W - 1 => (Nbr_Drivers => 0, @@ -170,6 +171,41 @@ package body Simul.Vhdl_Elab is Signals_Table.Table (Val.Val.S) := E; end Gather_Signal; + procedure Gather_Disconnection (Inst : Synth_Instance_Acc; Decl : Node) + is + List : constant Node_Flist := Get_Signal_List (Decl); + Marker : Mark_Type; + Name : Node; + Base_Vt : Valtyp; + Typ : Type_Acc; + Off : Value_Offsets; + Sig : Signal_Index_Type; + Tval : Valtyp; + T : Std_Time; + begin + Mark_Expr_Pool (Marker); + + Tval := Synth.Vhdl_Expr.Synth_Expression (Inst, Get_Expression (Decl)); + T := Std_Time (Read_Discrete (Tval)); + + for I in Flist_First .. Flist_Last (List) loop + Name := Get_Nth_Element (List, I); + Synth.Vhdl_Stmts.Synth_Assignment_Prefix + (Inst, Name, Base_Vt, Typ, Off); + Sig := Base_Vt.Val.S; + Typ := Unshare (Typ, Global_Pool'Access); + Disconnect_Table.Append + ((Sig => Sig, + Off => Off, + Typ => Typ, + Val => T, + Prev => Signals_Table.Table (Sig).Disconnect)); + Signals_Table.Table (Sig).Disconnect := Disconnect_Table.Last; + end loop; + + Release_Expr_Pool (Marker); + end Gather_Disconnection; + procedure Gather_Quantity (Inst : Synth_Instance_Acc; Decl : Node) is Val : constant Valtyp := Get_Value (Inst, Decl); @@ -206,28 +242,34 @@ package body Simul.Vhdl_Elab is when Iir_Linkage_Mode => Gather_Signal ((Mode_Linkage, Decl, Inst, null, null, null, No_Sensitivity_Index, No_Signal_Index, - No_Driver_Index, No_Connect_Index, null)); + No_Driver_Index, No_Connect_Index, + No_Disconnect_Index, null)); when Iir_Buffer_Mode => Gather_Signal ((Mode_Buffer, Decl, Inst, null, null, null, No_Sensitivity_Index, No_Signal_Index, - No_Driver_Index, No_Connect_Index, null)); + No_Driver_Index, No_Connect_Index, + No_Disconnect_Index, null)); when Iir_Out_Mode => Gather_Signal ((Mode_Out, Decl, Inst, null, null, null, No_Sensitivity_Index, No_Signal_Index, - No_Driver_Index, No_Connect_Index, null)); + No_Driver_Index, No_Connect_Index, + No_Disconnect_Index, null)); when Iir_Inout_Mode => Gather_Signal ((Mode_Inout, Decl, Inst, null, null, null, No_Sensitivity_Index, No_Signal_Index, - No_Driver_Index, No_Connect_Index, null)); + No_Driver_Index, No_Connect_Index, + No_Disconnect_Index, null)); when Iir_In_Mode => Gather_Signal ((Mode_In, Decl, Inst, null, null, null, No_Sensitivity_Index, No_Signal_Index, - No_Driver_Index, No_Connect_Index, null)); + No_Driver_Index, No_Connect_Index, + No_Disconnect_Index, null)); end case; when Iir_Kind_Signal_Declaration => Gather_Signal ((Mode_Signal, Decl, Inst, null, null, null, No_Sensitivity_Index, No_Signal_Index, - No_Driver_Index, No_Connect_Index, null)); + No_Driver_Index, No_Connect_Index, + No_Disconnect_Index, null)); when Iir_Kind_Configuration_Specification => null; when Iir_Kind_Free_Quantity_Declaration @@ -268,6 +310,8 @@ package body Simul.Vhdl_Elab is V := Get_Value (Inst, Decl); Convert_Type_Width (V.Typ); end; + when Iir_Kind_Disconnection_Specification => + Gather_Disconnection (Inst, Decl); when Iir_Kind_Variable_Declaration => pragma Assert (Get_Shared_Flag (Decl)); if Get_Default_Value (Decl) = Null_Node then @@ -846,7 +890,12 @@ package body Simul.Vhdl_Elab is when Iir_Kind_Block_Statement => declare Hdr : constant Node := Get_Block_Header (N); + Guard : constant Node := Get_Guard_Decl (N); begin + if Guard /= Null_Node then + Gather_Signal ((Mode_Guard, Guard, Inst, null, null, null, + No_Sensitivity_Index, No_Signal_Index)); + end if; if Hdr /= Null_Node then Gather_Processes_Decls (Inst, Get_Port_Chain (Hdr)); end if; @@ -916,27 +965,29 @@ package body Simul.Vhdl_Elab is Get_Kind (E.Decl) = Iir_Kind_Interface_Signal_Declaration and then Get_Mode (E.Decl) in Iir_Out_Modes; begin - for J in 1 .. E.Typ.W loop - declare - Ns : Nbr_Sources_Type renames E.Nbr_Sources (J - 1); - begin - Ns.Total := Ns.Nbr_Drivers + Ns.Nbr_Conns; - if Ns.Total = 0 and then Is_Out then - Ns.Total := 1; - end if; - if E.Collapsed_By /= No_Signal_Index then - -- Add to the parent. - declare - C_Ns : Nbr_Sources_Type renames - Signals_Table.Table (E.Collapsed_By) - .Nbr_Sources (J - 1); - begin - -- Remove 1 for the connection. - C_Ns.Total := C_Ns.Total + Ns.Total - 1; - end; - end if; - end; - end loop; + if E.Kind in Mode_Signal_User then + for J in 1 .. E.Typ.W loop + declare + Ns : Nbr_Sources_Type renames E.Nbr_Sources (J - 1); + begin + Ns.Total := Ns.Nbr_Drivers + Ns.Nbr_Conns; + if Ns.Total = 0 and then Is_Out then + Ns.Total := 1; + end if; + if E.Collapsed_By /= No_Signal_Index then + -- Add to the parent. + declare + C_Ns : Nbr_Sources_Type renames + Signals_Table.Table (E.Collapsed_By) + .Nbr_Sources (J - 1); + begin + -- Remove 1 for the connection. + C_Ns.Total := C_Ns.Total + Ns.Total - 1; + end; + end if; + end; + end loop; + end if; end; end loop; end Gather_Processes; diff --git a/src/simul/simul-vhdl_elab.ads b/src/simul/simul-vhdl_elab.ads index 8e6424b3c..233bad313 100644 --- a/src/simul/simul-vhdl_elab.ads +++ b/src/simul/simul-vhdl_elab.ads @@ -52,10 +52,12 @@ package Simul.Vhdl_Elab is type Process_Index_Type is new Nat32; type Driver_Index_Type is new Nat32; subtype Sensitivity_Index_Type is Driver_Index_Type; + type Disconnect_Index_Type is new Nat32; No_Process_Index : constant Process_Index_Type := 0; No_Driver_Index : constant Driver_Index_Type := 0; No_Sensitivity_Index : constant Sensitivity_Index_Type := 0; + No_Disconnect_Index : constant Disconnect_Index_Type := 0; type Proc_Record_Type is record Proc : Node; @@ -161,6 +163,7 @@ package Simul.Vhdl_Elab is when Mode_Signal_User => Drivers : Driver_Index_Type; Connect : Connect_Index_Type; + Disconnect : Disconnect_Index_Type; Nbr_Sources : Nbr_Sources_Arr_Acc; when Mode_Quiet | Mode_Stable | Mode_Delayed | Mode_Transaction => @@ -210,6 +213,20 @@ package Simul.Vhdl_Elab is Table_Low_Bound => No_Sensitivity_Index + 1, Table_Initial => 128); + type Disconnect_Entry is record + Sig : Signal_Index_Type; + Off : Value_Offsets; + Typ : Type_Acc; + Prev : Disconnect_Index_Type; + Val : Std_Time; + end record; + + package Disconnect_Table is new Tables + (Table_Component_Type => Disconnect_Entry, + Table_Index_Type => Disconnect_Index_Type, + Table_Low_Bound => No_Disconnect_Index + 1, + Table_Initial => 8); + type Scalar_Quantity_Index is new Uns32; No_Scalar_Quantity : constant Scalar_Quantity_Index := 0; diff --git a/src/simul/simul-vhdl_simul.adb b/src/simul/simul-vhdl_simul.adb index 5eeebe7b6..cae02fad7 100644 --- a/src/simul/simul-vhdl_simul.adb +++ b/src/simul/simul-vhdl_simul.adb @@ -2222,6 +2222,97 @@ package body Simul.Vhdl_Simul is Create_Signal (E.Val, 0, Sig_Type, E.Typ, E.Nbr_Sources.all, False); end Create_User_Signal; + type Guard_Instance_Type is record + Instance : Synth_Instance_Acc; + Guard : Iir; + end record; + + type Guard_Instance_Acc is access Guard_Instance_Type; + + function Guard_Func (Data : System.Address) return Ghdl_B1; + pragma Convention (C, Guard_Func); + + function Guard_Func (Data : System.Address) return Ghdl_B1 + is + use Areapools; + + Guard : Guard_Instance_Type; + pragma Import (Ada, Guard); + for Guard'Address use Data; + + Val : Boolean; + + Prev_Instance_Pool : constant Areapool_Acc := Instance_Pool; + begin + Instance_Pool := Process_Pool'Access; + + Val := Execute_Condition + (Guard.Instance, Get_Guard_Expression (Guard.Guard)); + + Instance_Pool := Prev_Instance_Pool; + + return Ghdl_B1'Val (Boolean'Pos (Val)); + end Guard_Func; + + procedure Add_Guard_Sensitivity (Typ : Type_Acc; Sig : Memory_Ptr) is + begin + case Typ.Kind is + when Type_Scalars => + Grt.Signals.Ghdl_Signal_Guard_Dependence (Read_Sig (Sig)); + when Type_Vector + | Type_Array => + declare + Len : constant Uns32 := Typ.Abound.Len; + begin + for I in 1 .. Len loop + Add_Guard_Sensitivity + (Typ.Arr_El, Sig_Index (Sig, (Len - I) * Typ.Arr_El.W)); + end loop; + end; + when Type_Record => + for I in Typ.Rec.E'Range loop + Add_Guard_Sensitivity + (Typ.Rec.E (I).Typ, + Sig_Index (Sig, Typ.Rec.E (I).Offs.Net_Off)); + end loop; + when others => + raise Internal_Error; + end case; + end Add_Guard_Sensitivity; + + procedure Create_Guard_Signal (Idx : Signal_Index_Type) + is + E : Signal_Entry renames Signals_Table.Table (Idx); + + Dep_List : Iir_List; + Dep_It : List_Iterator; + S : Ghdl_Signal_Ptr; + Data : Guard_Instance_Acc; + begin + Data := new Guard_Instance_Type'(Instance => E.Inst, Guard => E.Decl); + + S := Grt.Signals.Ghdl_Signal_Create_Guard + (To_Ghdl_Value_Ptr (To_Address (E.Val)), + Data.all'Address, Guard_Func'Access); + Write_Sig (E.Sig, S); + + Dep_List := Get_Guard_Sensitivity_List (E.Decl); + Dep_It := List_Iterate (Dep_List); + while Is_Valid (Dep_It) loop + declare + El : constant Node := Get_Element (Dep_It); + Sig_Mem : Memory_Ptr; + Info : Target_Info; + begin + Info := Synth_Target (E.Inst, El); + Sig_Mem := Signals_Table.Table (Info.Obj.Val.S).Sig; + Add_Guard_Sensitivity + (Info.Targ_Type, Sig_Index (Sig_Mem, Info.Off.Net_Off)); + end; + Next (Dep_It); + end loop; + end Create_Guard_Signal; + function Alloc_Signal_Memory (Vtype : Type_Acc) return Memory_Ptr is function To_Memory_Ptr is new Ada.Unchecked_Conversion @@ -2240,8 +2331,7 @@ package body Simul.Vhdl_Simul is E.Sig := Alloc_Signal_Memory (E.Typ); case E.Kind is when Mode_Guard => - -- Create_Guard_Signal (E.Instance, E.Sig, E.Val, E.Decl); - raise Internal_Error; + Create_Guard_Signal (Idx); when Mode_Stable | Mode_Quiet | Mode_Transaction => -- Create_Implicit_Signal -- (E.Sig, E.Val, E.Time, E.Prefix, E.Kind); @@ -2487,11 +2577,11 @@ package body Simul.Vhdl_Simul is Dst_Val := Create_Value_Memory (Val, Current_Pool); Dst_Val := Synth_Association_Conversion (Conv.Inst, Conv.Func, Dst_Val, Conv.Dst_Typ); - pragma Assert (Dst_Val.Typ.Wkind = Wkind_Sim); - if Dst_Val = No_Valtyp then Grt.Errors.Fatal_Error; end if; + + pragma Assert (Dst_Val.Typ.Wkind = Wkind_Sim); Convert_Type_Width (Dst_Val.Typ); Dst := Synth.Vhdl_Expr.Get_Value_Memtyp (Dst_Val); diff --git a/src/synth/elab-vhdl_stmts.adb b/src/synth/elab-vhdl_stmts.adb index 720db8ad3..def7e9218 100644 --- a/src/synth/elab-vhdl_stmts.adb +++ b/src/synth/elab-vhdl_stmts.adb @@ -197,6 +197,7 @@ package body Elab.Vhdl_Stmts is procedure Elab_Block_Statement (Syn_Inst : Synth_Instance_Acc; Blk : Node) is Hdr : constant Node := Get_Block_Header (Blk); + Guard : constant Node := Get_Guard_Decl (Blk); Blk_Inst : Synth_Instance_Acc; Assoc : Node; Inter : Node; @@ -207,9 +208,8 @@ package body Elab.Vhdl_Stmts is Blk_Inst := Make_Elab_Instance (Syn_Inst, Blk, Null_Iir); Create_Sub_Instance (Syn_Inst, Blk, Blk_Inst); - -- No support for guard. - if Get_Guard_Decl (Blk) /= Null_Node then - raise Internal_Error; + if Guard /= Null_Node then + Create_Signal (Blk_Inst, Guard, Boolean_Type, null); end if; if Hdr /= Null_Node then |