Skip to content

Commit

Permalink
Merge 32ed3a6 into e8544a4
Browse files Browse the repository at this point in the history
  • Loading branch information
rsetaluri committed May 7, 2019
2 parents e8544a4 + 32ed3a6 commit 8a172f8
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
23 changes: 15 additions & 8 deletions magma/fromverilog.py
Expand Up @@ -146,7 +146,8 @@ def ParseVerilogModule(node, type_map):
return node.name, args


def FromVerilog(source, func, type_map, target_modules=None, shallow=False):
def FromVerilog(source, func, type_map, target_modules=None, shallow=False,
external_modules={}):
parser = VerilogParser()
ast = parser.parse(source)
visitor = ModuleVisitor()
Expand All @@ -159,7 +160,11 @@ def _get_lines(start_line, end_line):
lines = source.split("\n")
return "\n".join(lines[start_line - 1:end_line])

magma_defns = {}
if not external_modules.keys().isdisjoint(visitor.defns.keys()):
intersection = external_modules.keys() & visitor.defns.keys()
raise Exception(f"Modules defined in both external_modules and in "
f"parsed verilog: {intersection}")
magma_defns = external_modules.copy()
for name, verilog_defn in visitor.defns.items():
parsed_name, args = ParseVerilogModule(verilog_defn, type_map)
assert parsed_name == name
Expand All @@ -180,16 +185,18 @@ def _get_lines(start_line, end_line):
logger.warning(f"Did not import any modules from verilog, either could "
f"not parse or could not find any of the target_modules "
f"({target_modules})")
# Filter back out external modules.
magma_defns = {name : magma_defns[name] for name in visitor.defns}
if target_modules is None:
return list(magma_defns.values())
# Filter modules based on target_modules list.
return [v for k, v in magma_defns.items() if k in target_modules]

def FromVerilogFile(file, func, type_map, target_modules=None, shallow=False):
def FromVerilogFile(file, func, type_map, target_modules=None, shallow=False, external_modules={}):
if file is None:
return None
verilog = open(file).read()
result = FromVerilog(verilog, func, type_map, target_modules, shallow)
result = FromVerilog(verilog, func, type_map, target_modules, shallow, external_modules)
# Store the original verilog file name, currently used by m.compile to
# generate a .sv when compiling a circuit that was defined from a verilog
# file
Expand Down Expand Up @@ -221,13 +228,13 @@ def DeclareFromTemplatedVerilogFile(file, type_map={}, **kwargs):
return FromTemplatedVerilogFile(file, DeclareCircuit, type_map, **kwargs)


def DefineFromVerilog(source, type_map={}, target_modules=None, shallow=False):
def DefineFromVerilog(source, type_map={}, target_modules=None, shallow=False, external_modules={}):
return FromVerilog(source, DefineCircuit, type_map, target_modules,
shallow=shallow)
shallow=shallow, external_modules=external_modules)

def DefineFromVerilogFile(file, target_modules=None, type_map={}, shallow=False):
def DefineFromVerilogFile(file, target_modules=None, type_map={}, shallow=False, external_modules={}):
return FromVerilogFile(file, DefineCircuit, type_map, target_modules,
shallow=shallow)
shallow=shallow, external_modules=external_modules)

def DefineFromTemplatedVerilog(source, type_map={}, **kwargs):
return FromTemplatedVerilog(source, DefineCircuit, type_map, **kwargs)
Expand Down
53 changes: 53 additions & 0 deletions tests/test_verilog/test_from_file.py
@@ -1,6 +1,8 @@
import magma as m
import magma.testing
import os
import pytest


def check_port(definition, port, type, direction):
assert hasattr(definition, port)
Expand Down Expand Up @@ -151,3 +153,54 @@ def test_verilog_dependency_out_of_order():
m.compile(f"build/{FILENAME}", top, output="coreir")
assert m.testing.check_files_equal(__file__, f"build/{FILENAME}.json",
f"gold/{FILENAME}.json")


def test_from_verilog_external_modules():
[foo] = m.DefineFromVerilog("""
module foo(input I, output O);
assign O = I;
endmodule""")
[bar] = m.DefineFromVerilog("""
module bar(input I, output O);
foo foo_inst(I, O);
endmodule""", external_modules={"foo": foo})
top = m.DefineCircuit("top", "I", m.In(m.Bit), "O", m.Out(m.Bit))
bar_inst = bar()
m.wire(top.I, bar_inst.I)
m.wire(bar_inst.O, top.O)
m.EndDefine()
FILENAME = "test_verilog_dependency_top"
m.compile(f"build/{FILENAME}", top, output="coreir")
assert m.testing.check_files_equal(__file__, f"build/{FILENAME}.json",
f"gold/{FILENAME}.json")


def test_from_verilog_external_modules_missing():
with pytest.raises(Exception) as pytest_e:
m.DefineFromVerilog("""
module bar(input I, output O);
foo foo_inst(I, O);
endmodule""")
assert False
assert pytest_e.type is KeyError
assert pytest_e.value.args == ("foo",)


def test_from_verilog_external_modules_duplicate():
with pytest.raises(Exception) as pytest_e:
[foo] = m.DefineFromVerilog("""
module foo(input I, output O);
assign O = I;
endmodule""")
[bar] = m.DefineFromVerilog("""
module foo(input I, output O);
assign O = I;
endmodule
module bar(input I, output O);
foo foo_inst(I, O);
endmodule""", external_modules={"foo": foo})
assert False
assert pytest_e.type is Exception
assert pytest_e.value.args == \
("Modules defined in both external_modules and in parsed verilog: {'foo'}",) # nopep8

0 comments on commit 8a172f8

Please sign in to comment.