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);