Package: ghdl
Version: 0.29+gcc4.3.4+dfsg-1
Severity: normal

--- Please enter the report below this line. ---

The following patch add support for selecting which signals are to be dumped
during a vcd simulation.

Here is an exemple of how to use it :
ghdl -r test_bench --vcd=a.vcd --vcd-dumpvars=dumpvars.txt

dumpvars.txt is the file containing a list of the signals to be dumped.
Here is an example :

# Comments begin by '#'

# The signal sig_s from the top level (test bench) will be dumped
sig_s # A comment can also be put here

# The signal sig2_s from the top level will be dumped too
/sig2_s # This syntax is also valid

# Signal a_s from component "comp" will be dumped
# "comp" is the label written at the corresponding port map in the top level
/comp/a_s # could also be written "comp/a_s"

# Signal b_s from component "comp2" will be dumped
# "comp2" is the label written at the corresponding port map in the architecture
# of the component "comp"
/comp/comp2/b_s

/comp/*_i # All signals which name end by _i will be dumped
                # The "*" can be used to match any sub-string. The sub-string 
length
                # can also be 0

/comp/a*_* # The "*" can be used several times

/comp*/c_s # Invalid syntax : the "*" cannot be used for a component
name



--- System information. ---
Architecture: i386
Kernel:       Linux 2.6.32-5-686

Debian Release: squeeze/sid
  700 testing         ftp.ch.debian.org 
  600 unstable        ftp.ch.debian.org 
    1 experimental    ftp.ch.debian.org 

--- Package information. ---
Depends             (Version) | Installed
=============================-+-=============
libc6                (>= 2.7) | 2.11.1-3
libgcc1          (>= 1:4.1.1) | 1:4.4.4-4
libgmp3c2                     | 2:4.3.2+dfsg-1
libgnat-4.4      (>= 4.4.3-1) | 4.4.4-4
libmpfr1ldbl                  | 2.4.2-3
gnat-4.4                      | 4.4.4-4
zlib1g-dev                    | 1:1.2.3.4.dfsg-3


Recommends      (Version) | Installed
=========================-+-===========
gtkwave                   | 3.3.6-1


Package's Suggests field is empty.
diff -rupN ghdl/vhdl/grt/grt-vcd.adb ghdl_nouveau//vhdl/grt/grt-vcd.adb
--- ghdl/vhdl/grt/grt-vcd.adb	2010-01-25 00:04:30.000000000 +0100
+++ ghdl_nouveau//vhdl/grt/grt-vcd.adb	2010-06-13 15:12:58.992644330 +0200
@@ -38,6 +38,14 @@ package body Grt.Vcd is
 
    Stream : FILEs;
 
+   -- Used for selecting the signals to be displayed
+   procedure Vcd_Dump_Fill(Str_File : String_Access);
+   procedure Set_Dumped_State (Sig : VhpiHandleT;
+                               Vcd_El : in out Verilog_Wire_Info);
+   function Vcd_Dump_Move_To (Obj : VhpiHandleT) return Boolean;
+   function Str_Index (Str : in String; Str_Motif : in String) return Integer;
+   --
+
    procedure My_Vcd_Put (Str : String)
    is
       R : size_t;
@@ -73,7 +81,9 @@ package body Grt.Vcd is
       F : constant Natural := Opt'First;
       Mode : constant String := "wt" & NUL;
       Vcd_Filename : String_Access;
+      Vcd_Dumpvars_Filename : String_Access;
    begin
+      Vcd_Dump_Tree := Null;
       if Opt'Length < 5 or else Opt (F .. F + 4) /= "--vcd" then
          return False;
       end if;
@@ -81,6 +91,15 @@ package body Grt.Vcd is
          Flag_Vcd_Date := False;
          return True;
       end if;
