-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
246b860
commit 17002fb
Showing
1 changed file
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
from collections import OrderedDict | ||
from migen.fhdl.std import * | ||
from migen.fhdl.namer import build_namespace | ||
from migen.fhdl.tools import list_special_ios | ||
from migen.fhdl.structure import _Fragment | ||
|
||
from collections import namedtuple | ||
|
||
_Port = namedtuple("_Port", "name direction") | ||
_Cell = namedtuple("_Cell", "name ports") | ||
_Property = namedtuple("_Property", "name value") | ||
_Instance = namedtuple("_Instance", "name cell properties") | ||
_NetBranch = namedtuple("_NetBranch", "portname instancename") | ||
|
||
def _write_cells(cells): | ||
r = "" | ||
for cell in cells: | ||
r += """ | ||
(cell {0.name} | ||
(cellType GENERIC) | ||
(view view_1 | ||
(viewType NETLIST) | ||
(interface""".format(cell) | ||
for port in cell.ports: | ||
r += """ | ||
(port {0.name} (direction {0.direction}))""".format(port) | ||
r += """ | ||
) | ||
) | ||
)""" | ||
return r | ||
|
||
def _write_io(ios): | ||
r = "" | ||
for s in ios: | ||
r += """ | ||
(port {0.name} (direction {0.direction}))""".format(s) | ||
return r | ||
|
||
def _write_instantiations(instances, cell_library): | ||
instantiations = "" | ||
for instance in instances: | ||
instantiations += """ | ||
(instance {0.name} | ||
(viewRef view_1 (cellRef {0.cell} (libraryRef {1})))""".format(instance, cell_library) | ||
for prop in instance.properties: | ||
instantiations += """ | ||
(property {0} (string "{1}"))""".format(prop.name, prop.value) | ||
instantiations += """ | ||
)""" | ||
return instantiations | ||
|
||
def _write_connections(connections): | ||
r = "" | ||
for netname, branches in connections.items(): | ||
r += """ | ||
(net {0} | ||
(joined""".format(netname) | ||
for branch in branches: | ||
r += """ | ||
(portRef {0}{1})""".format(branch.portname, "" if branch.instancename == "" else " (instanceRef {})".format(branch.instancename)) | ||
r += """ | ||
) | ||
)""" | ||
return r | ||
|
||
def _write_edif(cells, ios, instances, connections, cell_library, design_name, part, vendor): | ||
r = """(edif {0} | ||
(edifVersion 2 0 0) | ||
(edifLevel 0) | ||
(keywordMap (keywordLevel 0)) | ||
(external {1} | ||
(edifLevel 0) | ||
(technology (numberDefinition))""".format(design_name, cell_library) | ||
r += _write_cells(cells) | ||
r += """ | ||
) | ||
(library {0}_lib | ||
(edifLevel 0) | ||
(technology (numberDefinition)) | ||
(cell {0} | ||
(cellType GENERIC) | ||
(view view_1 | ||
(viewType NETLIST) | ||
(interface""".format(design_name) | ||
r += _write_io(ios) | ||
r += """ | ||
(designator "{0}") | ||
) | ||
(contents""".format(part) | ||
r += _write_instantiations(instances, cell_library) | ||
r += _write_connections(connections) | ||
r += """ | ||
) | ||
) | ||
) | ||
) | ||
(design {0} | ||
(cellRef {0} (libraryRef {0}_lib)) | ||
(property PART (string "{1}") (owner "{2}")) | ||
) | ||
)""".format(design_name, part, vendor) | ||
|
||
return r | ||
|
||
def _generate_cells(f): | ||
cell_dict = OrderedDict() | ||
for special in f.specials: | ||
if isinstance(special, Instance): | ||
port_list = [] | ||
for port in special.items: | ||
if isinstance(port, Instance.Input): | ||
port_list.append(_Port(port.name, "INPUT")) | ||
elif isinstance(port, Instance.Output): | ||
port_list.append(_Port(port.name, "OUTPUT")) | ||
elif isinstance(port, Instance.Parameter): | ||
pass | ||
else: | ||
raise NotImplementedError("Unsupported instance item") | ||
if special.of in cell_dict: | ||
if set(port_list) != set(cell_dict[special.of]): | ||
raise ValueError("All instances must have the same ports for EDIF conversion") | ||
else: | ||
cell_dict[special.of] = port_list | ||
else: | ||
raise ValueError("Edif conversion can only handle synthesized fragments") | ||
return [_Cell(k, v) for k, v in cell_dict.items()] | ||
|
||
def _generate_instances(f,ns): | ||
instances = [] | ||
for special in f.specials: | ||
if isinstance(special, Instance): | ||
props = [] | ||
for prop in special.items: | ||
if isinstance(prop, Instance.Input): | ||
pass | ||
elif isinstance(prop, Instance.Output): | ||
pass | ||
elif isinstance(prop, Instance.Parameter): | ||
props.append(_Property(name=prop.name, value=prop.value)) | ||
else: | ||
raise NotImplementedError("Unsupported instance item") | ||
instances.append(_Instance(name=ns.get_name(special), cell=special.of, properties=props)) | ||
else: | ||
raise ValueError("Edif conversion can only handle synthesized fragments") | ||
return instances | ||
|
||
def _generate_ios(f, ios, ns): | ||
outs = list_special_ios(f, False, True, False) | ||
r = [] | ||
for io in ios: | ||
direction = "OUTPUT" if io in outs else "INPUT" | ||
r.append(_Port(name=ns.get_name(io), direction=direction)) | ||
return r | ||
|
||
def _generate_connections(f, ios, ns): | ||
r = OrderedDict() | ||
for special in f.specials: | ||
if isinstance(special, Instance): | ||
instname = ns.get_name(special) | ||
for port in special.items: | ||
if isinstance(port, Instance.Input) or isinstance(port, Instance.Output): | ||
s = ns.get_name(port.expr) | ||
if s not in r: | ||
r[s] = [] | ||
r[s].append(_NetBranch(portname=port.name, instancename=instname)) | ||
elif isinstance(port, Instance.Parameter): | ||
pass | ||
else: | ||
raise NotImplementedError("Unsupported instance item") | ||
else: | ||
raise ValueError("Edif conversion can only handle synthesized fragments") | ||
for s in ios: | ||
io = ns.get_name(s) | ||
if io not in r: | ||
r[io] = [] | ||
r[io].append(_NetBranch(portname=io, instancename="")) | ||
return r | ||
|
||
def convert(f, ios, name, cell_library, part, vendor): | ||
if not isinstance(f, _Fragment): | ||
f = f.get_fragment() | ||
if f.comb != [] or f.sync != {}: | ||
raise ValueError("Edif conversion can only handle synthesized fragments") | ||
if ios is None: | ||
ios = set() | ||
cells = _generate_cells(f) | ||
ns = build_namespace(list_special_ios(f, True, True, True)) | ||
instances = _generate_instances(f, ns) | ||
inouts = _generate_ios(f, ios, ns) | ||
connections = _generate_connections(f, ios, ns) | ||
return _write_edif(cells, inouts, instances, connections, cell_library, name, part, vendor) |