Belle II Software development
VCDWriter Class Reference

Public Member Functions

def __init__ (self, file, timescale='1 us', date=None, comment='', version='', default_scope_type='module', scope_sep='.', check_values=True, init_timestamp=0)
 
def set_scope_type (self, scope, scope_type)
 
def register_var (self, scope, name, var_type, size=None, init=None, ident=None)
 
def dump_off (self, timestamp)
 
def dump_on (self, timestamp)
 
def change (self, var, timestamp, value)
 
def __enter__ (self)
 
def __exit__ (self, exc_type, exc_val, exc_tb)
 
def close (self, timestamp=None)
 
def flush (self, timestamp=None)
 

Static Public Attributes

list SCOPE_TYPES = ['begin', 'fork', 'function', 'module', 'task']
 Valid VCD scope types.
 
list VAR_TYPES
 Valid VCD variable types.
 
list TIMESCALE_NUMS = [1, 10, 100]
 Valid timescale numbers.
 
list TIMESCALE_UNITS = ['s', 'ms', 'us', 'ns', 'ps', 'fs']
 Valid timescale units.
 

Protected Member Functions

def _dump_off (self, timestamp)
 
def _dump_values (self, keyword)
 
def _get_scope_tuple (self, scope)
 
def _check_timescale (cls, timescale)
 
def _gen_header (self)
 
def _finalize_registration (self)
 

Protected Attributes

 _ofile
 output file
 
 _header_keywords
 header keywords
 
 _default_scope_type
 set default_scope_type
 
 _scope_sep
 set scope_sep
 
 _check_values
 set check_values
 
 _registering
 set registering
 
 _closed
 set closed
 
 _dumping
 set dumping
 
 _next_var_id
 set next_var_id
 
 _scope_var_strs
 set scope_var_strs
 
 _scope_var_names
 set scope_var_names
 
 _scope_types
 set scopr_types
 
 _ident_values
 set ident_values
 
 _timestamp
 set time_stamp
 

Detailed Description

Value Change Dump writer.

A VCD file captures time-ordered changes to the value of variables.

:param file file: A file-like object to write the VCD data.
:param timescale:
    Scale of the VCD timestamps. The timescale may either be a string or a
    tuple containing an (int, str) pair.
:type timescale: str, tuple
:param str date: Optional `$date` string used in the VCD header.
:param str comment: Optional `$comment` string used in the VCD header.
:param str version: Optional `$version` string used in the VCD header.
:param str default_scope_type: Scope type for scopes where
        :meth:`set_scope_type()` is not called explicitly.
:param str scope_sep: Separator for scopes specified as strings.
:param int init_timestamp: The initial timestamp. default=0
:raises ValueError: for invalid timescale values

Definition at line 44 of file writer.py.

Constructor & Destructor Documentation

◆ __init__()

def __init__ (   self,
  file,
  timescale = '1 us',
  date = None,
  comment = '',
  version = '',
  default_scope_type = 'module',
  scope_sep = '.',
  check_values = True,
  init_timestamp = 0 
)
Initialization of VCDWriter

Definition at line 79 of file writer.py.

81 check_values=True, init_timestamp=0):
82 """Initialization of VCDWriter"""
83
84 self._ofile = file
85
86 self._header_keywords = {
87 '$timescale': self._check_timescale(timescale),
88 '$date': str(datetime.datetime.now()) if date is None else date,
89 '$comment': comment,
90 '$version': version,
91 }
92 if default_scope_type not in self.SCOPE_TYPES:
93 raise ValueError(f'Invalid default scope type ({default_scope_type})')
94
95 self._default_scope_type = default_scope_type
96
97 self._scope_sep = scope_sep
98
99 self._check_values = check_values
100
101 self._registering = True
102
103 self._closed = False
104
105 self._dumping = True
106
107 self._next_var_id = 0
108
109 self._scope_var_strs = {}
110
111 self._scope_var_names = {}
112
113 self._scope_types = {}
114
115 self._ident_values = OrderedDict()
116
117 self._timestamp = int(init_timestamp)
118