+      if Opt'Length > 15 and then Opt(F + 5 .. F + 14) = "-dumpvars=" then
+         Vcd_Dump_Tree := new Vcd_Dump_Branch(Trunk);
+         Vcd_Dumpvars_Filename := new String (1 .. Opt'Length - 14);
+         Vcd_Dumpvars_Filename(1 .. Vcd_Dumpvars_Filename'Length-1) :=
+                                                            Opt(F+15..Opt'Last);
+         Vcd_Dumpvars_Filename(Vcd_Dumpvars_Filename'Last) := ASCII.NUL;
+         Vcd_Dump_Fill(Vcd_Dumpvars_Filename);
+         return True;
+      end if;
       if Opt'Length > 6 and then Opt (F + 5) = '=' then
          if Vcd_Close /= null then
             Error ("--vcd: file already set");
@@ -378,6 +397,11 @@ package body Grt.Vcd is
    begin
       Get_Verilog_Wire (Sig, Vcd_El);
 
+      Set_Dumped_State (Sig, Vcd_El);
+      if not Vcd_El.Is_Dumped then
+         return;
+      end if;
+
       if Vcd_El.Kind = Vcd_Bad then
          Vcd_Put ("$comment ");
          Vcd_Put_Name (Sig);
@@ -484,13 +508,19 @@ package body Grt.Vcd is
               | VhpiForGenerateK
               | VhpiBlockStmtK
               | VhpiCompInstStmtK =>
-               Vcd_Put ("$scope module ");
-               Vcd_Put_Name (Decl);
-               Vcd_Putc (' ');
-               Vcd_Put_End;
-               Vcd_Put_Hierarchy (Decl);
-               Vcd_Put ("$upscope ");
-               Vcd_Put_End;
+               if Vcd_Dump_Tree = Null or else Vcd_Dump_Move_To (Decl) then
+                  Vcd_Put ("$scope module ");
+                  Vcd_Put_Name (Decl);
+                  Vcd_Putc (' ');
+                  Vcd_Put_End;
+                  Vcd_Put_Hierarchy (Decl);
+                  Vcd_Put ("$upscope ");
+                  Vcd_Put_End;
+                  if Vcd_Dump_Tree /= Null then
+                     Vcd_Dump_Tree.Current_Branch :=
+                                            Vcd_Dump_Tree.Current_Branch.Parent;
+                  end if;
+               end if;
             when others =>
                null;
          end case;
@@ -548,6 +578,250 @@ package body Grt.Vcd is
       end loop;
    end Vcd_Put_Integer32;
 
+   procedure To_Lower (Str : in out String) is
+   begin
+      for i in Str'First..Str'Last loop
+         if Str(i) in 'A'..'Z' then
+            Str(i) := Character'Val(Character'Pos(Str(i))+32);
+         end if;
+      end loop;
+   end To_Lower;
+
+   function Str_Index (Str : in String; Str_Motif : in String) return Integer is
+      i, j : integer;
+   begin
+      i := Str'First;
+      j := i + Str_Motif'Length-1;
+      loop
+         if j > Str'Last then
+            return -1;
+         end if;
+         if Str(i..j) = Str_Motif then
+            return i;
+         end if;
+         i := i + 1;
+         j := j + 1;
+      end loop;
+   end Str_Index;
+
+   procedure Str_Error(Str_Line : String; Msg_Err : String) is
+   begin
+      Error_C ("Vcd dumpvars file at line '");
+      Error_C (Str_Line(Str_Line'First..Str_Line'Last));
+      Error_C ("' : ");
+      Error_E (Msg_Err);
+   end Str_Error;
+
+   procedure Vcd_Dump_Fill(Str_File : String_Access) is
+      Mode : constant String := "r" & NUL;
+      Stream_Vcd_Dump : FILEs;
+      Parent_Tmp, Branch_Tmp : Vcd_Dump_Branch_Access;
+      Sig_Tmp : Vcd_Dump_Leaf_Access;
+      Expr_Tmp, Expr_Prev : Sub_Expr_Access;
+      Index_Prev, Index_Tmp : Integer;
+      Str_Tmp : String_Access;
+      Line : String(1..1024);
+      Len : Natural;
+   begin
+      Stream_Vcd_Dump := fopen (Str_File.all'Address, Mode'Address);
+      if Stream_Vcd_Dump = NULL_Stream then
+         Error_C ("cannot open vcd dumpvars file '");
+         Error_C (Str_File.all);
+         Error_E ("'");
+         return;
+      end if;
+
+      while fgets(Line'Address, Line'Length, Stream_Vcd_Dump) /= Null_Address loop
+         Len := Str_Index(Line, ASCII.NUL & "");
+         To_Lower(Line(1..Len));
+         Index_Prev := 1;
+         While Character'Pos(Line(Index_Prev)) <= 32 loop -- LTrim
+            Index_Prev := Index_Prev + 1;
+         end loop;
+         -- Ignore comments and blank lines
+         if Len-Index_Prev >= 0 and Line(Index_Prev) /= '#' then
+            if Line(Index_Prev) = '/' then
+               Index_Prev := Index_Prev + 1;
+            end if;
+            Parent_Tmp := Vcd_Dump_Tree;
+            Index_Tmp := Str_Index (Line(Index_Prev..Len), "#");
+            if Index_Tmp >= 1 then
+               Len := Index_Tmp-1;
+            end if;
+            While Character'Pos(Line(Len)) <= 32 loop -- RTrim
+               Len := Len - 1;
+            end loop;
+            loop -- Loop to process the whole line
+               Index_Tmp := Str_Index (Line(Index_Prev..Len), "/") - 1;
+               exit when Index_Tmp < 1;
+               Branch_Tmp := Parent_Tmp.Niveau_Inf;
+               loop -- Seek if the component already exists in the same parent
+                  if Branch_Tmp = null then -- The component is new
+                     Str_Tmp := new String(1..(Index_Tmp-Index_Prev)+1);
+                     Str_Tmp.all := Line(Index_Prev..Index_Tmp);
+                     if Str_Tmp.all'Length = 0 then
+                        Str_Error (Line(1..Len), "A component name is missing");
+                     end if;
+                     if Str_Index (Str_Tmp.all, "*") >= 1 then
+                        Str_Error (Line(1..Len),
+                                  "Expressions not allowed in components name");
+                     end if;
+                     Branch_Tmp := new Vcd_Dump_Branch'(Kind => Branch,
+                                                        Name => Str_Tmp,
+                                                        Parent => Parent_Tmp,
+                                                        List_Signals => Null,
+                                                  Next => Parent_Tmp.Niveau_Inf,
+                                                        Niveau_Inf => Null);
+                     Parent_Tmp.Niveau_Inf := Branch_Tmp;
+                     Parent_Tmp := Branch_Tmp;
+                     exit;
+                  end if;
+                  -- If the component we are looking for already exists
+                  if Branch_Tmp.Name.all = Line(Index_Prev..Index_Tmp) then
+                     Parent_Tmp := Branch_Tmp; -- Move to it
+                     exit;
+                  end if;
+                  -- Move to the next child of the parent
+                  Branch_Tmp := Branch_Tmp.Next;
+               end loop;
+               Index_Prev := Index_Tmp + 2;
+            end loop;
+
+            Sig_Tmp := Parent_Tmp.List_Signals;
+            Str_Tmp := new String(1..(Len-Index_Prev)+1);
+            Str_Tmp.all := Line(Index_Prev..Len);
+            if Str_Tmp.all'Length = 0 then
+               Str_Error (Line(1..Len), "Signal name is missing");
+            end if;
+            while Sig_Tmp /= Null loop
+               if Sig_Tmp.Name.all = Str_Tmp.all then
+                  Str_Error (Line(1..Len), "Duplicate signal or expression");
+               end if;
+               Sig_Tmp := Sig_Tmp.Next;
+            end loop;
+
+            Index_Tmp := Str_Index (Line(Index_Prev..Len), "*")-1;
+            if Index_Tmp < 0 then -- New signal
+               Sig_Tmp := new Vcd_Dump_Leaf'(Kind => Signal,
+                                             Name => Str_Tmp,
+                                             Next => Parent_Tmp.List_Signals);
+            else -- New expression
+               Expr_Tmp := new Sub_Expr'(Sub_Str => Null, Next => Null);
+               Sig_Tmp := new Vcd_Dump_Leaf'(Kind => Expr_Signal,
+                                             Name => Str_Tmp,
+                                             Expr => Expr_Tmp,
+                                             Next => Parent_Tmp.List_Signals);
+               loop -- Generate all the sub-expressions of the expression
+                  Expr_Tmp.Sub_Str := New String(1..(Index_Tmp-Index_Prev)+1);
+                  Expr_Tmp.Sub_Str.all := Line(Index_Prev..Index_Tmp);
+                  Index_Prev := Index_Tmp + 2;
+                  Index_Tmp := Str_Index (Line(Index_Prev..Len), "*")-1;
+                  Expr_Prev := Expr_Tmp;
+                  Expr_Tmp := New Sub_Expr'(Sub_Str => Null, Next => Null);
+                  Expr_Prev.Next := Expr_Tmp;
+                  if Index_Tmp < 1 then -- Last sub-expression
+                     Expr_Tmp.Sub_Str := new String(1..(Len-Index_Prev)+1);
+                     Expr_Tmp.Sub_Str.all := Line(Index_Prev..Len);
+                     exit;
+                  end if;
+               end loop;
+            end if;
+            Parent_Tmp.List_Signals := Sig_Tmp;
+         end if;
+      end loop;
+
+      Vcd_Dump_Tree.Current_Branch := Vcd_Dump_Tree;
+      fclose (Stream_Vcd_Dump);
+      Stream_Vcd_Dump := NULL_Stream;
+   end Vcd_Dump_Fill;
+
+   procedure Set_Dumped_State (Sig : VhpiHandleT; Vcd_El :
+                               in out Verilog_Wire_Info)
+   is
+      Signal_Tmp : Vcd_Dump_Leaf_Access;
+      Sub_Expr_Tmp : Sub_Expr_Access;
+      Index_Tmp, Index_Prev : Integer;
+      Name_Len, Sub_Expr_Len : Integer;
+      Sig_Name : String(1..128);
+   begin
+      if Vcd_Dump_Tree = Null then
+         Vcd_El.Is_Dumped := True;
+         return;
+      end if;
+      Vhpi_Get_Str (VhpiNameP, Sig, Sig_Name, Name_Len);
+      Signal_Tmp := Vcd_Dump_Tree.Current_Branch.List_Signals;
+      while Signal_Tmp /= null loop
+
+         if Signal_Tmp.Kind = Signal then
+            if Sig_Name(1..Name_Len) = Signal_Tmp.Name.all then
+               Vcd_El.Is_Dumped := True;
+               return;
+            end if;
+         else
+            Sub_Expr_Tmp := Signal_Tmp.Expr;
+            Index_Tmp := 1;
+            loop -- Go through all sub-expressions of the expression
+               Sub_Expr_Len := Sub_Expr_Tmp.Sub_Str.all'Length;
+               -- (At least 2 sub-expressions exists,
+               --  even if the expression is "*")
+               if Sub_Expr_Tmp.Next = Null then -- Process the last sub-expression
+                  if Sub_Expr_Len >= 1 then
+                     Index_Prev := Index_Tmp;
+                     Index_Tmp := Name_Len-Sub_Expr_Len+1;
+                     if Index_Tmp < Index_Prev or else
+                              Sig_Name (Index_Tmp..Name_Len)
+                                                /= Sub_Expr_Tmp.Sub_Str.all then
+                        exit;
+                     end if;
+                  end if;
+                  Vcd_El.Is_Dumped := True;
+                  return;
+               end if;
+               Index_Tmp := Str_Index (Sig_Name (Index_Tmp..Name_Len),
+                                                   Sub_Expr_Tmp.Sub_Str.all);
+               if Index_Tmp < 1 then
+                  exit;
+               end if;
+               Index_Tmp := Index_Tmp + Sub_Expr_Len;
+               Sub_Expr_Tmp := Sub_Expr_Tmp.Next;
+            end loop;
+         end if;
+         Signal_Tmp := Signal_Tmp.Next;
+      end loop;
+      Vcd_El.Is_Dumped := False;
+   end Set_Dumped_State;
+
+   function Check_Dumped (I : Vcd_Index_Type) return Boolean
+   is
+      V : Verilog_Wire_Info renames Vcd_Table.Table (I);
+   begin
+      return V.Is_Dumped;
+   end Check_Dumped;
+
+   function Vcd_Dump_Move_To (Obj : VhpiHandleT) return Boolean
+   is
+      Comp_Name : String (1 .. 128);
+      Name_Len : Integer;
+      Branch_Tmp : Vcd_Dump_Branch_Access;
+   begin
+      Vhpi_Get_Str (VhpiNameP, Obj, Comp_Name, Name_Len);
+
+      Branch_Tmp := Vcd_Dump_Tree.Current_Branch.Niveau_Inf;
+
+      loop  -- Find if the component we are going to move to exists on the
+            -- tree of the dumped signals
+         if Branch_Tmp = null then -- It doesn't exist
+            return False;
+         end if;
+         if Branch_Tmp.Name.all = Comp_Name(1..Name_Len) then -- It exists
+            Vcd_Dump_Tree.Current_Branch := Branch_Tmp;
+            return True;
+         end if;
+         Branch_Tmp := Branch_Tmp.Next;
+      end loop;
+
+   end Vcd_Dump_Move_To;
+
    procedure Vcd_Put_Var (I : Vcd_Index_Type)
    is
       Addr : Address;
@@ -718,12 +992,16 @@ package body Grt.Vcd is
       if Cycle_Time = 0 then
          --  Disp all values.
          for I in Vcd_Table.First .. Vcd_Table.Last loop
-            Vcd_Put_Var (I);
+            if Check_Dumped(I) then
+               Vcd_Put_Var (I);
+            end if;
          end loop;
       else
          --  Disp only values changed.
          for I in Vcd_Table.First .. Vcd_Table.Last loop
-            if Verilog_Wire_Changed (Vcd_Table.Table (I), Cycle_Time) then
+            if Check_Dumped(I) and then
+               Verilog_Wire_Changed (Vcd_Table.Table (I), Cycle_Time)
+            then
                Vcd_Put_Var (I);
             end if;
          end loop;
diff -rupN ghdl/vhdl/grt/grt-vcd.ads ghdl_nouveau//vhdl/grt/grt-vcd.ads
--- ghdl/vhdl/grt/grt-vcd.ads	2010-01-25 00:04:30.000000000 +0100
+++ ghdl_nouveau//vhdl/grt/grt-vcd.ads	2010-06-13 13:14:23.013048000 +0200
@@ -43,7 +43,50 @@ package Grt.Vcd is
       Irange : Ghdl_Range_Ptr;
       Kind : Vcd_Var_Kind;
       Val : Vcd_Value_Kind;
+      Is_Dumped : Boolean;
    end record;
+   
+   Type Sub_Expr;
+   Type Sub_Expr_Access is Access Sub_Expr;
+   Type Sub_Expr is
+      record
+         Sub_Str : String_Access;
+         Next : Sub_Expr_Access;
+      end record;
+
+   Type Type_Elem_Leaf is (Signal, Expr_Signal);
+   type Vcd_Dump_Leaf;
+   Type Vcd_Dump_Leaf_Access is Access all Vcd_Dump_Leaf;
+   type Vcd_Dump_Leaf (Kind : Type_Elem_Leaf) is
+      record
+         Name : String_Access;
+         Next : Vcd_Dump_Leaf_Access;
+         case Kind is
+            when Signal =>
+               null;
+            when Expr_Signal =>
+               Expr : Sub_Expr_Access;
+         end case;
+      end record;
+
+   Type Type_Elem_Branch is (Trunk, Branch);
+   type Vcd_Dump_Branch;
+   Type Vcd_Dump_Branch_Access is Access all Vcd_Dump_Branch;
+   type Vcd_Dump_Branch (Kind : Type_Elem_Branch) is
+      record
+         Niveau_Inf : Vcd_Dump_Branch_Access;
+         List_Signals : Vcd_Dump_Leaf_Access;
+         case Kind is
+            when Trunk =>
+               Current_Branch : Vcd_Dump_Branch_Access;
+            when Branch =>
+               Name : String_Access;
+               Parent : Vcd_Dump_Branch_Access;
+               Next : Vcd_Dump_Branch_Access;
+         end case;
+      end record;
+      
+   Vcd_Dump_Tree : Vcd_Dump_Branch_Access;
 
    procedure Get_Verilog_Wire (Sig : VhpiHandleT;
                                Info : out Verilog_Wire_Info);

Reply via email to