Added option for reduction of long clock sequences in wavedrom converter
Signed-off-by: Wojciech Gryncewicz <wgryncewicz@antmicro.com>
diff --git a/scripts/python-skywater-pdk/skywater_pdk/cells/generate/vcd2wavedrom.py b/scripts/python-skywater-pdk/skywater_pdk/cells/generate/vcd2wavedrom.py
index ed9b43b..7e4adf1 100755
--- a/scripts/python-skywater-pdk/skywater_pdk/cells/generate/vcd2wavedrom.py
+++ b/scripts/python-skywater-pdk/skywater_pdk/cells/generate/vcd2wavedrom.py
@@ -18,6 +18,7 @@
import argparse
import pathlib
import wavedrom
+import re
from contextlib import contextmanager
@@ -44,7 +45,7 @@
def readVCD (file):
- ''' Parses VCD file.
+ ''' Parses VCD file.
Args:
file - path to a VCD file [pathlib.Path]
@@ -67,12 +68,12 @@
# tag, other than end
if not line.startswith('$end'):
currtag = line.partition(' ')[0].lstrip('$').rstrip()
- vcd[currtag] = vcd.setdefault(currtag, '') + line.partition(' ')[2].rpartition('$')[0]
+ vcd[currtag] = vcd.setdefault(currtag, '') + line.partition(' ')[2].rpartition('$')[0]
# line ends with end tag
if not vcd[currtag].endswith('\n'):
- vcd[currtag] += '\n'
+ vcd[currtag] += '\n'
if line.split()[-1]=='$end':
- currtag = 'body'
+ currtag = 'body'
vcd[currtag] = ''
if 'var' not in vcd:
@@ -83,13 +84,39 @@
return vcd
-def parsetowavedrom (file, savetofile = False):
+
+def reduce_clock_sequences (wave) :
+ ''' Remove clock seqnces longer than 2 cycles
+ not accompanied by other signals changes
+
+ Parameters:
+ wave - dictionary 'signal'->['list of states'] [dict]
+ '''
+ for v in wave:
+ sig = wave[v] # analized signal
+ other = [wave[i] for i in wave if i!=v] # list of other signals
+ other = [''.join(s) for s in zip(*other)] # list of concatenated states
+ other = [len(s.replace('.','')) for s in other] # list of state changes count
+ sig = [s if o==0 else ' ' for s,o in zip(sig,other)] # keep only when no changes in other
+ sig = "".join(sig)
+ cuts = []
+ for m in re.finditer("(10){2,}",sig):
+ cuts.append( (m.start()+1, m.end()-1) ) # area to be reduced, leave 1..0
+ cuts.reverse()
+ for cut in cuts:
+ for v,w in wave.items(): # reduce cuts from all signals
+ wave[v] = w[ :cut[0]] + w[cut[1]: ]
+
+ return wave
+
+
+def parsetowavedrom (file, savetofile = False, reduce_clock = False):
''' Reads and simplifies VCD waveform
Generates wavedrom notation.
Args:
file - path to a VCD file [pathlib.Path]
-
+
'''
varsubst = {} # var substitution
reg = [] # list of signals
@@ -117,21 +144,21 @@
# set initial states
event.append(0)
- #default
+ #default
for v in reg+wire:
wave[v] = ['x']
#defined
- for line in vcd['dumpvars'].split('\n'):
+ for line in vcd['dumpvars'].split('\n'):
if len(line)>=2:
wave[ varsubst[line[1]] ] = [line[0]]
- # parse wave body
+ # parse wave body
for line in vcd['body'].split('\n'):
#timestamp line
if line.startswith('#'):
line = line.strip().lstrip('#')
if not line.isnumeric():
- raise SyntaxError("Invalid VCD timestamp")
+ raise SyntaxError("Invalid VCD timestamp")
event.append(int(line))
for v in wave.keys():
wave[v].append('.')
@@ -139,11 +166,12 @@
else :
if len(line)>=2:
wave [ varsubst[line[1]] ][-1] = line[0]
-
- # TODO: add "double interval support"
+
+ if reduce_clock:
+ wave = reduce_clock_sequences(wave)
signals = []
- for v in wave.keys():
+ for v in wave.keys():
fill = ' ' * (max( [len(s) for s in wave.keys()] ) - len(v))
wavestr = ''.join(wave[v])
signals.append( signal_template.format( name = v, wave = wavestr, fill = fill ) )
@@ -151,15 +179,18 @@
wavedrom = wavedrom_template.format ( signals = signals )
- outfile = file.with_suffix(".wdr.json") if savetofile else None
+ outfile = file.with_suffix(".wdr.json") if savetofile else None
with file_or_stdout(outfile) as f:
f.write(wavedrom)
-
+
return wavedrom
def quoted_strings_wavedrom (wdr) :
''' Convert wavedrom script to more restrictive
version of JSON with quoted keywords
+
+ Parameters:
+ wdr - wavedrom script [str]
'''
wdr = wdr.replace(' signal:',' "signal":')
wdr = wdr.replace(' name:',' "name":')
@@ -191,6 +222,11 @@
help="generate .svg image",
action="store_true")
parser.add_argument(
+ "-r",
+ "--reduceclk",
+ help="reduce clock sequences",
+ action="store_true")
+ parser.add_argument(
"infile",
help="VCD waveform file",
type=pathlib.Path,
@@ -209,10 +245,10 @@
errors = 0
for f in infile:
try:
- wdr = parsetowavedrom(f, args.wavedrom)
+ wdr = parsetowavedrom(f, args.wavedrom, args.reduceclk)
if args.savesvg:
svg = wavedrom.render( quoted_strings_wavedrom(wdr) )
- outfile = f.with_suffix(".svg")
+ outfile = f.with_suffix(".svg")
svg.saveas(outfile)
except KeyboardInterrupt:
sys.exit(1)