Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature: Print breakpoint table #61

Merged
merged 6 commits into from
Sep 11, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sootty "waveform.vcd" -o > image.svg

with a Value Change Dump (VCD) or Extended VCD (EVCD) file to produce an svg waveform diagram. Optional arguments include:
- `-b | --break FORMULA` Specify the formula for the points in time to be highlighted.
- `--btable` Print the wire value table at breakpoints to `stdout` (`-b` is required).
- `-e | --end FORMULA` Specify the end of the window.
- `-h | --help` Show the help message and exit.
- `-l | --length N` Specify the number of ticks in the window (mutually exclusive with `-e`).
Expand Down Expand Up @@ -57,6 +58,12 @@ Reloading a saved query:
sootty -R "save.txt"
```

Add breakpoints at time 9, 11, and 16 - 17 and print wire values at breakpoints:

```bash
sootty "example/example5.evcd" -b "time 9 || time 11 || after time 15 && before time 18" --btable
```

How to run in python (using the repl):

```python
Expand Down
67 changes: 67 additions & 0 deletions example/example5.evcd
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
$comment
File created using the following command:
vcd file opt3.evcd -dumpports
$end
$date
Sat Sep 3 13:11:39 2022
$end
$version
dumpports ModelSim Version 10.2c
$end
$timescale
1ps
$end

$scope module testbench $end

$scope module pe8 $end
$var port [7:0] <0 req $end
$var port 1 <1 en $end
$upscope $end

$scope module pe4 $end
$var port [3:0] <2 req $end
$var port 1 <3 en $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
$dumpports
pU 0 6 <1
pU 0 6 <3
pDDDDDDDD 66666666 00000000 <0
pDDDD 6666 0000 <2
$end
#5
pUDDDDDDD 06666666 60000000 <0
pUDDD 0666 6000 <2
#10
pDDDUDDDD 66606666 00060000 <0
pDUDD 6066 0600 <2
#15
pDDDDDUDD 66666066 00000600 <0
pDDUD 6606 0060 <2
#20
pDDDDDDDU 66666660 00000006 <0
pDDDU 6660 0006 <2
#25
pDUDUDUDU 60606060 06060606 <0
pDUDU 6060 0606 <2
#30
pDUUDDUUD 60066006 06600660 <0
pDUUD 6006 0660 <2
#35
pUUUDUUUD 00060006 66606660 <0
pUUUD 0006 6660 <2
#40
pUUUUUUUU 00000000 66666666 <0
pUUUU 0000 6666 <2
#45
pD 6 0 <3
pD 6 0 <1
#50
pDUUDDUUD 60066006 06600660 <0
pDUUD 6006 0660 <2
$vcdclose
#55
$end
23 changes: 17 additions & 6 deletions sootty/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import argparse
import os
import yaml
import sys
from sootty.exceptions import SoottyError
from .save import save_query, reload_query
from .storage import WireTrace
Expand All @@ -17,7 +16,7 @@ def parse_args():
default=None,
metavar="FILENAME",
type=str,
help="input .vcd file (required unless -R flag is provided)",
help="input .vcd or .evcd file (required unless -R flag is provided)",
)
parser.add_argument(
"-s",
Expand All @@ -41,13 +40,23 @@ def parse_args():
parser.add_argument(
"-b",
"--break",
required='--btable' in sys.argv,
type=str,
metavar="FORMULA",
dest="breakpoints",
help="formula for the points in time to be highlighted",
)
parser.add_argument(
"-l", "--length", type=int, dest="length", help="number of cycles to display"
'--btable',
action="store_true",
help="print a breakpoint table to stdout",
)
parser.add_argument(
"-l",
"--length",
type=int,
dest="length",
help="number of cycles to display",
)
parser.add_argument(
"-o",
Expand Down Expand Up @@ -102,6 +111,7 @@ def parse_args():
args.filename,
args.wires,
args.breakpoints,
args.btable,
args.length,
args.start,
args.end,
Expand All @@ -111,7 +121,7 @@ def parse_args():


def main():
filename, wires, breakpoints, length, start, end, output, radix = parse_args()
filename, wires, breakpoints, btable, length, start, end, output, radix = parse_args()

if filename is None:
raise SoottyError("Input file is required. See --help for more info.")
Expand Down Expand Up @@ -161,10 +171,11 @@ def main():

if not output:
image.display() # Show image in terminal (works in kitty, iterm)

else:
print(image.source)

if btable:
wiretrace.print_breakpoints(breakpoints)

if __name__ == "__main__":
main()
1 change: 0 additions & 1 deletion sootty/storage/valuechange.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import sys
from vcd.reader import *
from itertools import islice
from sortedcontainers import SortedDict, SortedList, SortedSet
Expand Down
1 change: 0 additions & 1 deletion sootty/storage/wire.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import sys
from itertools import compress, chain

from ..exceptions import *
Expand Down
33 changes: 25 additions & 8 deletions sootty/storage/wiregroup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import sys

from ..exceptions import *
from .wire import Wire

Expand Down Expand Up @@ -39,10 +37,29 @@ def find(self, name: str):
raise SoottyError(f"Wire '{name}' does not exist.")

def get_names(self):
yihuajack marked this conversation as resolved.
Show resolved Hide resolved
"""Returns list of all wire names."""
names = set()
for wire in self.wires:
names.add(wire.name)
for group in self.groups:
names.update(group.get_names())
"""Returns a dictionary of all wire names of this wiregroup or a list if this wiregroup is the innermost one."""
yihuajack marked this conversation as resolved.
Show resolved Hide resolved
if self.groups:
names = dict()
if self.wires:
names[self.name] = list()
for wire in self.wires:
names[self.name].append(wire.name)
for group in self.groups:
names[group.name] = group.get_names()
else:
names = list()
for wire in self.wires:
names.append(wire.name)
return names

def get_wires(self):
yihuajack marked this conversation as resolved.
Show resolved Hide resolved
"""Returns a dictionary of all wires of this wiregroup or a list if this wiregroup is the innermost one."""
if self.groups:
wires = dict()
if self.wires:
wires[self.name] = self.wires
for group in self.groups:
wires[group.name] = group.get_wires()
else:
wires = self.wires
return wires
22 changes: 21 additions & 1 deletion sootty/storage/wiretrace.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import json, sys
import sys
from vcd.reader import *

from ..exceptions import *
Expand Down Expand Up @@ -290,3 +290,23 @@ def compute_limits(self, start_expr: str, end_expr: str):
ends = list(filter(lambda time: time > start, self.evaluate(end_expr)))
end = ends[0] if len(ends) else self.length()
return (start, end)

def print_breakpoints(self, breakpoints: list):
"""
Print a table of wires and their values.
"""
def rec_print(wires):
for scope, sub in wires.items():
if type(sub) is dict:
print("scope\t" + scope)
rec_print(sub)
else: # is list
print("scope\t" + scope)
for wire in sub:
print(wire.name, end="\t")
for breakpoint in breakpoints:
print(str(wire._data.get(breakpoint)), end="\t")
print()

print("time", *breakpoints, sep="\t")
rec_print(self.root.get_wires())
8 changes: 4 additions & 4 deletions sootty/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def dec2anybase(input, base, width):
res += chr(rem + ord("0"))
else:
res += chr(rem - 10 + ord("A"))
input = int(input / base)
input = input // base

return res[::-1].zfill(ceil(log(2**width - 1, base)))

Expand Down Expand Up @@ -129,12 +129,12 @@ def evcd2vcd(stream):
while True:
# Basic formatter and syntax checker
if tok == b'$comment' or tok == b'$date' or tok == b'$timescale' or tok == b'$version':
vcd.write(tok + b' ')
vcd.write(tok + b'\n ')
body = next(tokit)
while body != b'$end':
vcd.write(body + b' ')
vcd.write(b' ' + body)
body = next(tokit)
vcd.write(b'$end\n') # body + \n
vcd.write(b'\n$end\n') # body + \n
tok = next(tokit)
elif tok == b'$enddefinitions':
if next(tokit) != b'$end':
Expand Down
2 changes: 1 addition & 1 deletion sootty/visualizer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import sys, html
import html
from enum import Enum

from .display import VectorImage
Expand Down