Member Function Documentation

◆ __enter__()

def __enter__ (   self)
enter of VCDWriter

Definition at line 357 of file writer.py.

357 def __enter__(self):
358 """enter of VCDWriter"""
359 return self
360

◆ __exit__()

def __exit__ (   self,
  exc_type,
  exc_val,
  exc_tb 
)
exit of VCDWriter

Definition at line 361 of file writer.py.

361 def __exit__(self, exc_type, exc_val, exc_tb):
362 """exit of VCDWriter"""
363 self.close()
364

◆ _check_timescale()

def _check_timescale (   cls,
  timescale 
)
protected
check time scale function of the VCDWrite

Definition at line 325 of file writer.py.

325 def _check_timescale(cls, timescale):
326 """check time scale function of the VCDWrite"""
327 if isinstance(timescale, (list, tuple)):
328 if len(timescale) == 1:
329 num_str = '1'
330 unit = timescale[0]
331 elif len(timescale) == 2:
332 num, unit = timescale
333 if num not in cls.TIMESCALE_NUMS:
334 raise ValueError(f'Invalid timescale num {num}')
335 num_str = str(num)
336 else:
337 raise ValueError(f'Invalid timescale {timescale}')
338 elif isinstance(timescale, str):
339 if timescale in cls.TIMESCALE_UNITS:
340 num_str = '1'
341 unit = timescale
342 else:
343 for num in sorted(cls.TIMESCALE_NUMS, reverse=True):
344 num_str = str(num)
345 if timescale.startswith(num_str):
346 unit = timescale[len(num_str):].lstrip(' ')
347 break
348 else:
349 raise ValueError(
350 f'Invalid timescale num {timescale}')
351 else:
352 raise TypeError(f'Invalid timescale type {type(timescale).__name__}')
353 if unit not in cls.TIMESCALE_UNITS:
354 raise ValueError(f'Invalid timescale unit "{unit}"')
355 return ' '.join([num_str, unit])
356

◆ _dump_off()

def _dump_off (   self,
  timestamp 
)
protected
Stop dumping to VCD file.

Definition at line 238 of file writer.py.

238 def _dump_off(self, timestamp):
239 """Stop dumping to VCD file."""
240 print('#' + str(int(timestamp)), file=self._ofile)
241 print('$dumpoff', file=self._ofile)
242 for ident, val_str in self._ident_values.items():
243 if val_str[0] == 'b':
244 print('bx', ident, file=self._ofile)
245 elif val_str[0] == 'r':
246 pass # real variables cannot have 'z' or 'x' state
247 else:
248 print('x', ident, sep='', file=self._ofile)
249 print('$end', file=self._ofile)
250

◆ _dump_values()

def _dump_values (   self,
  keyword 
)
protected
Dump values to VCD file.

Definition at line 259 of file writer.py.

259 def _dump_values(self, keyword):
260 """Dump values to VCD file."""
261 print(keyword, file=self._ofile)
262 # TODO: events should be excluded
263 print(*self._ident_values.values(),
264 sep='\n', file=self._ofile)
265 print('$end', file=self._ofile)
266

◆ _finalize_registration()

def _finalize_registration (   self)
protected
finalize registration of VCDWriter

Definition at line 444 of file writer.py.

444 def _finalize_registration(self):
445 """finalize registration of VCDWriter"""
446 assert self._registering
447 print(*self._gen_header(), sep='\n', file=self._ofile)
448 if self._ident_values:
449 print('#' + str(int(self._timestamp)), file=self._ofile)
450 self._dump_values('$dumpvars')
451 if not self._dumping:
452 self._dump_off(self._timestamp)
453 self._registering = False
454
455 # This state is not needed after registration phase.
456 self._header_keywords.clear()
457 self._scope_types.clear()
458 self._scope_var_names.clear()
459
460

◆ _gen_header()

def _gen_header (   self)
protected
generate header for VCDWriter

