1--  Debugger for interpreter
2--  Copyright (C) 2014 Tristan Gingold
3--
4--  This program is free software: you can redistribute it and/or modify
5--  it under the terms of the GNU General Public License as published by
6--  the Free Software Foundation, either version 2 of the License, or
7--  (at your option) any later version.
8--
9--  This program is distributed in the hope that it will be useful,
10--  but WITHOUT ANY WARRANTY; without even the implied warranty of
11--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12--  GNU General Public License for more details.
13--
14--  You should have received a copy of the GNU General Public License
15--  along with this program.  If not, see <gnu.org/licenses>.
16
17with System;
18with Tables;
19with Types; use Types;
20with Name_Table;
21with Str_Table;
22with Files_Map;
23with Vhdl.Parse;
24with Vhdl.Scanner;
25with Vhdl.Tokens;
26with Vhdl.Sem_Expr;
27with Vhdl.Sem_Scopes;
28with Vhdl.Canon;
29with Std_Names;
30with Libraries;
31with Vhdl.Std_Package;
32with Vhdl.Annotations; use Vhdl.Annotations;
33with Simul.Elaboration; use Simul.Elaboration;
34with Simul.Execution; use Simul.Execution;
35with Vhdl.Utils; use Vhdl.Utils;
36with Errorout; use Errorout;
37with Vhdl.Errors; use Vhdl.Errors;
38with Vhdl.Prints;
39with Vhdl.Nodes_Walk; use Vhdl.Nodes_Walk;
40with Areapools; use Areapools;
41with Grt.Types; use Grt.Types;
42with Grt.Disp;
43with Grt.Readline;
44with Grt.Errors;
45with Grt.Disp_Signals;
46with Grt.Signals; use Grt.Signals;
47with Grt.Processes;
48with Grt.Options;
49with Grt.Stdio; use Grt.Stdio;
50with Grt.Astdio; use Grt.Astdio;
51with Grt.Astdio.Vhdl; use Grt.Astdio.Vhdl;
52
53package body Simul.Debugger is
54   --  This exception can be raised by a debugger command to directly return
55   --  to the prompt.
56   Command_Error : exception;
57
58   type Menu_Procedure is access procedure (Line : String);
59
60   --  If set (by commands), call this procedure on empty line to repeat
61   --  last command.
62   Cmd_Repeat : Menu_Procedure;
63
64   --  For the list command: current file and current line.
65   List_Current_File : Source_File_Entry := No_Source_File_Entry;
66   List_Current_Line : Natural := 0;
67   List_Current_Line_Pos : Source_Ptr := 0;
68
69   --  Set List_Current_* from a location.  To be called after program break
70   --  to indicate current location.
71   procedure Set_List_Current (Loc : Location_Type)
72   is
73      Offset : Natural;
74   begin
75      Files_Map.Location_To_Coord
76        (Loc, List_Current_File, List_Current_Line_Pos,
77         List_Current_Line, Offset);
78   end Set_List_Current;
79
80   Dbg_Top_Frame : Block_Instance_Acc;
81   Dbg_Cur_Frame : Block_Instance_Acc;
82
83   procedure Set_Cur_Frame (Frame : Block_Instance_Acc) is
84   begin
85      Dbg_Cur_Frame := Frame;
86   end Set_Cur_Frame;
87
88   procedure Set_Top_Frame (Frame : Block_Instance_Acc) is
89   begin
90      Dbg_Top_Frame := Frame;
91      Set_Cur_Frame (Frame);
92   end Set_Top_Frame;
93
94   type Breakpoint_Entry is record
95      Stmt : Iir;
96   end record;
97
98   package Breakpoints is new Tables
99     (Table_Index_Type => Natural,
100      Table_Component_Type => Breakpoint_Entry,
101      Table_Low_Bound => 1,
102      Table_Initial => 16);
103
104   --  Current execution state, or reason to stop execution (set by the
105   --  last debugger command).
106   type Exec_State_Type is
107     (--  Execution should continue until a breakpoint is reached or assertion
108      --  failure.
109      Exec_Run,
110
111      --  Execution will stop at the next statement.
112      Exec_Single_Step,
113
114      --  Execution will stop at the next simple statement in the same frame.
115      Exec_Next,
116
117      --  Execution will stop at the next statement in the same frame.  In
118      --  case of compound statement, stop after the compound statement.
119      Exec_Next_Stmt);
120
121   Exec_State : Exec_State_Type := Exec_Run;
122
123   --  Current frame for next.
124   Exec_Instance : Block_Instance_Acc;
125
126   --  Current statement for next_stmt.
127   Exec_Statement : Iir;
128
129   procedure Disp_Iir_Location (N : Iir) is
130   begin
131      if N = Null_Iir then
132         Put (stderr, "??:??:??");
133      else
134         Put (stderr, Disp_Location (N));
135      end if;
136      Put (stderr, ": ");
137   end Disp_Iir_Location;
138
139   -- Disp a message during execution.
140   procedure Error_Msg_Exec (Msg: String; Loc: in Iir) is
141   begin
142      Disp_Iir_Location (Loc);
143      Put_Line (stderr, Msg);
144      Grt.Errors.Fatal_Error;
145   end Error_Msg_Exec;
146
147   procedure Warning_Msg_Exec (Msg: String; Loc: Iir) is
148   begin
149      Disp_Iir_Location (Loc);
150      Put (stderr, "warning: ");
151      Put_Line (stderr, Msg);
152   end Warning_Msg_Exec;
153
154   -- Disp a message for a constraint error.
155   procedure Error_Msg_Constraint (Expr: in Iir) is
156   begin
157      if Expr /= Null_Iir then
158         Disp_Iir_Location (Expr);
159      end if;
160      Put (stderr, "constraint violation");
161      if Expr /= Null_Iir then
162         case Get_Kind (Expr) is
163            when Iir_Kind_Addition_Operator =>
164               Put_Line (stderr, " in the ""+"" operation");
165            when Iir_Kind_Substraction_Operator =>
166               Put_Line (stderr, " in the ""-"" operation");
167            when Iir_Kind_Integer_Literal =>
168               Put_Line (stderr, ", literal out of range");
169            when Iir_Kind_Interface_Signal_Declaration
170              | Iir_Kind_Signal_Declaration =>
171               Put_Line (stderr, " for " & Disp_Node (Expr));
172            when others =>
173               New_Line (stderr);
174         end case;
175      end if;
176      Grt.Errors.Fatal_Error;
177   end Error_Msg_Constraint;
178
179   function Get_Instance_Local_Name (Instance : Block_Instance_Acc;
180                                     Short : Boolean := False)
181                                    return String
182   is
183      Name : constant Iir := Instance.Label;
184   begin
185      if Name = Null_Iir then
186         return "<anon>";
187      end if;
188
189      case Get_Kind (Name) is
190         when Iir_Kind_Block_Statement
191           | Iir_Kind_If_Generate_Statement
192           | Iir_Kind_For_Generate_Statement
193           | Iir_Kind_Component_Instantiation_Statement
194           | Iir_Kind_Procedure_Declaration
195           | Iir_Kinds_Process_Statement
196           | Iir_Kind_Package_Declaration
197           | Iir_Kind_Configuration_Declaration =>
198            return Image_Identifier (Name);
199         when Iir_Kind_Generate_Statement_Body =>
200            return Image_Identifier (Get_Parent (Name))
201              & '(' & Image_Identifier (Name) & ')';
202         when Iir_Kind_Iterator_Declaration =>
203            return Image_Identifier (Get_Parent (Name)) & '('
204              & Execute_Image_Attribute
205              (Instance.Objects (Get_Info (Name).Slot), Get_Type (Name))
206              & ')';
207         when Iir_Kind_Architecture_Body =>
208            if Short then
209               return Image_Identifier (Get_Entity (Name));
210            else
211               return Image_Identifier (Get_Entity (Name))
212                 & '(' & Image_Identifier (Name) & ')';
213            end if;
214         when others =>
215            Error_Kind ("disp_instance_local_name", Name);
216      end case;
217   end Get_Instance_Local_Name;
218
219   -- Disp the name of an instance, without newline.
220   procedure Disp_Instance_Name (Instance: Block_Instance_Acc;
221                                 Short : Boolean := False) is
222   begin
223      if Instance.Parent /= null then
224         Disp_Instance_Name (Instance.Parent);
225         Put ('.');
226      end if;
227      Put (Get_Instance_Local_Name (Instance, Short));
228   end Disp_Instance_Name;
229
230   function Get_Instance_Name (Instance: Block_Instance_Acc) return String
231   is
232      function Parent_Name return String is
233      begin
234         if Instance.Parent /= null then
235            return Get_Instance_Name (Instance.Parent) & '.';
236         else
237            return "";
238         end if;
239      end Parent_Name;
240   begin
241      return Parent_Name & Get_Instance_Local_Name (Instance);
242   end Get_Instance_Name;
243
244   procedure Disp_Instances_Tree_Name (Inst : Block_Instance_Acc) is
245   begin
246      if Inst = null then
247         Put ("*null*");
248         New_Line;
249         return;
250      end if;
251      Put (Get_Instance_Local_Name (Inst));
252
253      Put (" ");
254      case Get_Kind (Inst.Label) is
255         when Iir_Kind_Block_Statement =>
256            Put ("[block]");
257         when Iir_Kind_If_Generate_Statement
258           | Iir_Kind_For_Generate_Statement
259           | Iir_Kind_Generate_Statement_Body =>
260            Put ("[generate]");
261         when Iir_Kind_Iterator_Declaration =>
262            Put ("[iterator]");
263         when Iir_Kind_Component_Instantiation_Statement =>
264            Put ("[component]");
265         when Iir_Kinds_Process_Statement =>
266            Put ("[process]");
267         when Iir_Kind_Architecture_Body =>
268            Put ("[entity]");
269         when Iir_Kind_Package_Declaration =>
270            Put ("[package]");
271         when Iir_Kind_Configuration_Declaration =>
272            Put ("[configuration]");
273         when others =>
274            Error_Kind ("disp_instances_tree_name", Inst.Label);
275      end case;
276      New_Line;
277   end Disp_Instances_Tree_Name;
278
279   procedure Disp_Instances_Tree1 (Inst : Block_Instance_Acc; Pfx : String)
280   is
281      Child : Block_Instance_Acc;
282   begin
283      Child := Inst.Children;
284      if Child = null then
285         return;
286      end if;
287
288      loop
289         if Child.Brother /= null then
290            Put (Pfx & "+-");
291            Disp_Instances_Tree_Name (Child);
292
293            Disp_Instances_Tree1 (Child, Pfx & "| ");
294            Child := Child.Brother;
295         else
296            Put (Pfx & "`-");
297            Disp_Instances_Tree_Name (Child);
298
299            Disp_Instances_Tree1 (Child, Pfx & "  ");
300            exit;
301         end if;
302      end loop;
303   end Disp_Instances_Tree1;
304
305   procedure Disp_Instances_Tree is
306   begin
307      for I in Global_Instances.Objects'Range loop
308         if Global_Instances.Objects (I) /= null then
309            Disp_Instances_Tree_Name (Global_Instances.Objects (I).Instance);
310         end if;
311      end loop;
312      Disp_Instances_Tree_Name (Top_Instance);
313      Disp_Instances_Tree1 (Top_Instance, "");
314   end Disp_Instances_Tree;
315
316   --  Disp a block instance, in a human readable way.
317   --  Used to debug.
318   procedure Disp_Block_Instance (Instance: Block_Instance_Acc) is
319   begin
320      Put_Line ("Objects:");
321      for I in Instance.Objects'Range loop
322         Put (Object_Slot_Type'Image (I) & ": ");
323         Disp_Value_Tab (Instance.Objects (I), 3);
324         New_Line;
325      end loop;
326   end Disp_Block_Instance;
327
328   procedure Disp_Signal (Value : Iir_Value_Literal_Acc; A_Type : Iir);
329
330   procedure Disp_Signal_Array (Value : Iir_Value_Literal_Acc;
331                                A_Type : Iir;
332                                Dim : Natural)
333   is
334   begin
335      if Dim = Get_Nbr_Elements (Get_Index_Subtype_List (A_Type)) then
336         Put ("(");
337         for I in Value.Val_Array.V'Range loop
338            if I /= 1 then
339               Put (", ");
340            end if;
341            Disp_Signal (Value.Val_Array.V (I), Get_Element_Subtype (A_Type));
342         end loop;
343         Put (")");
344      else
345         Put ("(");
346         Disp_Signal_Array (Value, A_Type, Dim + 1);
347         Put (")");
348      end if;
349   end Disp_Signal_Array;
350
351   procedure Disp_Signal_Record (Value : Iir_Value_Literal_Acc; A_Type : Iir)
352   is
353      List : constant Iir_Flist :=
354        Get_Elements_Declaration_List (Get_Base_Type (A_Type));
355      El : Iir_Element_Declaration;
356   begin
357      Put ("(");
358      for I in Value.Val_Record.V'Range loop
359         El := Get_Nth_Element (List, Natural (I - 1));
360         if I /= 1 then
361            Put (", ");
362         end if;
363         Put (Name_Table.Image (Get_Identifier (El)));
364         Put (" => ");
365         Disp_Signal (Value.Val_Record.V (I), Get_Type (El));
366      end loop;
367      Put (")");
368   end Disp_Signal_Record;
369
370   procedure Disp_Signal_Value
371     (Val : Value_Union; Mode : Mode_Type; Sig_Type : Iir) is
372   begin
373      case Mode is
374         when Mode_I64 =>
375            Put (Ghdl_I64'Image (Val.I64));
376         when Mode_I32 =>
377            Put (Ghdl_I32'Image (Val.I32));
378         when Mode_F64 =>
379            Put (Ghdl_F64'Image (Val.F64));
380         when Mode_E32 =>
381            Disp_Iir_Value_Enum (Ghdl_E32'Pos (Val.E32), Sig_Type);
382         when Mode_E8 =>
383            Disp_Iir_Value_Enum (Ghdl_E8'Pos (Val.E8), Sig_Type);
384         when Mode_B1 =>
385            Disp_Iir_Value_Enum (Ghdl_B1'Pos (Val.B1), Sig_Type);
386      end case;
387   end Disp_Signal_Value;
388
389   procedure Disp_Transaction
390     (Head : Transaction_Acc; Mode : Mode_Type; Sig_Type : Iir)
391   is
392      Trans : Transaction_Acc;
393   begin
394      Trans := Head;
395      loop
396         case Trans.Kind is
397            when Trans_Value =>
398               Disp_Signal_Value (Trans.Val, Mode, Sig_Type);
399            when Trans_Direct =>
400               Disp_Signal_Value (Trans.Val_Ptr.all, Mode, Sig_Type);
401            when Trans_Null =>
402               Put ("NULL");
403            when Trans_Error =>
404               Put ("ERROR");
405         end case;
406         if Trans.Kind = Trans_Direct then
407            Put ("[DIRECT]");
408         else
409            Put ("@");
410            Put_Time (stdout, Trans.Time);
411         end if;
412         Trans := Trans.Next;
413         exit when Trans = null;
414         Put (", ");
415      end loop;
416   end Disp_Transaction;
417
418   procedure Disp_Signal (Value : Iir_Value_Literal_Acc; A_Type : Iir) is
419   begin
420      if Value = null then
421         Put ("!NULL!");
422         return;
423      end if;
424      case Value.Kind is
425         when Iir_Value_Scalars
426           | Iir_Value_Access =>
427            Disp_Iir_Value (Value, A_Type);
428         when Iir_Value_Array =>
429            Disp_Signal_Array (Value, A_Type, 1);
430         when Iir_Value_Record =>
431            Disp_Signal_Record (Value, A_Type);
432         when Iir_Value_Range =>
433            -- FIXME.
434            raise Internal_Error;
435         when Iir_Value_Signal =>
436            declare
437               Sig : constant Ghdl_Signal_Ptr := Value.Sig;
438            begin
439               Disp_Signal_Value (Sig.Value_Ptr.all, Sig.Mode, A_Type);
440               Grt.Disp_Signals.Disp_Single_Signal_Attributes (Value.Sig);
441               New_Line;
442               if Sig.S.Mode_Sig in Mode_Signal_User then
443                  for I in 1 .. Sig.S.Nbr_Drivers loop
444                     Put ("    ");
445                     Disp_Transaction (Sig.S.Drivers (I - 1).First_Trans,
446                                       Sig.Mode, A_Type);
447                     New_Line;
448                  end loop;
449               end if;
450            end;
451         when Iir_Value_File
452           | Iir_Value_Protected
453           | Iir_Value_Quantity
454           | Iir_Value_Terminal
455           | Iir_Value_Instance =>
456            raise Internal_Error;
457      end case;
458   end Disp_Signal;
459
460   procedure Disp_Instance_Signal (Instance: Block_Instance_Acc; Decl : Iir)
461   is
462      Info : constant Sim_Info_Acc := Get_Info (Decl);
463   begin
464      Put ("  ");
465      Put (Name_Table.Image (Get_Identifier (Decl)));
466      Put (" = ");
467      Disp_Signal (Instance.Objects (Info.Slot), Get_Type (Decl));
468   end Disp_Instance_Signal;
469
470   procedure Disp_Instance_Signals_Of_Chain (Instance: Block_Instance_Acc;
471                                             Chain : Iir)
472   is
473      El : Iir;
474   begin
475      El := Chain;
476      while El /= Null_Iir loop
477         case Get_Kind (El) is
478            when Iir_Kind_Signal_Declaration
479              | Iir_Kind_Interface_Signal_Declaration =>
480               Disp_Instance_Signal (Instance, El);
481            when others =>
482               null;
483         end case;
484         El := Get_Chain (El);
485      end loop;
486   end Disp_Instance_Signals_Of_Chain;
487
488   procedure Disp_Instance_Signals (Instance: Block_Instance_Acc)
489   is
490      Blk : constant Iir := Instance.Label;
491      Child: Block_Instance_Acc;
492   begin
493      case Get_Kind (Blk) is
494         when Iir_Kind_Architecture_Body =>
495            declare
496               Ent : constant Iir := Get_Entity (Blk);
497            begin
498               Disp_Instance_Name (Instance);
499               Put_Line (" [architecture]:");
500
501               Disp_Instance_Signals_Of_Chain
502                 (Instance, Get_Port_Chain (Ent));
503               Disp_Instance_Signals_Of_Chain
504                 (Instance, Get_Declaration_Chain (Ent));
505               Disp_Instance_Signals_Of_Chain
506                 (Instance, Get_Declaration_Chain (Blk));
507            end;
508         when Iir_Kind_Block_Statement =>
509            Disp_Instance_Name (Instance);
510            Put_Line (" [block]:");
511
512            declare
513               Header : constant Iir := Get_Block_Header (Blk);
514            begin
515               if Header /= Null_Iir then
516                  Disp_Instance_Signals_Of_Chain
517                    (Instance, Get_Port_Chain (Header));
518               end if;
519            end;
520            Disp_Instance_Signals_Of_Chain
521              (Instance, Get_Declaration_Chain (Blk));
522
523         when Iir_Kind_If_Generate_Statement
524           | Iir_Kind_For_Generate_Statement =>
525            Disp_Instance_Name (Instance);
526            Put_Line (" [generate]:");
527
528         when Iir_Kind_Generate_Statement_Body =>
529            Disp_Instance_Signals_Of_Chain
530              (Instance, Get_Declaration_Chain (Blk));
531         when Iir_Kind_Component_Instantiation_Statement =>
532            Disp_Instance_Name (Instance);
533            Put_Line (" [component]:");
534            Disp_Instance_Signals_Of_Chain
535              (Instance, Get_Port_Chain (Instance.Stmt));
536         when Iir_Kinds_Process_Statement =>
537            null;
538         when Iir_Kind_Iterator_Declaration =>
539            null;
540         when others =>
541            Error_Kind ("disp_instance_signals", Instance.Label);
542      end case;
543
544      Child := Instance.Children;
545      while Child /= null loop
546         Disp_Instance_Signals (Child);
547         Child := Child.Brother;
548      end loop;
549   end Disp_Instance_Signals;
550
551   --  Disp all signals name and values.
552   procedure Disp_Signals_Value is
553   begin
554      if Disp_Time_Before_Values then
555         Grt.Disp.Disp_Now;
556      end if;
557      Disp_Instance_Signals (Top_Instance);
558   end Disp_Signals_Value;
559
560   procedure Disp_Label (Process : Iir)
561   is
562      Label : Name_Id;
563   begin
564      Label := Get_Label (Process);
565      if Label = Null_Identifier then
566         Put ("<unlabeled>");
567      else
568         Put (Name_Table.Image (Label));
569      end if;
570   end Disp_Label;
571
572   procedure Disp_Declaration_Object
573     (Instance : Block_Instance_Acc; Decl : Iir) is
574   begin
575      case Get_Kind (Decl) is
576         when Iir_Kind_Constant_Declaration
577           | Iir_Kind_Variable_Declaration
578           | Iir_Kind_Interface_Variable_Declaration
579           | Iir_Kind_Interface_Constant_Declaration
580           | Iir_Kind_Interface_File_Declaration
581           | Iir_Kind_Object_Alias_Declaration =>
582            Put (Disp_Node (Decl));
583            Put (" = ");
584            Disp_Value_Tab (Instance.Objects (Get_Info (Decl).Slot), 3);
585         when Iir_Kind_Interface_Signal_Declaration
586           | Iir_Kind_Signal_Declaration =>
587            declare
588               Sig : Iir_Value_Literal_Acc;
589            begin
590               Sig := Instance.Objects (Get_Info (Decl).Slot);
591               Put (Disp_Node (Decl));
592               Put (" = ");
593               Disp_Signal (Sig, Get_Type (Decl));
594               New_Line;
595            end;
596         when Iir_Kinds_Signal_Attribute =>
597            --  FIXME: todo ?
598            null;
599         when Iir_Kind_Type_Declaration
600           | Iir_Kind_Anonymous_Type_Declaration
601           | Iir_Kind_Subtype_Declaration =>
602            --  FIXME: disp ranges
603            null;
604         when others =>
605            Error_Kind ("disp_declaration_object", Decl);
606      end case;
607   end Disp_Declaration_Object;
608
609   procedure Disp_Declaration_Objects
610     (Instance : Block_Instance_Acc; Decl_Chain : Iir)
611   is
612      El : Iir;
613   begin
614      El := Decl_Chain;
615      while El /= Null_Iir loop
616         Disp_Declaration_Object (Instance, El);
617         El := Get_Chain (El);
618      end loop;
619   end Disp_Declaration_Objects;
620
621   procedure Disp_Objects (Instance : Block_Instance_Acc)
622   is
623      Decl : constant Iir := Instance.Label;
624   begin
625      Disp_Instance_Name (Instance);
626      New_Line;
627      case Get_Kind (Decl) is
628         when Iir_Kind_Procedure_Declaration
629           | Iir_Kind_Function_Declaration =>
630            Disp_Declaration_Objects
631              (Instance, Get_Interface_Declaration_Chain (Decl));
632            Disp_Declaration_Objects
633              (Instance,
634               Get_Declaration_Chain (Get_Subprogram_Body (Decl)));
635         when Iir_Kind_Architecture_Body =>
636            declare
637               Entity : constant Iir_Entity_Declaration := Get_Entity (Decl);
638            begin
639               Disp_Declaration_Objects
640                 (Instance, Get_Generic_Chain (Entity));
641               Disp_Declaration_Objects
642                 (Instance, Get_Port_Chain (Entity));
643               Disp_Declaration_Objects
644                 (Instance, Get_Declaration_Chain (Entity));
645               Disp_Declaration_Objects
646                 (Instance, Get_Declaration_Chain (Decl));
647               --  FIXME: processes.
648            end;
649         when Iir_Kind_Component_Instantiation_Statement =>
650            null;
651         when others =>
652            Error_Kind ("disp_objects", Decl);
653      end case;
654   end Disp_Objects;
655   pragma Unreferenced (Disp_Objects);
656
657   procedure Disp_Process_Stats
658   is
659      Proc : Iir;
660      Stmt : Iir;
661      Nbr_User_Sensitized_Processes : Natural := 0;
662      Nbr_User_If_Sensitized_Processes : Natural := 0;
663      Nbr_Conc_Sensitized_Processes : Natural := 0;
664      Nbr_User_Non_Sensitized_Processes : Natural := 0;
665      Nbr_Conc_Non_Sensitized_Processes : Natural := 0;
666   begin
667      for I in Processes_Table.First .. Processes_Table.Last loop
668         Proc := Processes_Table.Table (I).Label;
669         case Get_Kind (Proc) is
670            when Iir_Kind_Sensitized_Process_Statement =>
671               if Get_Process_Origin (Proc) = Null_Iir then
672                  Stmt := Get_Sequential_Statement_Chain (Proc);
673                  if Stmt /= Null_Iir
674                    and then Get_Kind (Stmt) = Iir_Kind_If_Statement
675                    and then Get_Chain (Stmt) = Null_Iir
676                  then
677                     Nbr_User_If_Sensitized_Processes :=
678                       Nbr_User_If_Sensitized_Processes + 1;
679                  else
680                     Nbr_User_Sensitized_Processes :=
681                       Nbr_User_Sensitized_Processes + 1;
682                  end if;
683               else
684                  Nbr_Conc_Sensitized_Processes :=
685                    Nbr_Conc_Sensitized_Processes + 1;
686               end if;
687            when Iir_Kind_Process_Statement =>
688               if Get_Process_Origin (Proc) = Null_Iir then
689                  Nbr_User_Non_Sensitized_Processes :=
690                    Nbr_User_Non_Sensitized_Processes + 1;
691               else
692                  Nbr_Conc_Non_Sensitized_Processes :=
693                    Nbr_Conc_Non_Sensitized_Processes + 1;
694               end if;
695            when others =>
696               raise Internal_Error;
697         end case;
698      end loop;
699
700      Put (Natural'Image (Nbr_User_If_Sensitized_Processes));
701      Put_Line (" user sensitized processes with only a if stmt");
702      Put (Natural'Image (Nbr_User_Sensitized_Processes));
703      Put_Line (" user sensitized processes (others)");
704      Put (Natural'Image (Nbr_User_Non_Sensitized_Processes));
705      Put_Line (" user non sensitized processes");
706      Put (Natural'Image (Nbr_Conc_Sensitized_Processes));
707      Put_Line (" sensitized concurrent statements");
708      Put (Natural'Image (Nbr_Conc_Non_Sensitized_Processes));
709      Put_Line (" non sensitized concurrent statements");
710      Put (Process_Index_Type'Image (Processes_Table.Last));
711      Put_Line (" processes (total)");
712   end Disp_Process_Stats;
713
714   procedure Disp_Signals_Stats
715   is
716      type Counters_Type is array (Mode_Signal_Type) of Natural;
717      Counters : Counters_Type := (others => 0);
718      Nbr_User_Signals : Natural := 0;
719      Nbr_Signal_Elements : Natural := 0;
720   begin
721      for I in Signals_Table.First .. Signals_Table.Last loop
722         declare
723            Ent : Signal_Entry renames Signals_Table.Table (I);
724         begin
725            if Ent.Kind in Mode_Signal_User then
726               Nbr_User_Signals := Nbr_User_Signals + 1;
727               Nbr_Signal_Elements := Nbr_Signal_Elements +
728                 Get_Nbr_Of_Scalars (Signals_Table.Table (I).Sig);
729            end if;
730            Counters (Ent.Kind) := Counters (Ent.Kind) + 1;
731         end;
732      end loop;
733      Put (Integer'Image (Nbr_User_Signals));
734      Put_Line (" declared user signals or ports");
735      Put (Integer'Image (Nbr_Signal_Elements));
736      Put_Line (" user signals sub-elements");
737      Put (Integer'Image (Counters (Mode_Quiet)));
738      Put_Line (" 'quiet implicit signals");
739      Put (Integer'Image (Counters (Mode_Stable)));
740      Put_Line (" 'stable implicit signals");
741      Put (Integer'Image (Counters (Mode_Delayed)));
742      Put_Line (" 'delayed implicit signals");
743      Put (Integer'Image (Counters (Mode_Transaction)));
744      Put_Line (" 'transaction implicit signals");
745      Put (Integer'Image (Counters (Mode_Guard)));
746      Put_Line (" guard signals");
747   end Disp_Signals_Stats;
748
749   procedure Disp_Design_Stats is
750   begin
751      Disp_Process_Stats;
752
753      New_Line;
754
755      Disp_Signals_Stats;
756
757      New_Line;
758
759      Put (Integer'Image (Connect_Table.Last));
760      Put_Line (" connections");
761   end Disp_Design_Stats;
762
763   procedure Disp_Design_Non_Sensitized
764   is
765      Instance : Block_Instance_Acc;
766      Proc : Iir;
767   begin
768      for I in Processes_Table.First .. Processes_Table.Last loop
769         Instance := Processes_Table.Table (I);
770         Proc := Processes_Table.Table (I).Label;
771         if Get_Kind (Proc) = Iir_Kind_Process_Statement then
772            Disp_Instance_Name (Instance);
773            New_Line;
774            Put_Line ("   at " & Disp_Location (Proc));
775         end if;
776      end loop;
777   end Disp_Design_Non_Sensitized;
778
779   procedure Disp_Design_Connections is
780   begin
781      for I in Connect_Table.First .. Connect_Table.Last loop
782         declare
783            Conn : Connect_Entry renames Connect_Table.Table (I);
784         begin
785            Disp_Iir_Location (Conn.Assoc);
786            New_Line;
787         end;
788      end loop;
789   end Disp_Design_Connections;
790
791   function Walk_Files (Cb : Walk_Cb) return Walk_Status
792   is
793      Lib : Iir_Library_Declaration := Libraries.Get_Libraries_Chain;
794      File : Iir_Design_File;
795   begin
796      while Lib /= Null_Iir loop
797         File := Get_Design_File_Chain (Lib);
798         while File /= Null_Iir loop
799            case Cb.all (File) is
800               when Walk_Continue =>
801                  null;
802               when Walk_Up =>
803                  exit;
804               when Walk_Abort =>
805                  return Walk_Abort;
806            end case;
807            File := Get_Chain (File);
808         end loop;
809         Lib := Get_Chain (Lib);
810      end loop;
811      return Walk_Continue;
812   end Walk_Files;
813
814   Walk_Units_Cb : Walk_Cb;
815
816   function Cb_Walk_Units (Design_File : Iir) return Walk_Status
817   is
818      Unit : Iir_Design_Unit;
819   begin
820      Unit := Get_First_Design_Unit (Design_File);
821      while Unit /= Null_Iir loop
822         case Walk_Units_Cb.all (Get_Library_Unit (Unit)) is
823            when Walk_Continue =>
824               null;
825            when Walk_Abort =>
826               return Walk_Abort;
827            when Walk_Up =>
828               exit;
829         end case;
830         Unit := Get_Chain (Unit);
831      end loop;
832      return Walk_Continue;
833   end Cb_Walk_Units;
834
835   function Walk_Units (Cb : Walk_Cb) return Walk_Status is
836   begin
837      Walk_Units_Cb := Cb;
838      return Walk_Files (Cb_Walk_Units'Access);
839   end Walk_Units;
840
841   Walk_Declarations_Cb : Walk_Cb;
842
843   function Cb_Walk_Declarations (Unit : Iir) return Walk_Status
844   is
845      function Walk_Decl_Chain (Chain : Iir) return Walk_Status
846      is
847         Decl : Iir;
848      begin
849         Decl := Chain;
850         while Decl /= Null_Iir loop
851            case Walk_Declarations_Cb.all (Decl) is
852               when Walk_Abort =>
853                  return Walk_Abort;
854               when Walk_Up =>
855                  return Walk_Continue;
856               when Walk_Continue =>
857                  null;
858            end case;
859            Decl := Get_Chain (Decl);
860         end loop;
861         return Walk_Continue;
862      end Walk_Decl_Chain;
863
864      function Walk_Conc_Chain (Chain : Iir) return Walk_Status;
865
866      function Walk_Generate_Statement_Body (Bod : Iir) return Walk_Status is
867      begin
868         if Walk_Decl_Chain (Get_Declaration_Chain (Bod)) = Walk_Abort then
869            return Walk_Abort;
870         end if;
871         if Walk_Conc_Chain (Get_Concurrent_Statement_Chain (Bod)) = Walk_Abort
872         then
873            return Walk_Abort;
874         end if;
875         return Walk_Continue;
876      end Walk_Generate_Statement_Body;
877
878      function Walk_Conc_Chain (Chain : Iir) return Walk_Status
879      is
880         Stmt : Iir := Chain;
881      begin
882         while Stmt /= Null_Iir loop
883            case Get_Kind (Stmt) is
884               when Iir_Kinds_Process_Statement =>
885                  if Walk_Decl_Chain (Get_Declaration_Chain (Stmt))
886                    = Walk_Abort
887                  then
888                     return Walk_Abort;
889                  end if;
890               when Iir_Kind_For_Generate_Statement =>
891                  if Walk_Declarations_Cb.all
892                    (Get_Parameter_Specification (Stmt)) = Walk_Abort
893                    or else Walk_Generate_Statement_Body
894                    (Get_Generate_Statement_Body (Stmt)) = Walk_Abort
895                  then
896                     return Walk_Abort;
897                  end if;
898               when Iir_Kind_If_Generate_Statement =>
899                  declare
900                     Stmt1 : Iir;
901                  begin
902                     Stmt1 := Stmt;
903                     while Stmt1 /= Null_Iir loop
904                        if Walk_Generate_Statement_Body
905                          (Get_Generate_Statement_Body (Stmt)) = Walk_Abort
906                        then
907                           return Walk_Abort;
908                        end if;
909                        Stmt1 := Get_Generate_Else_Clause (Stmt1);
910                     end loop;
911                  end;
912               when Iir_Kind_Component_Instantiation_Statement =>
913                  null;
914               when Iir_Kind_Block_Statement =>
915                  --  FIXME: header
916                  if (Walk_Decl_Chain
917                        (Get_Declaration_Chain (Stmt)) = Walk_Abort)
918                    or else
919                    (Walk_Conc_Chain
920                       (Get_Concurrent_Statement_Chain (Stmt)) = Walk_Abort)
921                  then
922                     return Walk_Abort;
923                  end if;
924               when others =>
925                  Error_Kind ("walk_conc_chain", Stmt);
926            end case;
927            Stmt := Get_Chain (Stmt);
928         end loop;
929         return Walk_Continue;
930      end Walk_Conc_Chain;
931   begin
932      case Get_Kind (Unit) is
933         when Iir_Kind_Entity_Declaration =>
934            if Walk_Decl_Chain (Get_Generic_Chain (Unit)) = Walk_Abort
935              or else Walk_Decl_Chain (Get_Port_Chain (Unit)) = Walk_Abort
936              or else (Walk_Decl_Chain
937                         (Get_Declaration_Chain (Unit)) = Walk_Abort)
938              or else (Walk_Conc_Chain
939                         (Get_Concurrent_Statement_Chain (Unit)) = Walk_Abort)
940            then
941               return Walk_Abort;
942            end if;
943         when Iir_Kind_Architecture_Body =>
944            if (Walk_Decl_Chain
945                  (Get_Declaration_Chain (Unit)) = Walk_Abort)
946              or else (Walk_Conc_Chain
947                         (Get_Concurrent_Statement_Chain (Unit)) = Walk_Abort)
948            then
949               return Walk_Abort;
950            end if;
951         when Iir_Kind_Package_Declaration
952           | Iir_Kind_Package_Body =>
953            if Walk_Decl_Chain (Get_Declaration_Chain (Unit)) = Walk_Abort
954            then
955               return Walk_Abort;
956            end if;
957         when Iir_Kind_Configuration_Declaration =>
958            if Walk_Decl_Chain (Get_Declaration_Chain (Unit)) = Walk_Abort
959            then
960               return Walk_Abort;
961            end if;
962            --  FIXME: block configuration ?
963         when Iir_Kind_Context_Declaration =>
964            null;
965         when others =>
966            Error_Kind ("Cb_Walk_Declarations", Unit);
967      end case;
968      return Walk_Continue;
969   end Cb_Walk_Declarations;
970
971   function Walk_Declarations (Cb : Walk_Cb) return Walk_Status is
972   begin
973      Walk_Declarations_Cb := Cb;
974      return Walk_Units (Cb_Walk_Declarations'Access);
975   end Walk_Declarations;
976
977   function Is_Blank (C : Character) return Boolean is
978   begin
979      return C = ' ' or else C = ASCII.HT;
980   end Is_Blank;
981
982   function Skip_Blanks (S : String) return Positive
983   is
984      P : Positive := S'First;
985   begin
986      while P <= S'Last and then Is_Blank (S (P)) loop
987         P := P + 1;
988      end loop;
989      return P;
990   end Skip_Blanks;
991
992   --  Return the position of the last character of the word (the last
993   --  non-blank character).
994   function Get_Word (S : String) return Positive
995   is
996      P : Positive := S'First;
997   begin
998      while P <= S'Last and then not Is_Blank (S (P)) loop
999         P := P + 1;
1000      end loop;
1001      return P - 1;
1002   end Get_Word;
1003
1004   procedure Disp_A_Frame (Instance: Block_Instance_Acc) is
1005   begin
1006      if Instance = Global_Instances then
1007         pragma Assert (Instance.Label = Null_Iir);
1008         Put_Line ("global instances");
1009         return;
1010      end if;
1011
1012      Put (Disp_Node (Instance.Label));
1013      if Instance.Stmt /= Null_Iir then
1014         Put (" at ");
1015         Put (Files_Map.Image (Get_Location (Instance.Stmt)));
1016      end if;
1017      New_Line;
1018   end Disp_A_Frame;
1019
1020   procedure Debug_Bt (Instance : Block_Instance_Acc)
1021   is
1022      Inst : Block_Instance_Acc;
1023   begin
1024      Inst := Instance;
1025      while Inst /= null loop
1026         Disp_A_Frame (Inst);
1027         Inst := Inst.Parent;
1028      end loop;
1029   end Debug_Bt;
1030   pragma Unreferenced (Debug_Bt);
1031
1032   procedure Debug_Upblock (Instance : Block_Instance_Acc)
1033   is
1034      Inst : Block_Instance_Acc;
1035   begin
1036      Inst := Instance;
1037      while Inst /= null loop
1038         Disp_A_Frame (Inst);
1039         Inst := Inst.Up_Block;
1040      end loop;
1041   end Debug_Upblock;
1042   pragma Unreferenced (Debug_Upblock);
1043
1044   procedure Disp_Current_Lines
1045   is
1046      use Files_Map;
1047      --  Number of lines to display before and after the current line.
1048      Radius : constant := 5;
1049
1050      Buf : File_Buffer_Acc;
1051
1052      Pos : Source_Ptr;
1053      Line : Natural;
1054      Len : Source_Ptr;
1055      C : Character;
1056   begin
1057      if List_Current_Line > Radius then
1058         Line := List_Current_Line - Radius;
1059      else
1060         Line := 1;
1061      end if;
1062
1063      Pos := File_Line_To_Position (List_Current_File, Line);
1064      Buf := Get_File_Source (List_Current_File);
1065
1066      while Line < List_Current_Line + Radius loop
1067         --  Compute line length.
1068         Len := 0;
1069         loop
1070            C := Buf (Pos + Len);
1071            exit when C = ASCII.CR or C = ASCII.LF or C = ASCII.EOT;
1072            Len := Len + 1;
1073         end loop;
1074
1075         --  Disp line number.
1076         declare
1077            Str : constant String := Natural'Image (Line);
1078         begin
1079            if Line = List_Current_Line then
1080               Put ('*');
1081            else
1082               Put (' ');
1083            end if;
1084            Put ((Str'Length .. 5 => ' '));
1085            Put (Str (Str'First + 1 .. Str'Last));
1086            Put (' ');
1087         end;
1088
1089         --  Disp line.
1090         Put_Line (String (Buf (Pos .. Pos + Len - 1)));
1091
1092         --  Skip EOL.
1093         exit when C = ASCII.EOT;
1094         Pos := Pos + Len + 1;
1095         if C = ASCII.CR then
1096            if Buf (Pos) = ASCII.LF then
1097               Pos := Pos + 1;
1098            end if;
1099         else
1100            pragma Assert (C = ASCII.LF);
1101            if Buf (Pos) = ASCII.CR then
1102               Pos := Pos + 1;
1103            end if;
1104         end if;
1105
1106         Line := Line + 1;
1107      end loop;
1108   end Disp_Current_Lines;
1109
1110   procedure Disp_Source_Line (Loc : Location_Type)
1111   is
1112      use Files_Map;
1113
1114      File : Source_File_Entry;
1115      Line_Pos : Source_Ptr;
1116      Line : Natural;
1117      Offset : Natural;
1118      Buf : File_Buffer_Acc;
1119      Next_Line_Pos : Source_Ptr;
1120   begin
1121      Location_To_Coord (Loc, File, Line_Pos, Line, Offset);
1122      Buf := Get_File_Source (File);
1123      Next_Line_Pos := File_Line_To_Position (File, Line + 1);
1124      Put (String (Buf (Line_Pos .. Next_Line_Pos - 1)));
1125   end Disp_Source_Line;
1126
1127   type Menu_Kind is (Menu_Command, Menu_Submenu);
1128   type Menu_Entry (Kind : Menu_Kind);
1129   type Menu_Entry_Acc is access all Menu_Entry;
1130
1131   type Cst_String_Acc is access constant String;
1132
1133   type Menu_Entry (Kind : Menu_Kind) is record
1134      Name : Cst_String_Acc;
1135      Next : Menu_Entry_Acc;
1136
1137      case Kind is
1138         when Menu_Command =>
1139            Proc : Menu_Procedure;
1140         when Menu_Submenu =>
1141            First, Last : Menu_Entry_Acc := null;
1142      end case;
1143   end record;
1144
1145   --  Check there is a current process.
1146   procedure Check_Current_Process is
1147   begin
1148      if Current_Process = null then
1149         Put_Line ("no current process");
1150         raise Command_Error;
1151      end if;
1152   end Check_Current_Process;
1153
1154   --  The status of the debugger.  This status can be modified by a command
1155   --  as a side effect to resume or quit the debugger.
1156   type Command_Status_Type is (Status_Default, Status_Quit);
1157   Command_Status : Command_Status_Type;
1158
1159   procedure Help_Proc (Line : String);
1160
1161   procedure Disp_Process_Loc (Proc : Process_State_Type) is
1162   begin
1163      Disp_Instance_Name (Proc.Top_Instance);
1164      Put (" (" & Files_Map.Image (Get_Location (Proc.Proc)) & ")");
1165      New_Line;
1166   end Disp_Process_Loc;
1167
1168   --  Disp the list of processes (and its state)
1169   procedure Ps_Proc (Line : String) is
1170      pragma Unreferenced (Line);
1171      Process : Iir;
1172   begin
1173      if Processes_State = null then
1174         Put_Line ("no processes");
1175         return;
1176      end if;
1177
1178      for I in Processes_State'Range loop
1179         Put (Process_Index_Type'Image (I) & ": ");
1180         Process := Processes_State (I).Proc;
1181         if Process /= Null_Iir then
1182            Disp_Process_Loc (Processes_State (I));
1183            Disp_A_Frame (Processes_State (I).Instance);
1184         else
1185            Put_Line ("not yet elaborated");
1186         end if;
1187      end loop;
1188   end Ps_Proc;
1189
1190   procedure List_Proc (Line : String)
1191   is
1192      pragma Unreferenced (Line);
1193   begin
1194      Disp_Current_Lines;
1195   end List_Proc;
1196
1197   procedure Up_Proc (Line : String)
1198   is
1199      pragma Unreferenced (Line);
1200   begin
1201      Check_Current_Process;
1202      if Dbg_Cur_Frame.Parent = null then
1203         Put_Line ("top of frames reached");
1204      else
1205         Set_Cur_Frame (Dbg_Cur_Frame.Parent);
1206      end if;
1207   end Up_Proc;
1208
1209   procedure Down_Proc (Line : String)
1210   is
1211      pragma Unreferenced (Line);
1212      Inst : Block_Instance_Acc;
1213   begin
1214      Check_Current_Process;
1215      if Dbg_Cur_Frame = Dbg_Top_Frame then
1216         Put_Line ("bottom of frames reached");
1217      else
1218         Inst := Dbg_Top_Frame;
1219         while Inst.Parent /= Dbg_Cur_Frame loop
1220            Inst := Inst.Parent;
1221         end loop;
1222         Set_Cur_Frame (Inst);
1223      end if;
1224   end Down_Proc;
1225
1226   procedure Set_Breakpoint (Stmt : Iir) is
1227   begin
1228      Put_Line ("set breakpoint at: " & Files_Map.Image (Get_Location (Stmt)));
1229      Breakpoints.Append (Breakpoint_Entry'(Stmt => Stmt));
1230      Flag_Need_Debug := True;
1231   end Set_Breakpoint;
1232
1233   function Is_Within_Statement (Stmt : Iir; Cur : Iir) return Boolean
1234   is
1235      Parent : Iir;
1236   begin
1237      Parent := Cur;
1238      loop
1239         if Parent = Stmt then
1240            return True;
1241         end if;
1242         case Get_Kind (Parent) is
1243            when Iir_Kinds_Sequential_Statement =>
1244               Parent := Get_Parent (Parent);
1245            when others =>
1246               return False;
1247         end case;
1248      end loop;
1249   end Is_Within_Statement;
1250
1251   --  Next statement in the same frame, but handle compound statements as
1252   --  one statement.
1253   procedure Next_Stmt_Proc (Line : String)
1254   is
1255      pragma Unreferenced (Line);
1256   begin
1257      Exec_State := Exec_Next_Stmt;
1258      Exec_Instance := Dbg_Top_Frame;
1259      Exec_Statement := Dbg_Top_Frame.Stmt;
1260      Flag_Need_Debug := True;
1261      Command_Status := Status_Quit;
1262   end Next_Stmt_Proc;
1263
1264   --  Finish parent statement.
1265   procedure Finish_Stmt_Proc (Line : String)
1266   is
1267      pragma Unreferenced (Line);
1268   begin
1269      Exec_State := Exec_Next_Stmt;
1270      Exec_Instance := Dbg_Top_Frame;
1271      Exec_Statement := Get_Parent (Dbg_Top_Frame.Stmt);
1272      Flag_Need_Debug := True;
1273      Command_Status := Status_Quit;
1274   end Finish_Stmt_Proc;
1275
1276   procedure Next_Proc (Line : String)
1277   is
1278      pragma Unreferenced (Line);
1279   begin
1280      Exec_State := Exec_Next;
1281      Exec_Instance := Dbg_Top_Frame;
1282      Flag_Need_Debug := True;
1283      Command_Status := Status_Quit;
1284      Cmd_Repeat := Next_Proc'Access;
1285   end Next_Proc;
1286
1287   procedure Step_Proc (Line : String)
1288   is
1289      pragma Unreferenced (Line);
1290   begin
1291      Exec_State := Exec_Single_Step;
1292      Flag_Need_Debug := True;
1293      Command_Status := Status_Quit;
1294      Cmd_Repeat := Step_Proc'Access;
1295   end Step_Proc;
1296
1297   Break_Id : Name_Id;
1298
1299   function Cb_Set_Break (El : Iir) return Walk_Status is
1300   begin
1301      case Get_Kind (El) is
1302         when Iir_Kind_Function_Declaration
1303           | Iir_Kind_Procedure_Declaration =>
1304            if Get_Identifier (El) = Break_Id
1305              and then
1306              Get_Implicit_Definition (El) not in Iir_Predefined_Implicit
1307            then
1308               Set_Breakpoint
1309                 (Get_Sequential_Statement_Chain (Get_Subprogram_Body (El)));
1310            end if;
1311         when others =>
1312            null;
1313      end case;
1314      return Walk_Continue;
1315   end Cb_Set_Break;
1316
1317   procedure Break_Proc (Line : String)
1318   is
1319      Status : Walk_Status;
1320      P : Natural;
1321   begin
1322      P := Skip_Blanks (Line);
1323      if Line (P) = '"' then
1324         --  An operator name.
1325         declare
1326            use Str_Table;
1327            Str : String8_Id;
1328            Len : Nat32;
1329         begin
1330            Str := Create_String8;
1331            Len := 0;
1332            P := P + 1;
1333            while Line (P) /= '"' loop
1334               Append_String8_Char (Line (P));
1335               Len := Len + 1;
1336               P := P + 1;
1337            end loop;
1338            Break_Id := Vhdl.Parse.Str_To_Operator_Name
1339              (Str, Len, No_Location);
1340            --  FIXME: free string.
1341            --  FIXME: catch error.
1342         end;
1343      else
1344         Break_Id := Name_Table.Get_Identifier (Line (P .. Line'Last));
1345      end if;
1346      Status := Walk_Declarations (Cb_Set_Break'Access);
1347      pragma Assert (Status = Walk_Continue);
1348   end Break_Proc;
1349
1350   procedure Where_Proc (Line : String) is
1351      pragma Unreferenced (Line);
1352      Frame : Block_Instance_Acc;
1353   begin
1354      Check_Current_Process;
1355      Frame := Dbg_Top_Frame;
1356      while Frame /= null loop
1357         if Frame = Dbg_Cur_Frame then
1358            Put ("* ");
1359         else
1360            Put ("  ");
1361         end if;
1362         Disp_A_Frame (Frame);
1363         Frame := Frame.Parent;
1364      end loop;
1365   end Where_Proc;
1366
1367   procedure Info_Tree_Proc (Line : String)
1368   is
1369      pragma Unreferenced (Line);
1370   begin
1371      if Top_Instance = null then
1372         Put_Line ("design not yet fully elaborated");
1373      else
1374         Disp_Instances_Tree;
1375      end if;
1376   end Info_Tree_Proc;
1377
1378   procedure Info_Instances_Proc (Line : String)
1379   is
1380      pragma Unreferenced (Line);
1381      procedure Disp_Instances (Inst : Block_Instance_Acc)
1382      is
1383         Child : Block_Instance_Acc;
1384      begin
1385         case Get_Kind (Inst.Label) is
1386            when Iir_Kind_Architecture_Body =>
1387               Disp_Instances_Tree_Name (Inst);
1388            when others =>
1389               null;
1390         end case;
1391
1392         Child := Inst.Children;
1393         while Child /= null loop
1394            if Get_Kind (Child.Label) not in Iir_Kinds_Process_Statement then
1395               Disp_Instances (Child);
1396            end if;
1397            Child := Child.Brother;
1398         end loop;
1399
1400      end Disp_Instances;
1401   begin
1402      if Top_Instance = null then
1403         Put_Line ("design not yet fully elaborated");
1404         return;
1405      end if;
1406      for I in Global_Instances.Objects'Range loop
1407         if Global_Instances.Objects (I) /= null then
1408            Put (Get_Instance_Local_Name
1409                   (Global_Instances.Objects (I).Instance));
1410            Put_Line (" [package]");
1411         end if;
1412      end loop;
1413      Disp_Instances (Top_Instance);
1414   end Info_Instances_Proc;
1415
1416   procedure Info_Params_Proc (Line : String)
1417   is
1418      pragma Unreferenced (Line);
1419      Decl : Iir;
1420      Params : Iir;
1421   begin
1422      Check_Current_Process;
1423      if Dbg_Cur_Frame = null then
1424         Put_Line ("not in a subprogram");
1425         return;
1426      end if;
1427      Decl := Dbg_Cur_Frame.Label;
1428      if Decl = Null_Iir
1429        or else Get_Kind (Decl) not in Iir_Kinds_Subprogram_Declaration
1430      then
1431         Put_Line ("current frame is not a subprogram");
1432         return;
1433      end if;
1434      Params := Get_Interface_Declaration_Chain (Decl);
1435      Disp_Declaration_Objects (Dbg_Cur_Frame, Params);
1436   end Info_Params_Proc;
1437
1438   procedure Info_Proc_Proc (Line : String) is
1439      pragma Unreferenced (Line);
1440   begin
1441      Check_Current_Process;
1442      Disp_Process_Loc (Current_Process.all);
1443   end Info_Proc_Proc;
1444
1445   function Cb_Disp_Subprograms (El : Iir) return Walk_Status is
1446   begin
1447      case Get_Kind (El) is
1448         when Iir_Kind_Function_Declaration
1449           | Iir_Kind_Procedure_Declaration =>
1450            Put_Line (Name_Table.Image (Get_Identifier (El)));
1451         when others =>
1452            null;
1453      end case;
1454      return Walk_Continue;
1455   end Cb_Disp_Subprograms;
1456
1457   procedure Info_Subprograms_Proc (Line : String) is
1458      pragma Unreferenced (Line);
1459      Status : Walk_Status;
1460   begin
1461      Status := Walk_Declarations (Cb_Disp_Subprograms'Access);
1462      pragma Assert (Status = Walk_Continue);
1463   end Info_Subprograms_Proc;
1464
1465   function Cb_Disp_Units (El : Iir) return Walk_Status is
1466   begin
1467      case Get_Kind (El) is
1468         when Iir_Kind_Package_Declaration =>
1469            Put ("package ");
1470            Put_Line (Name_Table.Image (Get_Identifier (El)));
1471         when Iir_Kind_Entity_Declaration =>
1472            Put ("entity ");
1473            Put_Line (Name_Table.Image (Get_Identifier (El)));
1474         when Iir_Kind_Architecture_Body =>
1475            Put ("architecture ");
1476            Put (Name_Table.Image (Get_Identifier (El)));
1477            Put (" of ");
1478            Put_Line (Name_Table.Image (Get_Identifier
1479                                          (Get_Entity_Name (El))));
1480         when Iir_Kind_Configuration_Declaration =>
1481            Put ("configuration ");
1482            Put_Line (Name_Table.Image (Get_Identifier (El)));
1483         when Iir_Kind_Package_Body =>
1484            null;
1485         when others =>
1486            Error_Kind ("cb_disp_units", El);
1487      end case;
1488      return Walk_Continue;
1489   end Cb_Disp_Units;
1490
1491   procedure Info_Units_Proc (Line : String) is
1492      pragma Unreferenced (Line);
1493      Status : Walk_Status;
1494   begin
1495      Status := Walk_Units (Cb_Disp_Units'Access);
1496      pragma Assert (Status = Walk_Continue);
1497   end Info_Units_Proc;
1498
1499   function Cb_Disp_File (El : Iir) return Walk_Status is
1500   begin
1501      Put_Line (Name_Table.Image (Get_Design_File_Filename (El)));
1502      return Walk_Continue;
1503   end Cb_Disp_File;
1504
1505   procedure Info_PSL_Proc (Line : String)
1506   is
1507      pragma Unreferenced (Line);
1508   begin
1509      if PSL_Table.Last < PSL_Table.First then
1510         Put_Line ("no PSL directive");
1511         return;
1512      end if;
1513
1514      for I in PSL_Table.First .. PSL_Table.Last loop
1515         declare
1516            E : PSL_Entry renames PSL_Table.Table (I);
1517         begin
1518            Disp_Instance_Name (E.Instance);
1519            Put ('.');
1520            Put (Name_Table.Image (Get_Identifier (E.Stmt)));
1521            New_Line;
1522            Vhdl.Prints.Disp_PSL_NFA (Get_PSL_NFA (E.Stmt));
1523            Put ("    01234567890123456789012345678901234567890123456789");
1524            for I in E.States'Range loop
1525               if I mod 50 = 0 then
1526                  New_Line;
1527                  Put (Int32'Image (I / 10));
1528                  Put (": ");
1529               end if;
1530               if E.States (I) then
1531                  Put ('*');
1532               else
1533                  Put ('.');
1534               end if;
1535            end loop;
1536            New_Line;
1537         end;
1538      end loop;
1539   end Info_PSL_Proc;
1540
1541   procedure Info_Stats_Proc (Line : String) is
1542      P : Natural := Line'First;
1543      E : Natural;
1544   begin
1545      P := Skip_Blanks (Line (P .. Line'Last));
1546      if P > Line'Last then
1547         --  No parameters.
1548         Disp_Design_Stats;
1549         return;
1550      end if;
1551
1552      E := Get_Word (Line (P .. Line'Last));
1553      if Line (P .. E) = "global" then
1554         Disp_Design_Stats;
1555      elsif Line (P .. E) = "non-sensitized" then
1556         Disp_Design_Non_Sensitized;
1557         null;
1558      elsif Line (P .. E) = "connections" then
1559         Disp_Design_Connections;
1560         --  TODO: nbr of conversions
1561      else
1562         Put_Line ("options are: global, non-sensitized, connections");
1563         --  TODO: signals: nbr of scalars, nbr of non-user...
1564      end if;
1565   end Info_Stats_Proc;
1566
1567   procedure Info_Files_Proc (Line : String)
1568   is
1569      pragma Unreferenced (Line);
1570      Status : Walk_Status;
1571   begin
1572      Status := Walk_Files (Cb_Disp_File'Access);
1573      pragma Assert (Status = Walk_Continue);
1574   end Info_Files_Proc;
1575
1576   procedure Info_Libraries_Proc (Line : String) is
1577      pragma Unreferenced (Line);
1578      Lib : Iir_Library_Declaration := Libraries.Get_Libraries_Chain;
1579   begin
1580      while Lib /= Null_Iir loop
1581         Put_Line (Name_Table.Image (Get_Identifier (Lib)));
1582         Lib := Get_Chain (Lib);
1583      end loop;
1584   end Info_Libraries_Proc;
1585
1586   procedure Disp_Declared_Signals_Chain
1587     (Chain : Iir; Instance : Block_Instance_Acc)
1588   is
1589      pragma Unreferenced (Instance);
1590      Decl : Iir;
1591   begin
1592      Decl := Chain;
1593      while Decl /= Null_Iir loop
1594         case Get_Kind (Decl) is
1595            when Iir_Kind_Interface_Signal_Declaration
1596              | Iir_Kind_Signal_Declaration =>
1597               Put_Line (" " & Name_Table.Image (Get_Identifier (Decl)));
1598            when others =>
1599               null;
1600         end case;
1601         Decl := Get_Chain (Decl);
1602      end loop;
1603   end Disp_Declared_Signals_Chain;
1604
1605   procedure Disp_Declared_Signals (Decl : Iir; Instance : Block_Instance_Acc)
1606   is
1607   begin
1608      case Get_Kind (Decl) is
1609         when Iir_Kind_Sensitized_Process_Statement
1610           | Iir_Kind_Process_Statement =>
1611            Disp_Declared_Signals (Get_Parent (Decl), Instance);
1612         when Iir_Kind_Architecture_Body =>
1613            Disp_Declared_Signals (Get_Entity (Decl), Instance);
1614         when Iir_Kind_Entity_Declaration =>
1615            null;
1616         when others =>
1617            Error_Kind ("disp_declared_signals", Decl);
1618      end case;
1619
1620      case Get_Kind (Decl) is
1621         when Iir_Kind_Sensitized_Process_Statement
1622           | Iir_Kind_Process_Statement =>
1623            --  No signal declaration in a process (FIXME: implicit signals)
1624            null;
1625         when Iir_Kind_Architecture_Body =>
1626            Put_Line ("Signals of architecture "
1627                        & Name_Table.Image (Get_Identifier (Decl)) & ':');
1628            Disp_Declared_Signals_Chain
1629              (Get_Declaration_Chain (Decl), Instance);
1630         when Iir_Kind_Entity_Declaration =>
1631            Put_Line ("Ports of entity "
1632                        & Name_Table.Image (Get_Identifier (Decl)) & ':');
1633            Disp_Declared_Signals_Chain
1634              (Get_Port_Chain (Decl), Instance);
1635         when others =>
1636            Error_Kind ("disp_declared_signals (2)", Decl);
1637      end case;
1638   end Disp_Declared_Signals;
1639
1640   procedure Info_Signals_Proc (Line : String)
1641   is
1642      Verbose : Boolean;
1643      P : Natural;
1644      E : Natural;
1645   begin
1646      Verbose := False;
1647
1648      P := Skip_Blanks (Line);
1649      loop
1650         E := Get_Word (Line (P .. Line'Last));
1651         exit when P > Line'Last;
1652         if Line (P .. E) = "-v" then
1653            Verbose := True;
1654         elsif Line (P .. E) = "-l" then
1655            --  Local signals
1656            Check_Current_Process;
1657            Disp_Declared_Signals
1658              (Current_Process.Proc, Current_Process.Top_Instance);
1659            return;
1660         elsif Line (P .. E) = "-t" then
1661            Disp_Signals_Value;
1662            return;
1663         elsif Line (P .. E) = "-T" then
1664            Grt.Disp_Signals.Disp_Signals_Table;
1665            return;
1666         else
1667            Put_Line ("options: -v(erbose) -l(ocal) -t(ree) -T(able)");
1668            return;
1669         end if;
1670         P := E + 1;
1671      end loop;
1672
1673      for I in Signals_Table.First .. Signals_Table.Last loop
1674         declare
1675            S : Signal_Entry renames Signals_Table.Table (I);
1676         begin
1677            Disp_Instance_Name (S.Instance, False);
1678            Put ('.');
1679            if S.Kind in Grt.Types.Mode_Signal_User then
1680               Put (Name_Table.Image (Get_Identifier (S.Decl)));
1681               New_Line;
1682               Put (" sig: ");
1683               Disp_Value (S.Sig);
1684               Put (" val: ");
1685               Disp_Value (S.Val);
1686               if Verbose then
1687                  --  Dummy to keep compiler happy.
1688                  Verbose := False;
1689               end if;
1690            else
1691               Disp_Declaration_Object (S.Instance, S.Decl);
1692            end if;
1693         end;
1694      end loop;
1695   end Info_Signals_Proc;
1696
1697   type Handle_Scope_Type is access procedure (N : Iir);
1698
1699   procedure Foreach_Scopes (N : Iir; Handler : Handle_Scope_Type) is
1700   begin
1701      case Get_Kind (N) is
1702         when Iir_Kind_Process_Statement
1703           | Iir_Kind_Sensitized_Process_Statement =>
1704            Foreach_Scopes (Get_Parent (N), Handler);
1705            Handler.all (N);
1706         when Iir_Kind_Architecture_Body =>
1707            Foreach_Scopes (Get_Entity (N), Handler);
1708            Handler.all (N);
1709
1710         when Iir_Kind_Entity_Declaration =>
1711            --  Top of scopes.
1712            Handler.all (N);
1713
1714         when Iir_Kind_Function_Body
1715           | Iir_Kind_Procedure_Body =>
1716            Foreach_Scopes (Get_Parent (N), Handler);
1717            Handler.all (N);
1718         when Iir_Kind_Package_Body =>
1719            Handler.all (N);
1720
1721         when Iir_Kind_Variable_Assignment_Statement
1722           | Iir_Kind_Simple_Signal_Assignment_Statement
1723           | Iir_Kind_Null_Statement
1724           | Iir_Kind_Assertion_Statement
1725           | Iir_Kind_Report_Statement
1726           | Iir_Kind_Wait_Statement
1727           | Iir_Kind_Return_Statement
1728           | Iir_Kind_Next_Statement
1729           | Iir_Kind_Exit_Statement
1730           | Iir_Kind_Procedure_Call_Statement
1731           | Iir_Kind_If_Statement
1732           | Iir_Kind_While_Loop_Statement
1733           | Iir_Kind_Case_Statement =>
1734            Foreach_Scopes (Get_Parent (N), Handler);
1735
1736         when Iir_Kind_For_Loop_Statement
1737           | Iir_Kind_Block_Statement
1738           | Iir_Kind_If_Generate_Statement
1739           | Iir_Kind_For_Generate_Statement
1740           | Iir_Kind_Generate_Statement_Body =>
1741            Foreach_Scopes (Get_Parent (N), Handler);
1742            Handler.all (N);
1743
1744         when others =>
1745            Error_Kind ("foreach_scopes", N);
1746      end case;
1747   end Foreach_Scopes;
1748
1749   procedure Add_Decls_For (N : Iir)
1750   is
1751      use Vhdl.Sem_Scopes;
1752   begin
1753      case Get_Kind (N) is
1754         when Iir_Kind_Entity_Declaration =>
1755            declare
1756               Unit : constant Iir := Get_Design_Unit (N);
1757            begin
1758               Add_Context_Clauses (Unit);
1759               --  Add_Name (Unit, Get_Identifier (N), False);
1760               Add_Entity_Declarations (N);
1761            end;
1762         when Iir_Kind_Architecture_Body =>
1763            Open_Declarative_Region;
1764            Add_Context_Clauses (Get_Design_Unit (N));
1765            Add_Declarations (Get_Declaration_Chain (N), False);
1766            Add_Declarations_Of_Concurrent_Statement (N);
1767         when Iir_Kind_Package_Body =>
1768            declare
1769               Package_Decl : constant Iir := Get_Package (N);
1770               Package_Unit : constant Iir := Get_Design_Unit (Package_Decl);
1771            begin
1772               Add_Name (Package_Unit);
1773               Add_Context_Clauses (Package_Unit);
1774               Open_Declarative_Region;
1775               Add_Declarations (Get_Declaration_Chain (Package_Decl), False);
1776               Add_Declarations (Get_Declaration_Chain (N), False);
1777            end;
1778         when Iir_Kind_Procedure_Body
1779           | Iir_Kind_Function_Body =>
1780            declare
1781               Spec : constant Iir := Get_Subprogram_Specification (N);
1782            begin
1783               Open_Declarative_Region;
1784               Add_Declarations
1785                 (Get_Interface_Declaration_Chain (Spec), False);
1786               Add_Declarations
1787                 (Get_Declaration_Chain (N), False);
1788            end;
1789         when Iir_Kind_Process_Statement
1790           | Iir_Kind_Sensitized_Process_Statement =>
1791            Open_Declarative_Region;
1792            Add_Declarations (Get_Declaration_Chain (N), False);
1793         when Iir_Kind_For_Loop_Statement
1794           | Iir_Kind_For_Generate_Statement =>
1795            Open_Declarative_Region;
1796            Add_Name (Get_Parameter_Specification (N));
1797         when Iir_Kind_Block_Statement =>
1798            declare
1799               Header : constant Iir := Get_Block_Header (N);
1800            begin
1801               Open_Declarative_Region;
1802               if Header /= Null_Iir then
1803                  Add_Declarations (Get_Generic_Chain (Header), False);
1804                  Add_Declarations (Get_Port_Chain (Header), False);
1805               end if;
1806               Add_Declarations (Get_Declaration_Chain (N), False);
1807               Add_Declarations_Of_Concurrent_Statement (N);
1808            end;
1809         when Iir_Kind_Generate_Statement_Body =>
1810            Open_Declarative_Region;
1811            Add_Declarations (Get_Declaration_Chain (N), False);
1812            Add_Declarations_Of_Concurrent_Statement (N);
1813         when others =>
1814            Error_Kind ("enter_scope(2)", N);
1815      end case;
1816   end Add_Decls_For;
1817
1818   procedure Enter_Scope (Node : Iir)
1819   is
1820      use Vhdl.Sem_Scopes;
1821   begin
1822      Push_Interpretations;
1823      Open_Declarative_Region;
1824
1825      --  Add STD
1826      Add_Name (Libraries.Std_Library, Std_Names.Name_Std, False);
1827      Use_All_Names (Vhdl.Std_Package.Standard_Package);
1828
1829      Foreach_Scopes (Node, Add_Decls_For'Access);
1830   end Enter_Scope;
1831
1832   procedure Del_Decls_For (N : Iir)
1833   is
1834      use Vhdl.Sem_Scopes;
1835   begin
1836      case Get_Kind (N) is
1837         when Iir_Kind_Entity_Declaration =>
1838            null;
1839         when Iir_Kind_Architecture_Body =>
1840            Close_Declarative_Region;
1841         when Iir_Kind_Process_Statement
1842           | Iir_Kind_Sensitized_Process_Statement
1843           | Iir_Kind_Package_Body
1844           | Iir_Kind_Procedure_Body
1845           | Iir_Kind_Function_Body
1846           | Iir_Kind_For_Loop_Statement
1847           | Iir_Kind_Block_Statement
1848           | Iir_Kind_If_Generate_Statement
1849           | Iir_Kind_For_Generate_Statement
1850           | Iir_Kind_Generate_Statement_Body =>
1851            Close_Declarative_Region;
1852         when others =>
1853            Error_Kind ("Decl_Decls_For", N);
1854      end case;
1855   end Del_Decls_For;
1856
1857   procedure Leave_Scope (Node : Iir)
1858   is
1859      use Vhdl.Sem_Scopes;
1860   begin
1861      Foreach_Scopes (Node, Del_Decls_For'Access);
1862
1863      Close_Declarative_Region;
1864      Pop_Interpretations;
1865   end Leave_Scope;
1866
1867   Buffer_Index : Natural := 1;
1868
1869   procedure Print_Proc (Line : String)
1870   is
1871      use Vhdl.Tokens;
1872      Index_Str : String := Natural'Image (Buffer_Index);
1873      File : Source_File_Entry;
1874      Expr : Iir;
1875      Res : Iir_Value_Literal_Acc;
1876      P : Natural;
1877      Opt_Value : Boolean := False;
1878      Opt_Name : Boolean := False;
1879      Marker : Mark_Type;
1880   begin
1881      --  Decode options: /v
1882      P := Line'First;
1883      loop
1884         P := Skip_Blanks (Line (P .. Line'Last));
1885         if P + 2 < Line'Last and then Line (P .. P + 1) = "/v" then
1886            Opt_Value := True;
1887            P := P + 2;
1888         elsif P + 2 < Line'Last and then Line (P .. P + 1) = "/n" then
1889            Opt_Name := True;
1890            P := P + 2;
1891         else
1892            exit;
1893         end if;
1894      end loop;
1895
1896      Buffer_Index := Buffer_Index + 1;
1897      Index_Str (Index_Str'First) := '*';
1898      File := Files_Map.Create_Source_File_From_String
1899        (Name_Table.Get_Identifier ("*debug" & Index_Str & '*'),
1900         Line (P .. Line'Last));
1901      Vhdl.Scanner.Set_File (File);
1902      Vhdl.Scanner.Scan;
1903      Expr := Vhdl.Parse.Parse_Expression;
1904      if Vhdl.Scanner.Current_Token /= Tok_Eof then
1905         Put_Line ("garbage at end of expression ignored");
1906      end if;
1907      Vhdl.Scanner.Close_File;
1908      if Nbr_Errors /= 0 then
1909         Put_Line ("error while parsing expression, evaluation aborted");
1910         Nbr_Errors := 0;
1911         return;
1912      end if;
1913
1914      Enter_Scope (Dbg_Cur_Frame.Stmt);
1915      Expr := Vhdl.Sem_Expr.Sem_Expression_Universal (Expr);
1916      Leave_Scope (Dbg_Cur_Frame.Stmt);
1917
1918      if Expr = Null_Iir
1919        or else Nbr_Errors /= 0
1920      then
1921         Put_Line ("error while analyzing expression, evaluation aborted");
1922         Nbr_Errors := 0;
1923         return;
1924      end if;
1925
1926      Vhdl.Prints.Disp_Expression (Expr);
1927      New_Line;
1928
1929      Annotate_Expand_Table;
1930      Vhdl.Canon.Canon_Expression (Expr);
1931
1932      Mark (Marker, Expr_Pool);
1933
1934      if Opt_Name then
1935         case Get_Kind (Expr) is
1936            when Iir_Kind_Simple_Name =>
1937               null;
1938            when others =>
1939               Put_Line ("expression is not a name");
1940               Opt_Name := False;
1941         end case;
1942      end if;
1943      if Opt_Name then
1944         Res := Execute_Name (Dbg_Cur_Frame, Expr, True);
1945      else
1946         Res := Execute_Expression (Dbg_Cur_Frame, Expr);
1947      end if;
1948      if Opt_Value then
1949         Disp_Value (Res);
1950      else
1951         Disp_Iir_Value (Res, Get_Type (Expr));
1952      end if;
1953      New_Line;
1954
1955      --  Free value
1956      Release (Marker, Expr_Pool);
1957   end Print_Proc;
1958
1959   procedure Quit_Proc (Line : String) is
1960      pragma Unreferenced (Line);
1961   begin
1962      Command_Status := Status_Quit;
1963      raise Debugger_Quit;
1964   end Quit_Proc;
1965
1966   procedure Prepare_Continue is
1967   begin
1968      Command_Status := Status_Quit;
1969
1970      --  Set Flag_Need_Debug only if there is at least one enabled breakpoint.
1971      Flag_Need_Debug := False;
1972      for I in Breakpoints.First .. Breakpoints.Last loop
1973         Flag_Need_Debug := True;
1974         exit;
1975      end loop;
1976   end Prepare_Continue;
1977
1978   procedure Run_Proc (Line : String)
1979   is
1980      Delta_Time : Std_Time;
1981      P : Positive;
1982   begin
1983      P := Skip_Blanks (Line);
1984      if P <= Line'Last then
1985         Delta_Time := Grt.Options.Parse_Time (Line (P .. Line'Last));
1986         if Delta_Time = -1 then
1987            return;
1988         end if;
1989         Break_Time := Grt.Processes.Next_Time + Delta_Time;
1990      end if;
1991
1992      Prepare_Continue;
1993   end Run_Proc;
1994
1995   procedure Cont_Proc (Line : String) is
1996      pragma Unreferenced (Line);
1997   begin
1998      Prepare_Continue;
1999   end Cont_Proc;
2000
2001   Menu_Info_Instances : aliased Menu_Entry :=
2002     (Kind => Menu_Command,
2003      Name => new String'("instances"),
2004      Next => null,
2005      Proc => Info_Instances_Proc'Access);
2006
2007   Menu_Info_Psl : aliased Menu_Entry :=
2008     (Kind => Menu_Command,
2009      Name => new String'("psl"),
2010      Next => Menu_Info_Instances'Access,
2011      Proc => Info_PSL_Proc'Access);
2012
2013   Menu_Info_Stats : aliased Menu_Entry :=
2014     (Kind => Menu_Command,
2015      Name => new String'("stats"),
2016      Next => Menu_Info_Psl'Access,
2017      Proc => Info_Stats_Proc'Access);
2018
2019   Menu_Info_Tree : aliased Menu_Entry :=
2020     (Kind => Menu_Command,
2021      Name => new String'("tree"),
2022      Next => Menu_Info_Stats'Access,
2023      Proc => Info_Tree_Proc'Access);
2024
2025   Menu_Info_Params : aliased Menu_Entry :=
2026     (Kind => Menu_Command,
2027      Name => new String'("param*eters"),
2028      Next => Menu_Info_Tree'Access,
2029      Proc => Info_Params_Proc'Access);
2030
2031   Menu_Info_Subprograms : aliased Menu_Entry :=
2032     (Kind => Menu_Command,
2033      Name => new String'("subp*rograms"),
2034      Next => Menu_Info_Params'Access,
2035      Proc => Info_Subprograms_Proc'Access);
2036
2037   Menu_Info_Units : aliased Menu_Entry :=
2038     (Kind => Menu_Command,
2039      Name => new String'("units"),
2040      Next => Menu_Info_Subprograms'Access,
2041      Proc => Info_Units_Proc'Access);
2042
2043   Menu_Info_Files : aliased Menu_Entry :=
2044     (Kind => Menu_Command,
2045      Name => new String'("files"),
2046      Next => Menu_Info_Units'Access,
2047      Proc => Info_Files_Proc'Access);
2048
2049   Menu_Info_Libraries : aliased Menu_Entry :=
2050     (Kind => Menu_Command,
2051      Name => new String'("lib*raries"),
2052      Next => Menu_Info_Files'Access,
2053      Proc => Info_Libraries_Proc'Access);
2054
2055   Menu_Info_Signals : aliased Menu_Entry :=
2056     (Kind => Menu_Command,
2057      Name => new String'("sig*nals"),
2058      Next => Menu_Info_Libraries'Access,
2059      Proc => Info_Signals_Proc'Access);
2060
2061   Menu_Info_Proc : aliased Menu_Entry :=
2062     (Kind => Menu_Command,
2063      Name => new String'("proc*esses"),
2064      Next => Menu_Info_Signals'Access,
2065      Proc => Info_Proc_Proc'Access);
2066
2067   Menu_List : aliased Menu_Entry :=
2068     (Kind => Menu_Command,
2069      Name => new String'("l*list"),
2070      Next => null,
2071      Proc => List_Proc'Access);
2072
2073   Menu_Down : aliased Menu_Entry :=
2074     (Kind => Menu_Command,
2075      Name => new String'("down"),
2076      Next => Menu_List'Access,
2077      Proc => Down_Proc'Access);
2078
2079   Menu_Up : aliased Menu_Entry :=
2080     (Kind => Menu_Command,
2081      Name => new String'("up"),
2082      Next => Menu_Down'Access,
2083      Proc => Up_Proc'Access);
2084
2085   Menu_Nstmt : aliased Menu_Entry :=
2086     (Kind => Menu_Command,
2087      Name => new String'("ns*tmt"),
2088      Next => Menu_Up'Access,
2089      Proc => Next_Stmt_Proc'Access);
2090
2091   Menu_Fstmt : aliased Menu_Entry :=
2092     (Kind => Menu_Command,
2093      Name => new String'("fs*tmt"),
2094      Next => Menu_Nstmt'Access,
2095      Proc => Finish_Stmt_Proc'Access);
2096
2097   Menu_Next : aliased Menu_Entry :=
2098     (Kind => Menu_Command,
2099      Name => new String'("n*ext"),
2100      Next => Menu_Fstmt'Access,
2101      Proc => Next_Proc'Access);
2102
2103   Menu_Step : aliased Menu_Entry :=
2104     (Kind => Menu_Command,
2105      Name => new String'("s*tep"),
2106      Next => Menu_Next'Access,
2107      Proc => Step_Proc'Access);
2108
2109   Menu_Break : aliased Menu_Entry :=
2110     (Kind => Menu_Command,
2111      Name => new String'("b*reak"),
2112      Next => Menu_Step'Access,
2113      Proc => Break_Proc'Access);
2114
2115   Menu_Where : aliased Menu_Entry :=
2116     (Kind => Menu_Command,
2117      Name => new String'("where"),
2118      Next => Menu_Break'Access,
2119      Proc => Where_Proc'Access);
2120
2121   Menu_Ps : aliased Menu_Entry :=
2122     (Kind => Menu_Command,
2123      Name => new String'("ps"),
2124      Next => Menu_Where'Access,
2125      Proc => Ps_Proc'Access);
2126
2127   Menu_Info : aliased Menu_Entry :=
2128     (Kind => Menu_Submenu,
2129      Name => new String'("i*nfo"),
2130      Next => Menu_Ps'Access,
2131      First | Last => Menu_Info_Proc'Access);
2132
2133   Menu_Print : aliased Menu_Entry :=
2134     (Kind => Menu_Command,
2135      Name => new String'("pr*int"),
2136      Next => Menu_Info'Access,
2137      Proc => Print_Proc'Access);
2138
2139   Menu_Cont : aliased Menu_Entry :=
2140     (Kind => Menu_Command,
2141      Name => new String'("c*ont"),
2142      Next => Menu_Print'Access,
2143      Proc => Cont_Proc'Access);
2144
2145   Menu_Run : aliased Menu_Entry :=
2146     (Kind => Menu_Command,
2147      Name => new String'("r*un"),
2148      Next => Menu_Cont'Access,
2149      Proc => Run_Proc'Access);
2150
2151   Menu_Quit : aliased Menu_Entry :=
2152     (Kind => Menu_Command,
2153      Name => new String'("q*uit"),
2154      Next => Menu_Run'Access,
2155      Proc => Quit_Proc'Access);
2156
2157   Menu_Help1 : aliased Menu_Entry :=
2158     (Kind => Menu_Command,
2159      Name => new String'("help"),
2160      Next => Menu_Quit'Access,
2161      Proc => Help_Proc'Access);
2162
2163   Menu_Help2 : aliased Menu_Entry :=
2164     (Kind => Menu_Command,
2165      Name => new String'("?"),
2166      Next => Menu_Help1'Access,
2167      Proc => Help_Proc'Access);
2168
2169   Menu_Top : aliased Menu_Entry :=
2170     (Kind => Menu_Submenu,
2171      Name => null,
2172      Next => null,
2173      First | Last => Menu_Help2'Access);
2174
2175   function Find_Menu (Menu : Menu_Entry_Acc; Cmd : String)
2176                      return Menu_Entry_Acc
2177   is
2178      function Is_Cmd (Cmd_Name : String; Str : String) return Boolean
2179      is
2180         -- Number of characters that were compared.
2181         P : Natural;
2182      begin
2183         P := 0;
2184         --  Prefix (before the '*').
2185         loop
2186            if P = Cmd_Name'Length then
2187               --  Full match.
2188               return P = Str'Length;
2189            end if;
2190            exit when Cmd_Name (Cmd_Name'First + P) = '*';
2191            if P = Str'Length then
2192               --  Command is too short
2193               return False;
2194            end if;
2195            if Cmd_Name (Cmd_Name'First + P) /= Str (Str'First + P) then
2196               return False;
2197            end if;
2198            P := P + 1;
2199         end loop;
2200         --  Suffix (after the '*')
2201         loop
2202            if P = Str'Length then
2203               return True;
2204            end if;
2205            if P + 1 = Cmd_Name'Length then
2206               --  String is too long
2207               return False;
2208            end if;
2209            if Cmd_Name (Cmd_Name'First + P + 1) /= Str (Str'First + P) then
2210               return False;
2211            end if;
2212            P := P + 1;
2213         end loop;
2214      end Is_Cmd;
2215      Ent : Menu_Entry_Acc;
2216   begin
2217      Ent := Menu.First;
2218      while Ent /= null loop
2219         if Is_Cmd (Ent.Name.all, Cmd) then
2220            return Ent;
2221         end if;
2222         Ent := Ent.Next;
2223      end loop;
2224      return null;
2225   end Find_Menu;
2226
2227   procedure Parse_Command (Line : String;
2228                            P : in out Natural;
2229                            Menu : out Menu_Entry_Acc)
2230   is
2231      E : Natural;
2232   begin
2233      P := Skip_Blanks (Line (P .. Line'Last));
2234      if P > Line'Last then
2235         return;
2236      end if;
2237      E := Get_Word (Line (P .. Line'Last));
2238      Menu := Find_Menu (Menu, Line (P .. E));
2239      if Menu = null then
2240         Put_Line ("command '" & Line (P .. E) & "' not found");
2241      end if;
2242      P := E + 1;
2243   end Parse_Command;
2244
2245   procedure Help_Proc (Line : String)
2246   is
2247      P : Natural;
2248      Root : Menu_Entry_Acc := Menu_Top'access;
2249   begin
2250      Put_Line ("This is the help command");
2251      P := Line'First;
2252      while P < Line'Last loop
2253         Parse_Command (Line, P, Root);
2254         if Root = null then
2255            return;
2256         elsif Root.Kind /= Menu_Submenu then
2257            Put_Line ("Menu entry " & Root.Name.all & " is not a submenu");
2258            return;
2259         end if;
2260      end loop;
2261
2262      Root := Root.First;
2263      while Root /= null loop
2264         Put (Root.Name.all);
2265         if Root.Kind = Menu_Submenu then
2266            Put (" (menu)");
2267         end if;
2268         New_Line;
2269         Root := Root.Next;
2270      end loop;
2271   end Help_Proc;
2272
2273   function Breakpoint_Hit return Natural
2274   is
2275      Stmt : constant Iir := Current_Process.Instance.Stmt;
2276   begin
2277      for I in Breakpoints.First .. Breakpoints.Last loop
2278         if Stmt = Breakpoints.Table (I).Stmt then
2279            return I;
2280         end if;
2281      end loop;
2282      return 0;
2283   end Breakpoint_Hit;
2284
2285   Prompt_Debug : constant String := "debug> " & ASCII.NUL;
2286   Prompt_Error : constant String := "error> " & ASCII.NUL;
2287   Prompt_Init  : constant String := "init> " & ASCII.NUL;
2288   Prompt_Elab  : constant String := "elab> " & ASCII.NUL;
2289
2290   procedure Debug (Reason: Debug_Reason)
2291   is
2292      use Grt.Readline;
2293      Raw_Line : Char_Ptr;
2294      Prompt : System.Address;
2295   begin
2296      --  Unless interractive, do not use the debugger.
2297      case Reason is
2298         when Reason_Internal_Debug =>
2299            null;
2300         when Reason_Assert
2301           | Reason_Error =>
2302            if not Flag_Debugger then
2303               return;
2304            end if;
2305         when Reason_Start
2306           | Reason_Elab =>
2307            if not Flag_Interractive then
2308               return;
2309            end if;
2310         when Reason_Break
2311           | Reason_Time =>
2312            null;
2313      end case;
2314
2315      Prompt := Prompt_Debug'Address;
2316
2317      case Reason is
2318         when Reason_Start =>
2319            Set_Top_Frame (null);
2320            Prompt := Prompt_Init'Address;
2321         when Reason_Elab =>
2322            Set_Top_Frame (null);
2323            Prompt := Prompt_Elab'Address;
2324         when Reason_Internal_Debug =>
2325            if Current_Process = null then
2326               Set_Top_Frame (null);
2327            else
2328               Set_Top_Frame (Current_Process.Instance);
2329            end if;
2330         when Reason_Time =>
2331            Break_Time := Grt.Types.Std_Time'Last;
2332            Exec_State := Exec_Run;
2333         when Reason_Break =>
2334            case Exec_State is
2335               when Exec_Run =>
2336                  if Breakpoint_Hit /= 0 then
2337                     Put_Line ("breakpoint hit");
2338                  else
2339                     return;
2340                  end if;
2341               when Exec_Single_Step =>
2342                  null;
2343               when Exec_Next =>
2344                  if Current_Process.Instance /= Exec_Instance then
2345                     return;
2346                  end if;
2347               when Exec_Next_Stmt =>
2348                  if Current_Process.Instance /= Exec_Instance
2349                    or else Is_Within_Statement (Exec_Statement,
2350                                                 Current_Process.Instance.Stmt)
2351                  then
2352                     return;
2353                  end if;
2354            end case;
2355            --  Default state.
2356            Exec_State := Exec_Run;
2357            Set_Top_Frame (Current_Process.Instance);
2358            declare
2359               Stmt : constant Iir := Dbg_Cur_Frame.Stmt;
2360            begin
2361               Put ("stopped at: ");
2362               Disp_Iir_Location (Stmt);
2363               New_Line;
2364               Disp_Source_Line (Get_Location (Stmt));
2365            end;
2366         when Reason_Assert =>
2367            Set_Top_Frame (Current_Process.Instance);
2368            Prompt := Prompt_Error'Address;
2369            Put_Line ("assertion failure, enterring in debugger");
2370         when Reason_Error =>
2371            Set_Top_Frame (Current_Process.Instance);
2372            Prompt := Prompt_Error'Address;
2373            Put_Line ("error occurred, enterring in debugger");
2374      end case;
2375
2376      if Dbg_Cur_Frame /= null then
2377         Set_List_Current (Get_Location (Dbg_Cur_Frame.Stmt));
2378      end if;
2379
2380      Command_Status := Status_Default;
2381
2382      loop
2383         loop
2384            Raw_Line := Readline (Prompt);
2385            --  Skip empty lines
2386            if Raw_Line = null or else Raw_Line (1) = ASCII.NUL then
2387               if Cmd_Repeat /= null then
2388                  Cmd_Repeat.all ("");
2389                  case Command_Status is
2390                     when Status_Default =>
2391                        null;
2392                     when Status_Quit =>
2393                        return;
2394                  end case;
2395               end if;
2396            else
2397               Cmd_Repeat := null;
2398               exit;
2399            end if;
2400         end loop;
2401         declare
2402            Line_Last : constant Natural := Strlen (Raw_Line);
2403            Line : String renames Raw_Line (1 .. Line_Last);
2404            P, E : Positive;
2405            Cmd : Menu_Entry_Acc := Menu_Top'Access;
2406         begin
2407            --  Find command
2408            P := 1;
2409            loop
2410               E := P;
2411               Parse_Command (Line, E, Cmd);
2412               exit when Cmd = null;
2413               case Cmd.Kind is
2414                  when Menu_Submenu =>
2415                     if E > Line_Last then
2416                        Put_Line ("missing command for submenu "
2417                                    & Line (P .. E - 1));
2418                        Cmd := null;
2419                        exit;
2420                     end if;
2421                     P := E;
2422                  when Menu_Command =>
2423                     exit;
2424               end case;
2425            end loop;
2426
2427            if Cmd /= null then
2428               Cmd.Proc.all (Line (E .. Line_Last));
2429
2430               case Command_Status is
2431                  when Status_Default =>
2432                     null;
2433                  when Status_Quit =>
2434                     exit;
2435               end case;
2436            end if;
2437         exception
2438            when Command_Error =>
2439               null;
2440         end;
2441      end loop;
2442      --  Put ("resuming");
2443   end Debug;
2444
2445   procedure Debug_Error is
2446   begin
2447      Debug (Reason_Error);
2448   end Debug_Error;
2449end Simul.Debugger;
2450