summaryrefslogtreecommitdiff
path: root/src/grt/grt-processes.adb
diff options
context:
space:
mode:
authorTristan Gingold2015-10-30 07:11:28 +0100
committerTristan Gingold2015-10-30 07:11:28 +0100
commitce10f7dbd57cb5d2273567aa536bfce79620849c (patch)
tree62fdd99a17aa09a04166e014444aeb8b732dce81 /src/grt/grt-processes.adb
parentab70415983fec433dd35aea6cc8b107699a5aff0 (diff)
downloadghdl-ce10f7dbd57cb5d2273567aa536bfce79620849c.tar.gz
ghdl-ce10f7dbd57cb5d2273567aa536bfce79620849c.tar.bz2
ghdl-ce10f7dbd57cb5d2273567aa536bfce79620849c.zip
Rework callbacks, support cocotb.
Diffstat (limited to 'src/grt/grt-processes.adb')
-rw-r--r--src/grt/grt-processes.adb227
1 files changed, 154 insertions, 73 deletions
diff --git a/src/grt/grt-processes.adb b/src/grt/grt-processes.adb
index 748ab6d..feb3123 100644
--- a/src/grt/grt-processes.adb
+++ b/src/grt/grt-processes.adb
@@ -33,6 +33,7 @@ with Grt.Options;
with Grt.Rtis_Addr; use Grt.Rtis_Addr;
with Grt.Rtis_Utils;
with Grt.Hooks;
+with Grt.Callbacks; use Grt.Callbacks;
with Grt.Disp_Signals;
with Grt.Stats;
with Grt.Threads; use Grt.Threads;
@@ -316,12 +317,12 @@ package body Grt.Processes is
-- List of unused action_list to be recycled.
Old_Action_List : Action_List_Acc;
-
procedure Ghdl_Process_Wait_Add_Sensitivity (Sig : Ghdl_Signal_Ptr)
is
Proc : constant Process_Acc := Get_Current_Process;
El : Action_List_Acc;
begin
+ -- Allocate a structure.
if Old_Action_List = null then
El := new Action_List (Dynamic => True);
else
@@ -620,21 +621,23 @@ package body Grt.Processes is
-- 1) TIME'HIGH
Res := Std_Time'Last;
- -- 2) The next time at which a driver becomes active, or
- Res := Std_Time'Min (Res, Grt.Signals.Find_Next_Time);
+ -- 3) The next time at which a process resumes.
+ Res := Std_Time'Min (Res, Process_First_Timeout);
+
+ -- LRM08 14.7.5.1 Model execution
+ -- d) The next time at which a registered and enabled vhpiCbAfterDelay
+ -- [...] callback is to occur.
+ Res := Std_Time'Min (Res, Get_First_Time (Hooks.Cb_After_Delay));
if Res = Current_Time then
return Res;
end if;
- -- 3) The next time at which a process resumes.
- if Process_First_Timeout < Res then
- -- No signals to be updated.
- Grt.Signals.Flush_Active_List;
-
- Res := Process_First_Timeout;
- end if;
+ -- 2) The next time at which a driver becomes active, or [...]
+ Res := Grt.Signals.Find_Next_Time (Res);
+ -- Note that Find_Next_Time has a side effect: it updates the
+ -- active_chain. That's the reason why it is the last.
return Res;
end Compute_Next_Time;
@@ -688,16 +691,6 @@ package body Grt.Processes is
-- Run resumed processes.
-- If POSTPONED is true, resume postponed processes, else resume
-- non-posponed processes.
- -- Returns one of these values:
- -- No process has been run.
- Run_None : constant Integer := 1;
- -- At least one process was run.
- Run_Resumed : constant Integer := 2;
- -- Simulation is finished.
- Run_Finished : constant Integer := 3;
- -- Stop/finish request from user (via std.env).
- Run_Stop : constant Integer := -2;
- pragma Unreferenced (Run_Stop);
Mt_Last : Natural;
Mt_Table : Process_Acc_Array_Acc;
@@ -736,7 +729,7 @@ package body Grt.Processes is
end loop;
end Run_Processes_Threads;
- function Run_Processes (Postponed : Boolean) return Natural
+ function Run_Processes (Postponed : Boolean) return Integer
is
Table : Process_Acc_Array_Acc;
Last : Natural;
@@ -795,9 +788,13 @@ package body Grt.Processes is
end if;
end Run_Processes;
+ -- Updated by Initialization_Phase and Simulation_Cycle to the time of the
+ -- next cycle. Unchanged in case of delta-cycle.
+ Next_Time : Std_Time;
+
procedure Initialization_Phase
is
- Status : Natural;
+ Status : Integer;
pragma Unreferenced (Status);
begin
-- Allocate processes arrays.
@@ -843,7 +840,10 @@ package body Grt.Processes is
-- - The time of the next simulation cycle (which in this case is the
-- first simulation cycle), Tn, is calculated according to the rules
-- of step f of the simulation cycle, below.
- Current_Time := Compute_Next_Time;
+ Next_Time := Compute_Next_Time;
+ if Next_Time /= 0 then
+ Update_Active_Chain;
+ end if;
-- Clear current_delta, will be set by Simulation_Cycle.
Current_Delta := 0;
@@ -856,7 +856,7 @@ package body Grt.Processes is
Tn : Std_Time;
Status : Integer;
begin
- -- LRM93 12.6.4
+ -- LRM08 14.7.5.3 Simulation cycle (ex LRM93 12.6.4)
-- A simulation cycle consists of the following steps:
--
-- a) The current time, Tc is set equal to Tn. Simulation is complete
@@ -865,22 +865,53 @@ package body Grt.Processes is
-- GHDL: this is done at the last step of the cycle.
null;
- -- b) Each active explicit signal in the model is updated. (Events
- -- may occur on signals as a result).
- -- c) Each implicit signal in the model is updated. (Events may occur
- -- on signals as a result.)
+ -- b) The following actions occur in the indicated order:
+ -- 1) If the current simulation cycle is not a delta cycle, each
+ -- registered and enabled vhpiCbNextTimeStep and
+ -- vhpiCbRepNextTimeStep callback is executed [TODO]
+ if Current_Delta = 0 then
+ Call_Callbacks (Hooks.Cb_Next_Time_Step);
+ end if;
+
+ -- 2) Each registered and enabled vhpiCbStartOfNextCycle and
+ -- vhpiCbRepStartOfNextCycle callback is executed [TODO]
+ -- 3) Each registered and enabled vhpiCbAfterDelay and
+ -- vhpiCbRepAfterDelay callback is executed.
+ if Current_Time = Get_First_Time (Hooks.Cb_After_Delay) then
+ Call_Time_Callbacks (Hooks.Cb_After_Delay);
+ if Options.Break_Simulation then
+ return Run_Stop;
+ end if;
+ end if;
+
+ -- c) Each active driver in the model is updated. If a force or deposit
+ -- was scheduled for any driver, the force or deposit is no longer
+ -- scheduler for the driver [TODO]
+ -- d) Each signal on each net in the model that includes active drivers
+ -- is updated in an order that is consistent with the dependency
+ -- relaction between signals (see 14.7.4). (Events may occur on
+ -- signals as a results.) If a force, deposit, or release was
+ -- scheduled for any signal, the force, deposit, or release is no
+ -- longer scheduled for the signal.
if Options.Flag_Stats then
Stats.Start_Update;
end if;
Update_Signals;
+ Call_Callbacks (Hooks.Cb_Signals_Updated);
if Options.Flag_Stats then
Stats.Start_Resume;
end if;
- -- d) For each process P, if P is currently sensitive to a signal S and
- -- if an event has occured on S in this simulation cycle, then P
- -- resumes.
+ -- e) Any action required to give effect to a PSL directive is performed
+ -- [TODO]
+ null;
+
+ -- f) The following actions occur in the indicated order:
+ -- 2) For each process P, if P is currently sensitive to a signal S
+ -- and if an event has occured on S in this simulation cycle, then
+ -- P resumes.
if Current_Time = Process_First_Timeout then
+ -- There are processes to awake.
Tn := Last_Time;
declare
Proc : Process_Acc;
@@ -921,44 +952,61 @@ package body Grt.Processes is
Process_First_Timeout := Tn;
end if;
- -- e) Each nonpostponed that has resumed in the current simulation cycle
- -- is executed until it suspends.
+ -- 3) For each nonpostponed that has resumed in the current
+ -- simulation cycle, the following actions occur in the indicated
+ -- order:
+ -- - Each registered and enabled vhpiCbResume callback associated
+ -- with P is executed [TODO]
+ -- - The processes executes until it suspends.
+ -- - Each registered and enabled vhpiCbSyspend callback associated
+ -- with P is executed [TODO]
Status := Run_Processes (Postponed => False);
- -- f) The time of the next simulation cycle, Tn, is determined by
- -- setting it to the earliest of
- -- 1) TIME'HIGH
- -- 2) The next time at which a driver becomes active, or
- -- 3) The next time at which a process resumes.
- -- If Tn = Tc, then the next simulation cycle (if any) will be a
- -- delta cycle.
+ -- g) The time of the next simulation cycle, Tn, is calculated according
+ -- to the rules of 14.7.5.1
if Options.Flag_Stats then
Stats.Start_Next_Time;
end if;
Tn := Compute_Next_Time;
- -- g) If the next simulation cycle will be a delta cycle, the remainder
- -- of the step is skipped.
- -- Otherwise, each postponed process that has resumed but has not
- -- been executed since its last resumption is executed until it
- -- suspends. Then Tn is recalculated according to the rules of
- -- step f. It is an error if the execution of any postponed
- -- process causes a delta cycle to occur immediatly after the
- -- current simulation cycle.
- if Tn = Current_Time then
- if Current_Time = Last_Time and then Status = Run_None then
- return Run_Finished;
- else
- Current_Delta := Current_Delta + 1;
- return Run_Resumed;
+ -- h) If the next simulation cycle will be a delta cycle, the remainder
+ -- of the step is skipped. Otherwise the following actions occur
+ -- in the indicated order:
+ -- 1) Each registered and enabled vhpiLastKnownDeltaCycle and
+ -- vhpiCbRepLastKnownDeltaCycle callback is executed. Tn is
+ -- recalculated according to the rules of 14.7.5.1
+ -- [...]
+ -- 4) For each postponed process P, if P has resumed but has not been
+ -- executed since its last resumption, the following actions occur
+ -- in the indicated order:
+ -- - Each registered and enabled vhpiCbResume callback associated
+ -- with P is executed [TODO]
+ -- - The process executes until it suspends.
+ -- - Each registered and enabled vhpiCbSuspend callback associated
+ -- with P is executed [TODO]
+ -- 5) Tn is recalculated according to the rules of 14.7.5.1
+ -- 6) [TODO]
+ -- 7) If Tn = TIME'HIGH and there are no active drivers, process
+ -- resumptions, or registered and enabled vhpiCbAfterDelay,
+ -- vhpiCbRepAfterDelay, vhpiCbTimeOut, or VhpiCbRepTimeOut
+ -- callbacks to occur at Tn, then each registered and enabled
+ -- vhpiCbQuiescence is executed. [TODO]
+ -- Tn is recalculated according to the rules of 14.7.5.1
+ -- It is an error if the execution of any postponed process or any
+ -- callback executed in substeps 3) through 7) of step h) causes a
+ -- delta cycle to occur immediatly after the current simulation
+ -- cycle.
+ if Tn /= Current_Time then
+ if Has_Callbacks (Hooks.Cb_Last_Known_Delta) then
+ Call_Callbacks (Hooks.Cb_Last_Known_Delta);
+ Flush_Active_Chain;
+ Tn := Compute_Next_Time;
end if;
- else
- Current_Delta := 0;
- if Nbr_Postponed_Processes /= 0 then
+ end if;
+ if Tn /= Current_Time then
+ if Last_Postponed_Resume_Process /= 0 then
+ Flush_Active_Chain;
Status := Run_Processes (Postponed => True);
- end if;
- if Status = Run_Resumed then
- Flush_Active_List;
if Options.Flag_Stats then
Stats.Start_Next_Time;
end if;
@@ -967,15 +1015,27 @@ package body Grt.Processes is
Error ("postponed process causes a delta cycle");
end if;
end if;
- Current_Time := Tn;
+
+ Call_Callbacks (Hooks.Cb_End_Of_Time_Step);
+
+ Update_Active_Chain;
+ Next_Time := Tn;
+ Current_Delta := 0;
+ return Run_Resumed;
+ end if;
+
+ if Current_Time = Last_Time and then Status = Run_None then
+ -- End of time and no process to run.
+ return Run_Finished;
+ else
+ Current_Delta := Current_Delta + 1;
return Run_Resumed;
end if;
end Simulation_Cycle;
- function Simulation return Integer
+ procedure Simulation_Init
is
use Options;
- Status : Integer;
begin
if Nbr_Threads /= 1 then
Threads.Init;
@@ -993,20 +1053,29 @@ package body Grt.Processes is
Grt.Disp_Signals.Disp_All_Signals;
end if;
- if Current_Time /= 0 then
+ if Next_Time /= 0 then
-- This is the end of a cycle. This can happen when the time is not
-- zero after initialization.
- Cycle_Time := 0;
Grt.Hooks.Call_Cycle_Hooks;
end if;
+ end Simulation_Init;
+ function Simulation_Main_Loop return Integer
+ is
+ use Options;
+ Status : Integer;
+ begin
loop
- Cycle_Time := Current_Time;
+ -- Update time. This is the only place where Current_Time is
+ -- updated.
+ Current_Time := Next_Time;
if Disp_Time then
Grt.Disp.Disp_Now;
end if;
+
Status := Simulation_Cycle;
- exit when Status < 0;
+ exit when Status = Run_Stop;
+
if Trace_Signals then
Grt.Disp_Signals.Disp_All_Signals;
end if;
@@ -1027,14 +1096,15 @@ package body Grt.Processes is
Error ("simulation stopped by --stop-delta");
exit;
end if;
- if Current_Time > Stop_Time then
- if Current_Time /= Last_Time then
- Info ("simulation stopped by --stop-time");
- end if;
- exit;
- end if;
end loop;
+ return Status;
+ end Simulation_Main_Loop;
+
+ procedure Simulation_Finish
+ is
+ use Options;
+ begin
if Nbr_Threads /= 1 then
Threads.Finish;
end if;
@@ -1042,6 +1112,17 @@ package body Grt.Processes is
Call_Finalizers;
Grt.Hooks.Call_Finish_Hooks;
+ end Simulation_Finish;
+
+ function Simulation return Integer
+ is
+ Status : Integer;
+ begin
+ Simulation_Init;
+
+ Status := Simulation_Main_Loop;
+
+ Simulation_Finish;
return Status;
end Simulation;