Definition at line 404 of file writer.py.

404 def _gen_header(self):
405 """generate header for VCDWriter"""
406 for kwname, kwvalue in sorted(self._header_keywords.items()):
407 if not kwvalue:
408 continue
409 lines = kwvalue.split('\n')
410 if len(lines) == 1:
411 yield f'{kwname} {lines[0]} $end'
412 else:
413 yield kwname
414 for line in lines:
415 yield '\t' + line
416 yield '$end'
417
418 prev_scope = []
419 for scope in sorted(self._scope_var_strs):
420 var_strs = self._scope_var_strs.pop(scope)
421
422 for i, (prev, this) in enumerate(zip_longest(prev_scope, scope)):
423 if prev != this:
424 for _ in prev_scope[i:]:
425 yield '$upscope $end'
426
427 for j, name in enumerate(scope[i:]):
428 scope_type = self._scope_types.get(
429 scope[:i + j + 1], self._default_scope_type)
430 yield f'$scope {scope_type} {name} $end'
431 break
432 else:
433 assert scope != prev_scope # pragma no cover
434
435 yield from var_strs
436
437 prev_scope = scope
438
439 for _ in prev_scope:
440 yield '$upscope $end'
441
442 yield '$enddefinitions $end'
443

◆ _get_scope_tuple()

def _get_scope_tuple (   self,
  scope 
)
protected
get scope tuple function of the VCDWrite

Definition at line 315 of file writer.py.

315 def _get_scope_tuple(self, scope):
316 """get scope tuple function of the VCDWrite"""
317 if isinstance(scope, str):
318 return tuple(scope.split(self._scope_sep))
319 if isinstance(scope, (list, tuple)):
320 return tuple(scope)
321 else:
322 raise TypeError(f'Invalid scope {scope}')
323

◆ change()

def change (   self,
  var,
  timestamp,
  value 
)
Change variable's value in VCD stream.

This is the fundamental behavior of a :class:`VCDWriter` instance. Each
time a variable's value changes, this method should be called.

The *timestamp* must be in-order relative to timestamps from previous
calls to :meth:`change()`. It is okay to call :meth:`change()` multiple
times with the same *timestamp*, but never with a past *timestamp*.

.. Note::

    :meth:`change()` may be called multiple times before the timestamp
    progresses past 0. The last value change for each variable will go
    into the $dumpvars section.

:param Variable var: :class:`Variable` instance (i.e. from
                     :meth:`register_var()`).
:param int timestamp: Current simulation time.
:param value:
    New value for *var*. For :class:`VectorVariable`, if the variable's
    *size* is a tuple, then *value* must be a tuple of the same arity.

:raises ValueError: if the value is not valid for *var*.
:raises VCDPhaseError: if the timestamp is out of order or the
                       :class:`VCDWriter` instance is closed.

Definition at line 267 of file writer.py.

267 def change(self, var, timestamp, value):
268 """Change variable's value in VCD stream.
269
270 This is the fundamental behavior of a :class:`VCDWriter` instance. Each
271 time a variable's value changes, this method should be called.
272
273 The *timestamp* must be in-order relative to timestamps from previous
274 calls to :meth:`change()`. It is okay to call :meth:`change()` multiple
275 times with the same *timestamp*, but never with a past *timestamp*.
276
277 .. Note::
278
279 :meth:`change()` may be called multiple times before the timestamp
280 progresses past 0. The last value change for each variable will go
281 into the $dumpvars section.
282
283 :param Variable var: :class:`Variable` instance (i.e. from
284 :meth:`register_var()`).
285 :param int timestamp: Current simulation time.
286 :param value:
287 New value for *var*. For :class:`VectorVariable`, if the variable's
288 *size* is a tuple, then *value* must be a tuple of the same arity.
289
290 :raises ValueError: if the value is not valid for *var*.
291 :raises VCDPhaseError: if the timestamp is out of order or the
292 :class:`VCDWriter` instance is closed.
293
294 """
295 if timestamp < self._timestamp:
296 raise VCDPhaseError(f'Out of order value change ({var})')
297 elif self._closed:
298 raise VCDPhaseError('Cannot change value after close()')
299
300 val_str = var.format_value(value, self._check_values)
301 ts_int = int(timestamp)
302
303 if ts_int > self._timestamp:
304 if self._registering:
305 self._finalize_registration()
306 if self._dumping:
307 print('#', ts_int, sep='', file=self._ofile)
308 self._timestamp = ts_int
309
310 if self._dumping and not self._registering:
311 print(val_str, file=self._ofile)
312 else:
313 self._ident_values[var.ident] = val_str
314

