Skip to content

Commit

Permalink
Merge pull request #66 from Ben1152000/feature/call-syntax
Browse files Browse the repository at this point in the history
Implement function call syntax
  • Loading branch information
Ben1152000 authored Sep 20, 2022
2 parents f2153a9 + 99da516 commit 8d4efae
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 31 deletions.
13 changes: 6 additions & 7 deletions sootty/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,6 @@ def main():
if breakpoints is not None:
breakpoints = wiretrace.evaluate(breakpoints)

if wires is not None:
wires = set([name.strip() for name in wires.split(",")])

# Convert wiretrace to graphical vector image.
image = Visualizer().to_svg(
wiretrace,
Expand All @@ -164,10 +161,12 @@ def main():
vector_radix=radix,
)

if wires is not None and len(wires):
raise Exception(
f"Unknown wires {wires.__repr__()}\nThe following wires were detected in the wiretrace:\n{wiretrace.get_wire_names()}"
)
# This was the previous way of handling invalid wire names. It is no longer needed,
# but I'm keeping it here as a reminder to review the error handling system.
# if wires is not None and len(wires):
# raise Exception(
# f"Unknown wires {wires.__repr__()}\nThe following wires were detected in the wiretrace:\n{wiretrace.get_wire_names()}"
# )

if not output:
image.display() # Show image in terminal (works in kitty, iterm)
Expand Down
34 changes: 21 additions & 13 deletions sootty/limits.py → sootty/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
except ImportError:
import importlib_resources as pkg_resources

# Read and interpret grammar file.
from . import static

parser = Lark(pkg_resources.open_text(static, "grammar.lark").read())
from . import static # Read and interpret grammar file.
from .exceptions import SoottyError


class Prune(Visitor):
Expand All @@ -26,7 +24,7 @@ def binexp(self, tree):
tree.data = tree.children[1]
tree.children = [tree.children[0], tree.children[2]]

def start(self, tree):
def expr(self, tree):
self.binexp(tree)

def lexp(self, tree):
Expand Down Expand Up @@ -64,13 +62,23 @@ def wire(self, tree):
tree.children = [tree.children[0], tree.children[2]]


class LimitExpression:
"""Parses an expression representing the limits of a wiretrace window."""
class ExpressionParser(Lark):
"""Implementation of Lark parser class for limit expressions."""

def __init__(self):
grammar = pkg_resources.open_text(static, "grammar.lark").read()
super().__init__(grammar, start=["expr", "exprs"])

def parse(self, expression: str):
tree = super().parse(expression, start="expr")
tree = Prune().visit(tree)
# print(self.tree.pretty(), file=sys.stderr)
return tree

def parse_list(self, expressions: str):
tree = super().parse(expressions, start="exprs")
tree = Prune().visit(tree)
return tree.children

def __init__(self, expression):
parsed = parser.parse(expression)
self.tree = Prune().visit(parsed)

def display(self):
"""Display parse tree for debugging purposes."""
print(self.tree.pretty(), file=sys.stderr)
parser = ExpressionParser() # initialize global parser object
14 changes: 10 additions & 4 deletions sootty/static/grammar.lark
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
%import common.DIGIT -> DIGIT
%import common.NUMBER -> NUM

start : lexp
NAME: ("_"|LETTER) ("_"|LETTER|DIGIT)* ("." ("_"|LETTER|DIGIT)+)*
NAME : ("_"|LETTER) ("_"|LETTER|DIGIT)* ("." ("_"|LETTER|DIGIT)+)*

AND : "&"
OR : "|"
Expand Down Expand Up @@ -58,5 +57,12 @@ uop : INV | NEG | NOT
type : CONST | TIME
top : FROM | AFTER | UNTIL | BEFORE
tsop : NEXT | PREV
wire : NAME | "(" lexp ")" | uop wire | type NUM
| top wire | tsop wire | NUM tsop wire | ACC wire

call : NAME "(" args ")"
args : wire ("," wire)*

wire : NAME | "(" lexp ")" | uop wire | type NUM | top wire | tsop wire
| NUM tsop wire | ACC wire | call

expr : lexp
exprs : expr ("," expr)*
16 changes: 13 additions & 3 deletions sootty/storage/wiretrace.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from vcd.reader import *

from ..exceptions import *
from ..limits import LimitExpression
from ..parser import parser
from .wiregroup import WireGroup
from .wire import Wire
from ..utils import evcd2vcd
Expand Down Expand Up @@ -188,6 +188,12 @@ def _compute_wire(self, node):
"""Evaluate a limit expression"""
if node.data == "wire":
return self.find(node.children[0])
elif node.data == "call":
name = node.children[0]
args = list(map(self._compute_wire, node.children[1].children))
if name == "AXI":
return args[0] # TODO: implement axi protocol
raise SoottyError(f'Function "{name}" does not exist.')
elif node.data.type == "NEG":
return self._compute_wire(node.children[0]).__neg__()
elif node.data.type == "INV":
Expand Down Expand Up @@ -278,8 +284,12 @@ def _compute_wire(self, node):
return Wire.time(int(node.children[0]))

def compute_wire(self, expr: str):
"""Evaluate a limit expression"""
return self._compute_wire(LimitExpression(expr).tree)
"""Evaluate a limit expression to a wire."""
return self._compute_wire(parser.parse(expr))

def compute_wires(self, exprs: str):
"""Evaluate comma-separated limit expressions as a list of wires."""
return list(map(self._compute_wire, parser.parse_list(exprs)))

def evaluate(self, expr: str):
return self.compute_wire(expr).times(self.length())
Expand Down
21 changes: 17 additions & 4 deletions sootty/visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,27 @@ def to_svg(
wiretrace,
start=0,
length=None,
wires=None,
wires="",
breakpoints=None,
vector_radix=10,
):
"""
Converts the provided wiretrace object to a VectorImage object (svg).
:param wires: comma-seperated list of wires to include
"""
if length is None:
length = wiretrace.length()
"""Converts the provided wiretrace object to a VectorImage object (svg)."""

if wires: # include all wires if empty list provided
wires = (
None
if len(wires) == 0
else set(
map(lambda wire: wire.name, wiretrace.compute_wires(wires.strip()))
)
)

return VectorImage(
self._wiretrace_to_svg(
wiretrace, start, length, wires, breakpoints, vector_radix
Expand All @@ -91,11 +105,10 @@ def to_svg(
def _wiretrace_to_svg(
self, wiretrace, start, length, wires=None, breakpoints=None, vector_radix=10
):
if wires and len(wires) == 0: # include all wires if empty list provided
wires = None
width = (
2 * self.style.LEFT_MARGIN + self.style.TEXT_WIDTH + self.style.FULL_WIDTH
)

height = (
2 * self.style.TOP_MARGIN
- self.style.WIRE_MARGIN
Expand Down

0 comments on commit 8d4efae

Please sign in to comment.