📄 grt-signals.adb
字号:
procedure Mark_Active (Sig : Ghdl_Signal_Ptr); pragma Inline (Mark_Active); procedure Mark_Active (Sig : Ghdl_Signal_Ptr) is begin if Sig.Active then Internal_Error ("mark_active"); end if; Sig.Active := True; Sig.Last_Active := Current_Time; Sig.Alink := Clear_List; Clear_List := Sig; end Mark_Active; type Resolver_Acc is access procedure (Instance : System.Address; Val : System.Address; Bool_Vec : System.Address; Vec_Len : Ghdl_Index_Type; Nbr_Drv : Ghdl_Index_Type; Nbr_Ports : Ghdl_Index_Type); function To_Resolver_Acc is new Ada.Unchecked_Conversion (Source => System.Address, Target => Resolver_Acc); procedure Compute_Resolved_Signal (Resolv : Resolved_Signal_Acc) is Sig : Ghdl_Signal_Ptr := Sig_Table.Table (Resolv.Sig_Range.First); Length : Ghdl_Index_Type; type Bool_Array_Type is array (1 .. Sig.S.Nbr_Drivers) of Boolean; Vec : Bool_Array_Type; begin -- Compute number of non-null drivers. Length := 0; for I in 1 .. Sig.S.Nbr_Drivers loop case Sig.S.Drivers (I - 1).First_Trans.Kind is when Trans_Value => Length := Length + 1; Vec (I) := True; when Trans_Null => Vec (I) := False; when Trans_Error => Error ("range check error"); end case; end loop; -- Check driving condition on all signals. for J in Resolv.Sig_Range.First + 1.. Resolv.Sig_Range.Last loop for I in 1 .. Sig.S.Nbr_Drivers loop if (Sig_Table.Table (J).S.Drivers (I - 1).First_Trans.Kind /= Trans_Null) xor Vec (I) then Error ("null-transaction required"); end if; end loop; end loop; -- if no driving sources and register, exit. if Length = 0 and then Sig.Nbr_Ports = 0 and then ((Sig.Rti.Common.Mode and Ghdl_Rti_Signal_Kind_Mask) = Ghdl_Rti_Signal_Kind_Register) then return; end if; -- Call the procedure. To_Resolver_Acc (Resolv.Resolv_Proc).all (Resolv.Resolv_Inst, Resolv.Resolv_Ptr, Vec'Address, Length, Sig.S.Nbr_Drivers, Sig.Nbr_Ports); end Compute_Resolved_Signal; type Conversion_Func_Acc is access procedure (Instance : System.Address); function To_Conversion_Func_Acc is new Ada.Unchecked_Conversion (Source => System.Address, Target => Conversion_Func_Acc); procedure Call_Conversion_Function (Conv : Sig_Conversion_Acc) is F : Conversion_Func_Acc; begin F := To_Conversion_Func_Acc (Conv.Func); F.all (Conv.Instance); end Call_Conversion_Function; procedure Resume_Process_If_Event (Sig : Ghdl_Signal_Ptr; Proc : Process_Id) is El : Action_List_Acc; begin El := new Action_List'(Kind => Action_Process, Proc => Proc, Next => Sig.Event_List); Sig.Event_List := El; end Resume_Process_If_Event; -- Order of signals: -- To be computed: driving value or/and effective value -- To be considered: ports, signals, implicit signals, resolution, -- conversion -- procedure Add_Propagation (P : Propagation_Type) is begin Propagation.Increment_Last; Propagation.Table (Propagation.Last) := P; end Add_Propagation; -- Put SIG in PROPAGATION table until ORDER level. procedure Order_Signal (Sig : Ghdl_Signal_Ptr; Order : Propag_Order_Flag); -- Return TRUE is the effective value of SIG is the driving value of SIG. function Is_Eff_Drv (Sig : Ghdl_Signal_Ptr) return Boolean is begin case Sig.S.Mode_Sig is when Mode_Signal | Mode_Buffer => return True; when Mode_Linkage | Mode_Out => -- No effective value. return False; when Mode_Inout | Mode_In => if Sig.S.Effective = null then if Sig.S.Nbr_Drivers > 0 or Sig.Nbr_Ports > 0 then -- Only for inout. return True; else return False; end if; else return False; end if; when Mode_Conv_In | Mode_Conv_Out => return False; when Mode_Stable | Mode_Guard | Mode_Quiet | Mode_Transaction | Mode_Delayed => return True; when Mode_End => return False; end case; end Is_Eff_Drv; procedure Order_Signal_List (Sig : Ghdl_Signal_Ptr; Order : Propag_Order_Flag) is begin for I in 1 .. Sig.Nbr_Ports loop Order_Signal (Sig.Ports (I - 1), Order); end loop; end Order_Signal_List; -- Put SIG in PROPAGATION table until ORDER level. procedure Order_Signal (Sig : Ghdl_Signal_Ptr; Order : Propag_Order_Flag) is begin if Sig = null then return; end if; -- Catch infinite loops, which must never happen. -- Also exit if the signal is already fully ordered. case Sig.Flags.Propag is when Propag_None => null; when Propag_Being_Driving => Internal_Error ("order_signal: being driving"); when Propag_Being_Effective => Internal_Error ("order_signal: being effective"); when Propag_Driving => null; when Propag_Done => -- If sig was already handled, nothing to do! return; end case; -- First, the driving value. if Sig.Flags.Propag = Propag_None then case Sig.S.Mode_Sig is when Mode_Signal_User => if Sig.S.Nbr_Drivers = 0 and Sig.Nbr_Ports = 0 then -- No source. Sig.Flags.Propag := Propag_Driving; elsif Sig.S.Resolv = null then -- Not resolved (so at most one source). if Sig.S.Nbr_Drivers = 1 then -- Not resolved, 1 source : a driver. if Is_Eff_Drv (Sig) then Add_Propagation ((Kind => Eff_One_Driver, Sig => Sig)); Sig.Flags.Propag := Propag_Done; else Add_Propagation ((Kind => Drv_One_Driver, Sig => Sig)); Sig.Flags.Propag := Propag_Driving; end if; else Sig.Flags.Propag := Propag_Being_Driving; -- not resolved, 1 source : Source is a port. Order_Signal (Sig.Ports (0), Propag_Driving); if Is_Eff_Drv (Sig) then Add_Propagation ((Kind => Eff_One_Port, Sig => Sig)); Sig.Flags.Propag := Propag_Done; else Add_Propagation ((Kind => Drv_One_Port, Sig => Sig)); Sig.Flags.Propag := Propag_Driving; end if; end if; else -- Resolved signal. declare Resolv : Resolved_Signal_Acc; S : Ghdl_Signal_Ptr; begin -- Compute driving value of brothers. Resolv := Sig.S.Resolv; for I in Resolv.Sig_Range.First .. Resolv.Sig_Range.Last loop S := Sig_Table.Table (I); if S.Flags.Propag /= Propag_None then Internal_Error ("order_signal(1)"); end if; S.Flags.Propag := Propag_Being_Driving; end loop; for I in Resolv.Sig_Range.First .. Resolv.Sig_Range.Last loop S := Sig_Table.Table (I); -- Compute driving value of the sources. for J in 1 .. S.Nbr_Ports loop Order_Signal (S.Ports (J - 1), Propag_Driving); end loop; end loop; for I in Resolv.Sig_Range.First .. Resolv.Sig_Range.Last loop S := Sig_Table.Table (I); S.Flags.Propag := Propag_Driving; end loop; if Is_Eff_Drv (Sig) then if Resolv.Sig_Range.First = Resolv.Sig_Range.Last then Add_Propagation ((Kind => Eff_One_Resolved, Sig => Sig)); else Add_Propagation ((Kind => Eff_Multiple, Resolv => Resolv)); end if; else if Resolv.Sig_Range.First = Resolv.Sig_Range.Last then Add_Propagation ((Kind => Drv_One_Resolved, Sig => Sig)); else Add_Propagation ((Kind => Drv_Multiple, Resolv => Resolv)); end if; end if; end; end if; when Mode_Signal_Implicit => Sig.Flags.Propag := Propag_Being_Driving; Order_Signal_List (Sig, Propag_Done); Sig.Flags.Propag := Propag_Done; case Mode_Signal_Implicit (Sig.S.Mode_Sig) is when Mode_Guard => Add_Propagation ((Kind => Imp_Guard, Sig => Sig)); when Mode_Stable => Add_Propagation ((Kind => Imp_Stable, Sig => Sig)); when Mode_Quiet => Add_Propagation ((Kind => Imp_Quiet, Sig => Sig)); when Mode_Transaction => Add_Propagation ((Kind => Imp_Transaction, Sig => Sig)); when Mode_Delayed => Add_Propagation ((Kind => Imp_Delayed, Sig => Sig)); end case; return; when Mode_Conv_In => -- In conversion signals have no driving value null; when Mode_Conv_Out => declare Conv : Sig_Conversion_Acc; begin Conv := Sig.S.Conv; for I in Conv.Dest.First .. Conv.Dest.Last loop Sig_Table.Table (I).Flags.Propag := Propag_Being_Driving; end loop; for I in Conv.Src.First .. Conv.Src.Last loop Order_Signal (Sig_Table.Table (I), Propag_Driving); end loop; Add_Propagation ((Kind => Out_Conversion, Conv => Conv)); for I in Conv.Dest.First .. Conv.Dest.Last loop Sig_Table.Table (I).Flags.Propag := Propag_Done; end loop; end; when Mode_End => Internal_Error ("order_signal: mode_end"); end case; end if; -- Effective value. if Order = Propag_Driving then -- Will be done later. return; end if; case Sig.S.Mode_Sig is when Mode_Signal | Mode_Buffer => -- Effective value is driving value. Sig.Flags.Propag := Propag_Done; when Mode_Linkage | Mode_Out => -- No effective value. Sig.Flags.Propag := Propag_Done; when Mode_Inout | Mode_In => if Sig.S.Effective = null then -- Effective value is driving value or initial value. null; else Sig.Flags.Propag := Propag_Being_Effective; Order_Signal (Sig.S.Effective, Propag_Done); Add_Propagation ((Kind => Eff_Actual, Sig => Sig)); Sig.Flags.Propag := Propag_Done; end if; when Mode_Stable | Mode_Guard | Mode_Quiet | Mode_Transaction | Mode_Delayed => -- Sig.Propag is already set to PROPAG_DONE. null; when Mode_Conv_In => declare Conv : Sig_Conversion_Acc; begin Conv := Sig.S.Conv; for I in Conv.Dest.First .. Conv.Dest.Last loop Sig_Table.Table (I).Flags.Propag := Propag_Being_Effective; end loop; for I in Conv.Src.First .. Conv.Src.Last loop Order_Signal (Sig_Table.Table (I), Propag_Done); end loop; Add_Propagation ((Kind => In_Conversion, Conv => Conv)); for I in Conv.Dest.First .. Conv.Dest.Last loop Sig_Table.Table (I).Flags.Propag := Propag_Done; end loop; end; when Mode_Conv_Out => -- No effective value. null; when Mode_End => Internal_Error ("order_signal: mode_end"); end case; end Order_Signal; procedure Set_Net (Sig : Ghdl_Signal_Ptr; Net : Signal_Net_Type; Link : Ghdl_Signal_Ptr) is use Astdio; use Stdio; begin if Sig = null then return; end if; if Boolean'(False) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -