Hi Tristan,
I'm still getting:
./xx:internal error: process in timeout
./xx:error: simulation failed
This time with svn131. It starts to get annoying...
Unfortunately, this bug seems quite elusive, I haven't been able to
produce a small understandable reproducer.
I have patched grt to dump lots of process-related info to stdout (see
the patch below for details). What happens is that one process that does
the following:
Ghdl_Process_Wait_Set_Timeout: .xx(testbench).writer_p current 119876ns wait
124ns
Ghdl_Process_Wait_Suspend: suspend: .xx(testbench).writer_p current 119876ns
Ghdl_Process_Wait_Suspend: resume: .xx(testbench).writer_p current 119876ns
return False
Ghdl_Process_Wait_Close: .xx(testbench).writer_p current 119876ns
Ghdl_Process_Wait_Suspend: suspend: .xx(testbench)._writer_p current 119876ns
Ghdl_Process_Wait_Suspend: resume: .xx(testbench).writer_p current 120876ns
return False
Ghdl_Process_Wait_Close: .xx(testbench).writer_p current 120876ns
Ghdl_Process_Wait_Exit: .xx(testbench).writer_p current 120876ns
As you can see, it calls Ghdl_Process_Wait_Close twice without calling
Ghdl_Process_Wait_Set_Timeout in between!
This means that Remove_Process_From_Timeout_Chain is called twice. Since
there is no protection against spurious unlinking from the
Process_Timeout_Chain, the second call will corrupt the
Process_Timeout_Chain data structure, causing another process to be
circularly linked to the list.
Due to the circular linking, the same process is first resumed within
Simulation_Cycle, then revisited again, resulting in the "process in
timeout" abort.
Now why Ghdl_Process_Wait_Close is called twice without an interspersed
Ghdl_Process_Wait_Set_Timeout is beyond me, I do not (yet?) understand
the interface between ghdl and grt.
Thomas
--- grt-processes.adb.orig 2009-12-12 14:40:37.000000000 +0100
+++ grt-processes.adb 2009-12-12 19:06:33.000000000 +0100
@@ -31,6 +31,7 @@
with Grt.Disp_Signals;
with Grt.Stats;
with Grt.Threads; use Grt.Threads;
+with Grt.Disp_Rti;
pragma Elaborate_All (Grt.Table);
package body Grt.Processes is
@@ -223,7 +224,16 @@
procedure Ghdl_Process_Add_Sensitivity (Sig : Ghdl_Signal_Ptr)
is
+ Proc : constant Process_Acc := Get_Current_Process;
begin
+ Grt.Astdio.Put ("Ghdl_Process_Add_Sensitivity: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" current ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ Grt.Astdio.Put (" signal ");
+ Grt.Disp_Rti.Disp_Name (Sig.Rti.Name);
+ Grt.Astdio.New_Line;
+
Resume_Process_If_Event
(Sig, Process_Table.Table (Process_Table.Last));
end Ghdl_Process_Add_Sensitivity;
@@ -285,6 +295,38 @@
Proc.Sensitivity := El;
end Ghdl_Process_Wait_Add_Sensitivity;
+ procedure Debug_Dump_Timeout_Chain
+ is
+ Proc : Process_Acc;
+ begin
+ Grt.Astdio.Put ("Process_Timeout_Chain:");
+ Grt.Astdio.New_Line;
+ Proc := Process_Timeout_Chain;
+ while Proc /= null loop
+ Grt.Astdio.Put (" ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" [");
+ Grt.Astdio.Put (Stdio.stdout, Proc.This);
+ Grt.Astdio.Put ("] Next ");
+ if Proc.Timeout_Chain_Next = null then
+ Grt.Astdio.Put ("NULL");
+ else
+ Disp_Process_Name (Stdio.stdout, Proc.Timeout_Chain_Next);
+ end if;
+ Grt.Astdio.Put (" Prev ");
+ if Proc.Timeout_Chain_Prev = null then
+ Grt.Astdio.Put ("NULL");
+ else
+ Disp_Process_Name (Stdio.stdout, Proc.Timeout_Chain_Prev);
+ end if;
+ Grt.Astdio.New_Line;
+ if Proc = Proc.Timeout_Chain_Next then
+ Internal_Error ("Process_Timeout_Chain inconsistent: ");
+ end if;
+ Proc := Proc.Timeout_Chain_Next;
+ end loop;
+ end Debug_Dump_Timeout_Chain;
+
procedure Update_Process_First_Timeout (Proc : Process_Acc) is
begin
if Proc.Timeout < Process_First_Timeout then
@@ -296,6 +338,11 @@
Process_Timeout_Chain.Timeout_Chain_Prev := Proc;
end if;
Process_Timeout_Chain := Proc;
+
+ Grt.Astdio.Put ("Update_Process_First_Timeout: After Adding: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.New_Line;
+ Debug_Dump_Timeout_Chain;
end Update_Process_First_Timeout;
procedure Remove_Process_From_Timeout_Chain (Proc : Process_Acc) is
@@ -312,6 +359,11 @@
Proc.Timeout_Chain_Next.Timeout_Chain_Prev :=
Proc.Timeout_Chain_Prev;
end if;
+
+ Grt.Astdio.Put ("Remove_Process_From_Timeout_Chain: After Removing: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.New_Line;
+ Debug_Dump_Timeout_Chain;
end Remove_Process_From_Timeout_Chain;
procedure Ghdl_Process_Wait_Set_Timeout (Time : Std_Time)
@@ -324,6 +376,14 @@
end if;
Proc.Timeout := Current_Time + Time;
Update_Process_First_Timeout (Proc);
+
+ Grt.Astdio.Put ("Ghdl_Process_Wait_Set_Timeout: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" current ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ Grt.Astdio.Put (" wait ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Time);
+ Grt.Astdio.New_Line;
end Ghdl_Process_Wait_Set_Timeout;
function Ghdl_Process_Wait_Suspend return Boolean
@@ -338,9 +398,29 @@
-- if Cur_Proc.Timeout = Bad_Time then
-- Cur_Proc.Timeout := Std_Time'Last;
-- end if;
+
+ Grt.Astdio.Put ("Ghdl_Process_Wait_Suspend: suspend: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" current ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ Grt.Astdio.New_Line;
+
Stack_Switch (Get_Main_Stack, Proc.Stack);
-- Note: in case of timeout, the timeout is removed when process is
-- woken up.
+
+ Grt.Astdio.Put ("Ghdl_Process_Wait_Suspend: resume: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" current ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ Grt.Astdio.Put (" return ");
+ if Proc.State = State_Timeout then
+ Grt.Astdio.Put ("True");
+ else
+ Grt.Astdio.Put ("False");
+ end if;
+ Grt.Astdio.New_Line;
+
return Proc.State = State_Timeout;
end Ghdl_Process_Wait_Suspend;
@@ -353,6 +433,13 @@
El : Action_List_Acc;
N_El : Action_List_Acc;
begin
+
+ Grt.Astdio.Put ("Ghdl_Process_Wait_Close: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" current ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ Grt.Astdio.New_Line;
+
-- Remove the sensitivity.
El := Proc.Sensitivity;
Proc.Sensitivity := null;
@@ -414,6 +501,13 @@
is
Proc : constant Process_Acc := Get_Current_Process;
begin
+
+ Grt.Astdio.Put ("Ghdl_Process_Wait_Exit: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" current ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ Grt.Astdio.New_Line;
+
if Proc.State = State_Sensitized then
Error ("wait statement in a sensitized process");
end if;
@@ -437,6 +531,17 @@
end if;
Proc.Timeout := Current_Time + Time;
Proc.State := State_Wait;
+
+ Grt.Astdio.Put ("Ghdl_Process_Wait_Timeout: add to queue: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" [");
+ Grt.Astdio.Put (Stdio.stdout, Proc.This);
+ Grt.Astdio.Put ("] current ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ Grt.Astdio.Put (" wakeup ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Proc.Timeout);
+ Grt.Astdio.New_Line;
+
Update_Process_First_Timeout (Proc);
-- Suspend this process.
Stack_Switch (Get_Main_Stack, Proc.Stack);
@@ -444,6 +549,15 @@
Proc.Timeout := Bad_Time;
Remove_Process_From_Timeout_Chain (Proc);
Proc.State := State_Ready;
+
+ Grt.Astdio.Put ("Ghdl_Process_Wait_Timeout: remove from queue: ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" [");
+ Grt.Astdio.Put (Stdio.stdout, Proc.This);
+ Grt.Astdio.Put ("] current ");
+ Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ Grt.Astdio.New_Line;
+
end Ghdl_Process_Wait_Timeout;
-- Verilog.
@@ -812,11 +926,30 @@
-- resumes.
if Current_Time = Process_First_Timeout then
Tn := Last_Time;
+
declare
Proc : Process_Acc;
+ Proc_Prev : Process_Acc;
begin
+ -- Debug_Dump_Timeout_Chain;
+
+ -- Grt.Astdio.Put ("start resuming nonsensitized timed out
processes @ time ");
+ -- Grt.Astdio.Put_Time (Stdio.stdout, Current_Time);
+ -- Grt.Astdio.New_Line;
+
Proc := Process_Timeout_Chain;
+ Proc_Prev := null;
while Proc /= null loop
+ if Proc_Prev = Proc then
+ Grt.Astdio.Put ("process twice in Process_Timeout_Chain ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" [");
+ Grt.Astdio.Put (Stdio.stdout, Proc.This);
+ Grt.Astdio.Put ("]");
+ Grt.Astdio.New_Line;
+ Internal_Error ("process twice in Process_Timeout_Chain: ");
+ end if;
+
case Proc.State is
when State_Sensitized =>
null;
@@ -833,19 +966,48 @@
Proc.Timeout := Bad_Time;
Resume_Process (Proc);
Proc.State := State_Timeout;
+
+ -- Grt.Astdio.Put ("resuming timeout process ");
+ -- Disp_Process_Name (Stdio.stdout, Proc);
+ -- Grt.Astdio.Put (" [");
+ -- Grt.Astdio.Put (Stdio.stdout, Proc.This);
+ -- Grt.Astdio.Put ("]");
+ -- if not Proc.Postponed then
+ -- Grt.Astdio.Put (" not");
+ -- end if;
+ -- Grt.Astdio.Put (" Postponed");
+ -- Grt.Astdio.New_Line;
+
elsif Proc.Timeout > 0 and then Proc.Timeout < Tn then
Tn := Proc.Timeout;
end if;
when State_Timeout
| State_Ready =>
- Internal_Error ("process in timeout");
+ Grt.Astdio.Put ("process in timeout ");
+ Disp_Process_Name (Stdio.stdout, Proc);
+ Grt.Astdio.Put (" [");
+ Grt.Astdio.Put (Stdio.stdout, Proc.This);
+ Grt.Astdio.Put ("] ");
+ if Proc.State = State_Timeout then
+ Grt.Astdio.Put ("State_Timeout");
+ else
+ Grt.Astdio.Put ("State_Ready");
+ end if;
+ Grt.Astdio.New_Line;
+ Internal_Error ("process in timeout: ");
when State_Dead =>
null;
end case;
+ Proc_Prev := Proc;
Proc := Proc.Timeout_Chain_Next;
end loop;
end;
Process_First_Timeout := Tn;
+
+ -- Grt.Astdio.Put ("done resuming nonsensitized timed out processes;
new timeout ");
+ -- Grt.Astdio.Put_Time (Stdio.stdout, Tn);
+ -- Grt.Astdio.New_Line;
+
end if;
-- e) Each nonpostponed that has resumed in the current simulation cycle
_______________________________________________
Ghdl-discuss mailing list
[email protected]
https://mail.gna.org/listinfo/ghdl-discuss