◆ close()

def close (   self,
  timestamp = None 
)
Close VCD writer.

Any buffered VCD data is flushed to the output file. After
:meth:`close()`, no variable registration or value changes will be
accepted.

:param int timestamp: optional final timestamp to insert into VCD
                      stream.

.. Note::

    The output file is not automatically closed. It is up to the user
    to ensure the output file is closed after the :class:`VCDWriter`
    instance is closed.

Definition at line 365 of file writer.py.

365 def close(self, timestamp=None):
366 """Close VCD writer.
367
368 Any buffered VCD data is flushed to the output file. After
369 :meth:`close()`, no variable registration or value changes will be
370 accepted.
371
372 :param int timestamp: optional final timestamp to insert into VCD
373 stream.
374
375 .. Note::
376
377 The output file is not automatically closed. It is up to the user
378 to ensure the output file is closed after the :class:`VCDWriter`
379 instance is closed.
380
381 """
382 if not self._closed:
383 self.flush(timestamp)
384 self._closed = True
385

◆ dump_off()

def dump_off (   self,
  timestamp 
)
Suspend dumping to VCD file.

Definition at line 231 of file writer.py.

231 def dump_off(self, timestamp):
232 """Suspend dumping to VCD file."""
233 if self._dumping and not self._registering and self._ident_values:
234 """set dump_off"""
235 self._dump_off(timestamp)
236 self._dumping = False
237

◆ dump_on()

def dump_on (   self,
  timestamp 
)
Resume dumping to VCD file.

Definition at line 251 of file writer.py.

251 def dump_on(self, timestamp):
252 """Resume dumping to VCD file."""
253 if not self._dumping and not self._registering and self._ident_values:
254 print('#' + str(int(timestamp)), file=self._ofile)
255 """set dump_values"""
256 self._dump_values('$dumpon')
257 self._dumping = True
258

◆ flush()

def flush (   self,
  timestamp = None 
)
Flush any buffered VCD data to output file.

If the VCD header has not already been written, calling `flush()` will
force the header to be written thus disallowing any further variable
registration.

:param int timestamp: optional timestamp to insert into VCD stream.

Definition at line 386 of file writer.py.

386 def flush(self, timestamp=None):
387 """Flush any buffered VCD data to output file.
388
389 If the VCD header has not already been written, calling `flush()` will
390 force the header to be written thus disallowing any further variable
391 registration.
392
393 :param int timestamp: optional timestamp to insert into VCD stream.
394
395 """
396 if self._closed:
397 raise VCDPhaseError('Cannot flush() after close()')
398 if self._registering:
399 self._finalize_registration()
400 if timestamp is not None and timestamp > self._timestamp:
401 print("#", int(timestamp), sep='', file=self._ofile)
402 self._ofile.flush()
403

◆ register_var()

def register_var (   self,
  scope,
  name,
  var_type,
  size = None,
  init = None,
  ident = None 
)
Register a VCD variable and return function to change value.

All VCD variables must be registered prior to any value changes.

.. Note::

    The variable `name` differs from the variable's `ident`
    (identifier). The `name` (also known as `ref`) is meant to refer to
    the variable name in the code being traced and is visible in VCD
    viewer applications.  The `ident`, however, is only used within the
    VCD file and can be auto-generated (by specifying ``ident=None``)
    for most applications.

:param scope: The hierarchical scope that the variable belongs within.
:type scope: str or sequence of str
:param str name: Name of the variable.
:param str var_type: One of :const:`VAR_TYPES`.
:param size:
    Size, in bits, of the variable. The *size* may be expressed as an
    int or, for vector variable types, a tuple of int. When the size is
    expressed as a tuple, the *value* passed to :meth:`change()` must
    also be a tuple of same arity as the *size* tuple. Some variable
    types ('integer', 'real', 'realtime', and 'event') have a default
    size and thus *size* may be ``None`` for those variable types.
:type size: int or tuple(int) or None
:param init: Optional initial value; defaults to 'x'.
:param str ident: Optional identifier for use in the VCD stream.
:raises VCDPhaseError: if any values have been changed
:raises ValueError: for invalid var_type value
:raises TypeError: for invalid parameter types
:raises KeyError: for duplicate var name
:returns: :class:`Variable` instance appropriate for use with
          :meth:`change()`.

Definition at line 136 of file writer.py.

137 ident=None):
138 """Register a VCD variable and return function to change value.
139
140 All VCD variables must be registered prior to any value changes.
141
142 .. Note::
143
144 The variable `name` differs from the variable's `ident`
145 (identifier). The `name` (also known as `ref`) is meant to refer to
146 the variable name in the code being traced and is visible in VCD
147 viewer applications. The `ident`, however, is only used within the
148 VCD file and can be auto-generated (by specifying ``ident=None``)
149 for most applications.
150
151 :param scope: The hierarchical scope that the variable belongs within.
152 :type scope: str or sequence of str
153 :param str name: Name of the variable.
154 :param str var_type: One of :const:`VAR_TYPES`.
155 :param size:
156 Size, in bits, of the variable. The *size* may be expressed as an
157 int or, for vector variable types, a tuple of int. When the size is
158 expressed as a tuple, the *value* passed to :meth:`change()` must
159 also be a tuple of same arity as the *size* tuple. Some variable
160 types ('integer', 'real', 'realtime', and 'event') have a default
161 size and thus *size* may be ``None`` for those variable types.
162 :type size: int or tuple(int) or None
163 :param init: Optional initial value; defaults to 'x'.
164 :param str ident: Optional identifier for use in the VCD stream.
165 :raises VCDPhaseError: if any values have been changed
166 :raises ValueError: for invalid var_type value
167 :raises TypeError: for invalid parameter types
168 :raises KeyError: for duplicate var name
169 :returns: :class:`Variable` instance appropriate for use with
170 :meth:`change()`.
171
172 """
173 if self._closed:
174 raise VCDPhaseError('Cannot register after close().')
175 elif not self._registering:
176 raise VCDPhaseError('Cannot register after time 0.')
177 elif var_type not in self.VAR_TYPES:
178 raise ValueError(f'Invalid var_type "{var_type}"')
179
180 scope_tuple = self._get_scope_tuple(scope)
181
182 scope_names = self._scope_var_names.setdefault(scope_tuple, [])
183 if name in scope_names:
184 raise KeyError(f'Duplicate var {name} in scope {scope}')
185
186 if ident is None:
187 ident = format(self._next_var_id, 'x')
188
189 if size is None:
190 if var_type in ['integer', 'real', 'realtime']:
191 size = 64
192 elif var_type == 'event':
193 size = 1
194 else:
195 raise ValueError(
196 f'Must supply size for {var_type} var_type')
197
198 if isinstance(size, Sequence):
199 size = tuple(size)
200 var_size = sum(size)
201 else:
202 var_size = size
203
204 var_str = f'$var {var_type} {var_size} {ident} {name} $end'
205
206 if init is None:
207 if var_type == 'real':
208 init = 0.0
209 elif isinstance(size, tuple):
210 init = tuple('x' * len(size))
211 else:
212 init = 'x'
213
214 if size == 1:
215 var = ScalarVariable(ident, var_type, size)
216 elif var_type == 'real':
217 var = RealVariable(ident, var_type, size)
218 else:
219 var = VectorVariable(ident, var_type, size)
220
221 if var_type != 'event':
222 self.change(var, self._timestamp, init)
223
224 # Only alter state after change_func() succeeds
225 self._next_var_id += 1
226 self._scope_var_strs.setdefault(scope_tuple, []).append(var_str)
227 scope_names.append(name)
228
229 return var
230

