@@ -876,33 +876,46 @@ def tick_segment(self, n, symbol_len, segment_size):
876
876
num_tick = self ._tick + str (n )
877
877
return num_tick .ljust (symbol_len * segment_size )
878
878
879
- def render_val (self , w , n , current_val , symbol_len ):
879
+ def render_val (self , w , n , current_val , symbol_len , repr_func , repr_per_name ):
880
880
if w is not self .prev_wire :
881
881
self .prev_wire = w
882
882
self .prior_val = current_val
883
- out = self ._render_val_with_prev (w , n , current_val , symbol_len )
883
+ out = self ._render_val_with_prev (w , n , current_val , symbol_len , repr_func , repr_per_name )
884
884
self .prior_val = current_val
885
885
return out
886
886
887
- def _render_val_with_prev (self , w , n , current_val , symbol_len ):
887
+ def _render_val_with_prev (self , w , n , current_val , symbol_len , repr_func , repr_per_name ):
888
888
"""Return a string encoding the given value in a waveform.
889
889
890
890
:param w: The WireVector we are rendering to a waveform
891
891
:param n: An integer from 0 to segment_len-1
892
892
:param current_val: the value to be rendered
893
893
:param symbol_len: and integer for how big to draw the current value
894
+ :param repr_func: function to use for representing the current_val;
895
+ examples are 'hex', 'oct', 'bin', 'str' (for decimal), or even the name
896
+ of an IntEnum class you know the value will belong to. Defaults to 'hex'.
897
+ :param repr_per_name: Map from signal name to a function that takes in the signal's
898
+ value and returns a user-defined representation. If a signal name is
899
+ not found in the map, the argument `repr_func` will be used instead.
894
900
895
901
Returns a string of printed length symbol_len that will draw the
896
902
representation of current_val. The input prior_val is used to
897
903
render transitions.
898
904
"""
905
+ def to_str (v ):
906
+ f = repr_per_name .get (w .name )
907
+ if f is None :
908
+ return str (repr_func (v ))
909
+ else :
910
+ return str (f (v ))
911
+
899
912
sl = symbol_len - 1
900
913
if len (w ) > 1 :
901
914
out = self ._revstart
902
915
if current_val != self .prior_val :
903
- out += self ._x + hex (current_val ).rstrip ('L' ).ljust (sl )[:sl ]
916
+ out += self ._x + to_str (current_val ).rstrip ('L' ).ljust (sl )[:sl ]
904
917
elif n == 0 :
905
- out += hex (current_val ).rstrip ('L' ).ljust (symbol_len )[:symbol_len ]
918
+ out += to_str (current_val ).rstrip ('L' ).ljust (symbol_len )[:symbol_len ]
906
919
else :
907
920
out += ' ' * symbol_len
908
921
out += self ._revstop
@@ -1130,14 +1143,22 @@ def print_trace_strs(time):
1130
1143
1131
1144
def render_trace (
1132
1145
self , trace_list = None , file = sys .stdout , render_cls = default_renderer (),
1133
- symbol_len = 5 , segment_size = 5 , segment_delim = ' ' , extra_line = True ):
1146
+ symbol_len = 5 , repr_func = hex , repr_per_name = {}, segment_size = 5 ,
1147
+ segment_delim = ' ' , extra_line = True ):
1134
1148
1135
1149
""" Render the trace to a file using unicode and ASCII escape sequences.
1136
1150
1137
1151
:param trace_list: A list of signal names to be output in the specified order.
1138
1152
:param file: The place to write output, default to stdout.
1139
1153
:param render_cls: A class that translates traces into output bytes.
1140
1154
:param symbol_len: The "length" of each rendered cycle in characters.
1155
+ If None, the length will be automatically set such that the largest
1156
+ represented value fits.
1157
+ :param repr_func: Function to use for representing each value in the trace;
1158
+ examples are 'hex', 'oct', 'bin', and 'str' (for decimal). Defaults to 'hex'.
1159
+ :param repr_per_name: Map from signal name to a function that takes in the signal's
1160
+ value and returns a user-defined representation. If a signal name is
1161
+ not found in the map, the argument `repr_func` will be used instead.
1141
1162
:param segment_size: Traces are broken in the segments of this number of cycles.
1142
1163
:param segment_delim: The character to be output between segments.
1143
1164
:param extra_line: A Boolean to determine if we should print a blank line between signals.
@@ -1166,12 +1187,12 @@ def render_trace(
1166
1187
else :
1167
1188
self .render_trace_to_text (
1168
1189
trace_list = trace_list , file = file , render_cls = render_cls ,
1169
- symbol_len = symbol_len , segment_size = segment_size ,
1170
- segment_delim = segment_delim , extra_line = extra_line )
1190
+ symbol_len = symbol_len , repr_func = repr_func , repr_per_name = repr_per_name ,
1191
+ segment_size = segment_size , segment_delim = segment_delim , extra_line = extra_line )
1171
1192
1172
1193
def render_trace_to_text (
1173
1194
self , trace_list , file , render_cls ,
1174
- symbol_len , segment_size , segment_delim , extra_line ):
1195
+ symbol_len , repr_func , repr_per_name , segment_size , segment_delim , extra_line ):
1175
1196
1176
1197
renderer = render_cls ()
1177
1198
@@ -1185,7 +1206,9 @@ def formatted_trace_line(wire, trace):
1185
1206
self ._wires [wire ],
1186
1207
i % segment_size ,
1187
1208
trace [i ],
1188
- symbol_len )
1209
+ symbol_len ,
1210
+ repr_func ,
1211
+ repr_per_name )
1189
1212
return heading + trace_line
1190
1213
1191
1214
# default to printing all signals in sorted order
@@ -1204,6 +1227,20 @@ def formatted_trace_line(wire, trace):
1204
1227
"untraceable wires were removed prior to simulation, "
1205
1228
"if a CompiledSimulation was used." )
1206
1229
1230
+ if symbol_len is None :
1231
+
1232
+ def to_str (v , name ):
1233
+ f = repr_per_name .get (name )
1234
+ if f is None :
1235
+ return str (repr_func (v ))
1236
+ else :
1237
+ return str (f (v ))
1238
+
1239
+ maxvallen = 0
1240
+ for name , trace in self .trace .items ():
1241
+ maxvallen = max (maxvallen , max (len (to_str (v , name )) for v in trace ))
1242
+ symbol_len = maxvallen + 1
1243
+
1207
1244
# print the 'ruler' which is just a list of 'ticks'
1208
1245
# mapped by the pretty map
1209
1246
0 commit comments