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

Reply via email to