◆ set_scope_type()

def set_scope_type (   self,
  scope,
  scope_type 
)
Set the scope_type for a given scope.

The scope's type may be set to one of the valid :const:`SCOPE_TYPES`.
VCD viewer applications may display different scope types differently.

:param scope: The scope to set the type of.
:type scope: str or sequence of str
:param str scope_type: A valid scope type string.
:raises ValueError: for invalid `scope_type`

Definition at line 119 of file writer.py.

119 def set_scope_type(self, scope, scope_type):
120 """Set the scope_type for a given scope.
121
122 The scope's type may be set to one of the valid :const:`SCOPE_TYPES`.
123 VCD viewer applications may display different scope types differently.
124
125 :param scope: The scope to set the type of.
126 :type scope: str or sequence of str
127 :param str scope_type: A valid scope type string.
128 :raises ValueError: for invalid `scope_type`
129
130 """
131 if scope_type is not None and scope_type not in self.SCOPE_TYPES:
132 raise ValueError(f'Invalid scope_type "{scope_type}"')
133 scope_tuple = self._get_scope_tuple(scope)
134 self._scope_types[scope_tuple] = scope_type
135

Member Data Documentation

◆ _check_values

_check_values
protected

set check_values

Definition at line 99 of file writer.py.

◆ _closed

_closed
protected

set closed

Definition at line 103 of file writer.py.

◆ _default_scope_type

_default_scope_type
protected

set default_scope_type

Definition at line 95 of file writer.py.

◆ _dumping

_dumping
protected

set dumping

Definition at line 105 of file writer.py.

◆ _header_keywords

_header_keywords
protected

header keywords

Definition at line 86 of file writer.py.

◆ _ident_values

_ident_values
protected

set ident_values

Definition at line 115 of file writer.py.

◆ _next_var_id

_next_var_id
protected

set next_var_id

Definition at line 107 of file writer.py.

◆ _ofile

_ofile
protected

output file

Definition at line 84 of file writer.py.

◆ _registering

_registering
protected

set registering

Definition at line 101 of file writer.py.

◆ _scope_sep

_scope_sep
protected

set scope_sep

Definition at line 97 of file writer.py.

◆ _scope_types

_scope_types
protected

set scopr_types

Definition at line 113 of file writer.py.

◆ _scope_var_names

_scope_var_names
protected

set scope_var_names

Definition at line 111 of file writer.py.

◆ _scope_var_strs

_scope_var_strs
protected

set scope_var_strs

Definition at line 109 of file writer.py.

◆ _timestamp

_timestamp
protected

set time_stamp

Definition at line 117 of file writer.py.

◆ SCOPE_TYPES

list SCOPE_TYPES = ['begin', 'fork', 'function', 'module', 'task']
static

Valid VCD scope types.

Definition at line 66 of file writer.py.

◆ TIMESCALE_NUMS

list TIMESCALE_NUMS = [1, 10, 100]
static

Valid timescale numbers.

Definition at line 74 of file writer.py.

◆ TIMESCALE_UNITS

list TIMESCALE_UNITS = ['s', 'ms', 'us', 'ns', 'ps', 'fs']
static

Valid timescale units.

Definition at line 77 of file writer.py.

◆ VAR_TYPES

list VAR_TYPES
static
Initial value:
= ['event', 'integer', 'parameter', 'real', 'realtime', 'reg',
'supply0', 'supply1', 'time', 'tri', 'triand', 'trior',
'trireg', 'tri0', 'tri1', 'wand', 'wire', 'wor']

Valid VCD variable types.

Definition at line 69 of file writer.py.


The documentation for this class was generated from the following file: