5
5
import enum as py_enum
6
6
7
7
from ..hdl import *
8
+ from ..hdl ._mem import MemoryInstance
8
9
from ..hdl ._ast import SignalDict
10
+ from ..lib import data , wiring
9
11
from ._base import *
10
12
from ._async import *
11
13
from ._pyeval import eval_format , eval_value , eval_assign
@@ -49,7 +51,7 @@ def __init__(self, state, design, *, vcd_file, gtkw_file=None, traces=(), fs_per
49
51
self .gtkw_file = gtkw_file
50
52
self .gtkw_save = gtkw_file and vcd .gtkw .GTKWSave (self .gtkw_file )
51
53
52
- self .traces = []
54
+ self .traces = traces
53
55
54
56
signal_names = SignalDict ()
55
57
memories = {}
@@ -64,9 +66,9 @@ def __init__(self, state, design, *, vcd_file, gtkw_file=None, traces=(), fs_per
64
66
65
67
trace_names = SignalDict ()
66
68
assigned_names = set ()
67
- for trace in traces :
68
- if isinstance (trace , ValueLike ):
69
- trace = Value .cast (trace )
69
+ def traverse_traces ( traces ) :
70
+ if isinstance (traces , ValueLike ):
71
+ trace = Value .cast (traces )
70
72
if isinstance (trace , MemoryData ._Row ):
71
73
memory = trace ._memory
72
74
if not memory in memories :
@@ -77,7 +79,6 @@ def __init__(self, state, design, *, vcd_file, gtkw_file=None, traces=(), fs_per
77
79
assert name not in assigned_names
78
80
memories [memory ] = ("bench" , name )
79
81
assigned_names .add (name )
80
- self .traces .append (trace )
81
82
else :
82
83
for trace_signal in trace ._rhs_signals ():
83
84
if trace_signal not in signal_names :
@@ -88,19 +89,27 @@ def __init__(self, state, design, *, vcd_file, gtkw_file=None, traces=(), fs_per
88
89
assert name not in assigned_names
89
90
trace_names [trace_signal ] = {("bench" , name )}
90
91
assigned_names .add (name )
91
- self .traces .append (trace_signal )
92
- elif isinstance (trace , MemoryData ):
93
- if not trace in memories :
94
- if trace .name not in assigned_names :
95
- name = trace .name
92
+ elif isinstance (traces , MemoryData ):
93
+ if not traces in memories :
94
+ if traces .name not in assigned_names :
95
+ name = traces .name
96
96
else :
97
- name = f"{ trace .name } ${ len (assigned_names )} "
97
+ name = f"{ traces .name } ${ len (assigned_names )} "
98
98
assert name not in assigned_names
99
- memories [trace ] = ("bench" , name )
99
+ memories [traces ] = ("bench" , name )
100
100
assigned_names .add (name )
101
- self .traces .append (trace )
101
+ elif hasattr (traces , "signature" ) and isinstance (traces .signature , wiring .Signature ):
102
+ for name in traces .signature .members :
103
+ traverse_traces (getattr (traces , name ))
104
+ elif isinstance (traces , list ) or isinstance (traces , tuple ):
105
+ for trace in traces :
106
+ traverse_traces (trace )
107
+ elif isinstance (traces , dict ):
108
+ for trace in traces .values ():
109
+ traverse_traces (trace )
102
110
else :
103
- raise TypeError (f"{ trace !r} is not a traceable object" )
111
+ raise TypeError (f"{ traces !r} is not a traceable object" )
112
+ traverse_traces (traces )
104
113
105
114
if self .vcd_writer is None :
106
115
return
@@ -277,19 +286,40 @@ def close(self, timestamp):
277
286
self .gtkw_save .dumpfile_size (self .vcd_file .tell ())
278
287
279
288
self .gtkw_save .treeopen ("top" )
280
- for trace in self .traces :
281
- if isinstance (trace , Signal ):
282
- for name in self .gtkw_signal_names [trace ]:
289
+
290
+ def traverse_traces (traces ):
291
+ if isinstance (traces , Signal ):
292
+ for name in self .gtkw_signal_names [traces ]:
283
293
self .gtkw_save .trace (name )
284
- elif isinstance (trace , MemoryData ):
285
- for row_names in self .gtkw_memory_names [trace ]:
294
+ elif isinstance (traces , data .View ):
295
+ with self .gtkw_save .group ("view" ):
296
+ trace = Value .cast (traces )
297
+ for trace_signal in trace ._rhs_signals ():
298
+ for name in self .gtkw_signal_names [trace_signal ]:
299
+ self .gtkw_save .trace (name )
300
+ elif isinstance (traces , ValueLike ):
301
+ traverse_traces (Value .cast (traces ))
302
+ elif isinstance (traces , MemoryData ):
303
+ for row_names in self .gtkw_memory_names [traces ]:
286
304
for name in row_names :
287
305
self .gtkw_save .trace (name )
288
- elif isinstance (trace , MemoryData ._Row ):
289
- for name in self .gtkw_memory_names [trace ._memory ][trace ._index ]:
306
+ elif isinstance (traces , MemoryData ._Row ):
307
+ for name in self .gtkw_memory_names [traces ._memory ][traces ._index ]:
290
308
self .gtkw_save .trace (name )
309
+ elif hasattr (traces , "signature" ) and isinstance (traces .signature , wiring .Signature ):
310
+ with self .gtkw_save .group ("interface" ):
311
+ for _ , _ , member in traces .signature .flatten (traces ):
312
+ traverse_traces (member )
313
+ elif isinstance (traces , list ) or isinstance (traces , tuple ):
314
+ for trace in traces :
315
+ traverse_traces (trace )
316
+ elif isinstance (traces , dict ):
317
+ for name , trace in traces .items ():
318
+ with self .gtkw_save .group (name ):
319
+ traverse_traces (trace )
291
320
else :
292
321
assert False # :nocov:
322
+ traverse_traces (self .traces )
293
323
294
324
if self .close_vcd :
295
325
self .vcd_file .close ()
0 commit comments