📄 grt-signals.adb
字号:
Error ("assignment to a signal without a driver for the process"); end Find_Driver; function Get_Driver (Sig : Ghdl_Signal_Ptr) return Driver_Acc is Id : Process_Id; begin if Sig.S.Drivers = null then return null; end if; Id := Get_Current_Process_Id; for I in 0 .. Sig.S.Nbr_Drivers - 1 loop if Sig.S.Drivers (I).Proc = Id then return Sig.S.Drivers (I)'Access; end if; end loop; return null; end Get_Driver; -- Unused but well-known signal which always terminate ACTIVE_LIST. -- As a consequence, every element of ACTIVE_LIST has a link field set to -- a non-null value (this is of course not true for SIGNAL_END). This may -- be used to quickly check if a signal is in the list. -- This signal is not in the signal table. Signal_End : Ghdl_Signal_Ptr; -- List of active signals. Active_List : Ghdl_Signal_Ptr; -- List of signals which have projected waveforms in the future (beyond -- the next delta cycle). Future_List : Ghdl_Signal_Ptr; procedure Ghdl_Signal_Start_Assign (Sign : Ghdl_Signal_Ptr; Reject : Std_Time; Trans : Transaction_Acc; After : Std_Time) is Assign_Time : Std_Time; Drv : constant Ghdl_Index_Type := Find_Driver (Sign); Drv_Ptr : constant Driver_Arr_Ptr := Sign.S.Drivers; Driver : Driver_Type renames Drv_Ptr (Drv); begin -- LRM93 8.4.1 -- It is an error if the time expression in a waveform element -- evaluates to a negative value. if After < 0 then Error ("negative time expression in signal assignment"); end if; if After = 0 then -- Put SIGN on the active list if the transaction is scheduled -- for the next delta cycle. if Sign.Link = null then Sign.Link := Active_List; Active_List := Sign; end if; else -- AFTER > 0. -- Put SIGN on the future list. if Sign.Flink = null then Sign.Flink := Future_List; Future_List := Sign; end if; end if; Assign_Time := Current_Time + After; if Assign_Time < 0 then -- Beyond the future declare Ntrans : Transaction_Acc; begin Ntrans := Trans; Free (Ntrans); return; end; end if; -- LRM93 8.4.1 -- 1. All old transactions that are projected to occur at or after the -- time at which the earliest new transaction is projected to occur -- are deleted from the projected output waveform. if Driver.Last_Trans.Time >= Assign_Time then declare -- LAST is the last transaction to keep. Last : Transaction_Acc; Next : Transaction_Acc; begin Last := Driver.First_Trans; -- Find the first transaction to be deleted. Next := Last.Next; while Next /= null and then Next.Time < Assign_Time loop Last := Next; Next := Next.Next; end loop; -- Delete old transactions. if Next /= null then -- Set the last transaction of the driver. Driver.Last_Trans := Last; -- Cut the chain. This is not strickly necessary, since -- it will be overriden below, by appending TRANS to the -- driver. Last.Next := null; -- Free removed transactions. loop Last := Next.Next; Free (Next); exit when Last = null; Next := Last; end loop; end if; end; end if; -- 2. The new transaction are then appended to the projected output -- waveform in the order of their projected occurence. Trans.Time := Assign_Time; Driver.Last_Trans.Next := Trans; Driver.Last_Trans := Trans; -- If the initial delay is inertial delay according to the definitions -- of section 8.4, the projected output waveform is further modified -- as follows: -- 1. All of the new transactions are marked. -- 2. An old transaction is marked if the time at which it is projected -- to occur is less than the time at which the first new transaction -- is projected to occur minus the pulse rejection limit. -- 3. For each remaining unmarked, old transaction, the old transaction -- is marked if it immediatly precedes a marked transaction and its -- value component is the same as that of the marked transaction; -- 4. The transaction that determines the current value of the driver -- is marked. -- 5. All unmarked transactions (all of which are old transactions) are -- deleted from the projected output waveform. -- -- GHDL: only transactions that are projected to occur at [T-R, T[ -- can be deleted (R is the reject time, T is now + after time). if Reject > 0 then -- LRM93 8.4 -- It is an error if the pulse rejection limit for any inertially -- delayed signal assignment statement is [...] or greater than the -- time expression associated with the first waveform element. if Reject > After then Error ("pulse rejection greater than first waveform delay"); end if; declare Prev : Transaction_Acc; Next : Transaction_Acc; begin -- Find the first transaction after the project time less the -- rejection time. -- PREV will be the last old transaction which is projected to -- occur before T - R. Prev := Driver.First_Trans; loop Next := Prev.Next; exit when Next.Time >= Assign_Time - Reject; Prev := Next; end loop; -- Scan every transaction until TRANS. If a transaction value is -- different from the TRANS value, then delete all previous -- transactions (from T - R to the currently scanned transaction), -- since they are not marked. while Next /= Trans loop if Next.Kind /= Trans.Kind or else (Trans.Kind = Trans_Value and then not Value_Equal (Next.Val, Trans.Val, Sign.Mode)) then -- NEXT is different from TRANS. -- Delete ]PREV;NEXT]. declare D, N : Transaction_Acc; begin D := Prev.Next; Next := Next.Next; Prev.Next := Next; loop N := D.Next; Free (D); exit when N = Next; D := N; end loop; end; else Next := Next.Next; end if; end loop; end; elsif Reject /= 0 then -- LRM93 8.4 -- It is an error if the pulse rejection limit for any inertially -- delayed signal assignment statement is either negative or [...]. Error ("pulse rejection is negative"); end if; -- Do some checks. if Driver.Last_Trans.Next /= null then Error ("ghdl_signal_start_assign internal_error"); end if; end Ghdl_Signal_Start_Assign; procedure Ghdl_Signal_Next_Assign (Sign : Ghdl_Signal_Ptr; Val : Value_Union; After : Std_Time) is Drv_Ptr : constant Driver_Arr_Ptr := Sign.S.Drivers; Driver : Driver_Type renames Drv_Ptr (Find_Driver (Sign)); Trans : Transaction_Acc; begin if After > 0 and then Sign.Flink = null then -- Put SIGN on the future list. Sign.Flink := Future_List; Future_List := Sign; end if; Trans := new Transaction'(Kind => Trans_Value, Time => Current_Time + After, Next => null, Val => Val); if Trans.Time <= Driver.Last_Trans.Time then Error ("transactions not in ascending order"); end if; Driver.Last_Trans.Next := Trans; Driver.Last_Trans := Trans; end Ghdl_Signal_Next_Assign; procedure Ghdl_Signal_Simple_Assign_Error (Sign : Ghdl_Signal_Ptr) is Trans : Transaction_Acc; begin Trans := new Transaction'(Kind => Trans_Error, Time => 0, Next => null); Ghdl_Signal_Start_Assign (Sign, 0, Trans, 0); end Ghdl_Signal_Simple_Assign_Error; procedure Ghdl_Signal_Start_Assign_Error (Sign : Ghdl_Signal_Ptr; Rej : Std_Time; After : Std_Time) is Trans : Transaction_Acc; begin Trans := new Transaction'(Kind => Trans_Error, Time => 0, Next => null); Ghdl_Signal_Start_Assign (Sign, Rej, Trans, After); end Ghdl_Signal_Start_Assign_Error; procedure Ghdl_Signal_Start_Assign_Null (Sign : Ghdl_Signal_Ptr; Rej : Std_Time; After : Std_Time) is Trans : Transaction_Acc; begin if not Is_Signal_Guarded (Sign) then Error ("null transaction for a non-guarded target"); end if; Trans := new Transaction'(Kind => Trans_Null, Time => 0, Next => null); Ghdl_Signal_Start_Assign (Sign, Rej, Trans, After); end Ghdl_Signal_Start_Assign_Null; procedure Ghdl_Signal_Disconnect (Sign : Ghdl_Signal_Ptr) is Trans : Transaction_Acc; Time : Std_Time; begin if not Is_Signal_Guarded (Sign) then Error ("null transaction for a non-guarded target"); end if; Trans := new Transaction'(Kind => Trans_Null, Time => 0, Next => null); Time := Sign.S.Resolv.Disconnect_Time; Ghdl_Signal_Start_Assign (Sign, Time, Trans, Time); end Ghdl_Signal_Disconnect; procedure Ghdl_Signal_Associate (Sig : Ghdl_Signal_Ptr; Val : Value_Union) is begin Sig.Value := Val; Sig.Driving_Value := Val; end Ghdl_Signal_Associate; function Ghdl_Create_Signal_B2 (Init_Val : Ghdl_B2; Resolv_Func : System.Address; Resolv_Inst : System.Address) return Ghdl_Signal_Ptr is begin return Create_Signal (Mode_B2, Value_Union'(Mode => Mode_B2, B2 => Init_Val), Get_Current_Mode_Signal, Resolv_Func, Resolv_Inst); end Ghdl_Create_Signal_B2; procedure Ghdl_Signal_Init_B2 (Sig : Ghdl_Signal_Ptr; Init_Val : Ghdl_B2) is begin Ghdl_Signal_Init (Sig, Value_Union'(Mode => Mode_B2, B2 => Init_Val)); end Ghdl_Signal_Init_B2; procedure Ghdl_Signal_Associate_B2 (Sig : Ghdl_Signal_Ptr; Val : Ghdl_B2) is begin Ghdl_Signal_Associate (Sig, Value_Union'(Mode => Mode_B2, B2 => Val)); end Ghdl_Signal_Associate_B2; procedure Ghdl_Signal_Simple_Assign_B2 (Sign : Ghdl_Signal_Ptr; Val : Ghdl_B2) is Trans : Transaction_Acc; begin if not Sign.Flags.Has_Active and then Sign.Net = Net_One_Driver and then Val = Sign.Value.B2 and then Sign.S.Drivers (0).First_Trans.Next = null then return; end if; Trans := new Transaction' (Kind => Trans_Value, Time => 0, Next => null, Val => Value_Union'(Mode => Mode_B2, B2 => Val)); Ghdl_Signal_Start_Assign (Sign, 0, Trans, 0); end Ghdl_Signal_Simple_Assign_B2; procedure Ghdl_Signal_Start_Assign_B2 (Sign : Ghdl_Signal_Ptr; Rej : Std_Time; Val : Ghdl_B2; After : Std_Time) is Trans : Transaction_Acc; begin Trans := new Transaction' (Kind => Trans_Value, Time => 0, Next => null, Val => Value_Union'(Mode => Mode_B2, B2 => Val)); Ghdl_Signal_Start_Assign (Sign, Rej, Trans, After); end Ghdl_Signal_Start_Assign_B2; procedure Ghdl_Signal_Next_Assign_B2 (Sign : Ghdl_Signal_Ptr; Val : Ghdl_B2; After : Std_Time) is begin Ghdl_Signal_Next_Assign (Sign, Value_Union'(Mode => Mode_B2, B2 => Val), After); end Ghdl_Signal_Next_Assign_B2; function Ghdl_Create_Signal_E8 (Init_Val : Ghdl_E8; Resolv_Func : System.Address; Resolv_Inst : System.Address) return Ghdl_Signal_Ptr is begin return Create_Signal (Mode_E8, Value_Union'(Mode => Mode_E8, E8 => Init_Val), Get_Current_Mode_Signal, Resolv_Func, Resolv_Inst); end Ghdl_Create_Signal_E8; procedure Ghdl_Signal_Init_E8 (Sig : Ghdl_Signal_Ptr; Init_Val : Ghdl_E8) is begin Ghdl_Signal_Init (Sig, Value_Union'(Mode => Mode_E8, E8 => Init_Val)); end Ghdl_Signal_Init_E8; procedure Ghdl_Signal_Associate_E8 (Sig : Ghdl_Signal_Ptr; Val : Ghdl_E8) is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -