Skip to content

Commit

Permalink
feat: add basic vhdl parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
glencoe committed May 19, 2023
1 parent c328bd5 commit 5df2a3f
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 1 deletion.
28 changes: 28 additions & 0 deletions elasticai/creator/hdl/vhdl/language.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from dataclasses import dataclass as _dataclass


def _language_node(cls):
return _dataclass(eq=True, frozen=True)(cls)


@_language_node
class SignalDef:
name: str
direction: str
width: int


@_language_node
class Port:
signal_defs: list[SignalDef]


@_language_node
class Connection:
_to: str
_from: str


@_language_node
class Connections:
children: list[Connection]
Empty file.
38 changes: 38 additions & 0 deletions elasticai/creator/hdl/vhdl/parser/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from lark import Transformer

from elasticai.creator.hdl.vhdl.language import Connection, Connections, Port, SignalDef

from .standalone_parser import Lark_StandAlone


class TreeToVHDL(Transformer):
def connection(self, s):
return Connection(_to=s[0].value, _from=s[1].value)

def connections(self, s):
return Connections(s)

def port(self, s):
return Port(s[0])

def vhdl(self, s):
return s[0]

def signal_defs(self, s):
return s

def signal_type(self, s):
v = s[0].data
if v.value == "std_logic":
return 0
else:
return int(s[1].value) - 1

def signal_def(self, s):
name, direction, width = s
name = name.value
direction = direction.data
return SignalDef(name=name, direction=direction, width=width)


parser = Lark_StandAlone(transformer=TreeToVHDL())
20 changes: 20 additions & 0 deletions elasticai/creator/hdl/vhdl/parser/vhdl_grammar.lark
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
vhdl : port | connections
connections: connection+
port : "port" "(" signal_defs ")" ";"
signal_defs : signal_def | signal_def+ ";" signal_def
signal_def : ID ":" direction signal_type
direction: "in" -> in
| "out" -> out
signal_type: std_logic
| std_logic_vector "(" NUMBER "-" "1" "downto" "0" ")"
std_logic_vector: "std_logic_vector"
std_logic: "std_logic"
connection: ID "<" "=" ID ";"

ID: /[a-zA-Z_][a-zA-Z0-9_]*/
NUMBER: /[0-9]+/
COMMENT: /--.*$/
WHITESPACE: /\s+/

%ignore WHITESPACE
%ignore COMMENT
19 changes: 18 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ setuptools = "^67.5.1"

[tool.poetry.group.dev.dependencies]
pytest-bdd = "^6.1.1"
lark = "^1.1.5"

[tool.pylint]
max-line-length = 88
Expand Down
25 changes: 25 additions & 0 deletions tests/vhdl/test_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from elasticai.creator.hdl.vhdl.language import Connection, Connections, Port, SignalDef
from elasticai.creator.hdl.vhdl.parser.parser import parser


def test_parsing_connections():
expected = Connections(
[Connection(_from="y", _to="x"), Connection(_from="b", _to="a")]
)
code = "x <= y; a <= b;"
actual = parser.parse(code)
assert actual == expected


def test_parsing_port():
v = parser.parse(
"port ( my_signal : in std_logic; my_other : out std_logic_vector(5 - 1 downto"
" 0));"
)

assert v == Port(
[
SignalDef(n, d, w)
for n, d, w in (("my_signal", "in", 0), ("my_other", "out", 4))
]
)

0 comments on commit 5df2a3f

Please sign in to comment.