1 from collections
import OrderedDict
, namedtuple
3 from migen
.fhdl
.structure
import *
4 from migen
.fhdl
.namer
import build_namespace
5 from migen
.fhdl
.tools
import list_special_ios
6 from migen
.fhdl
.structure
import _Fragment
7 from migen
.fhdl
.conv_output
import ConvOutput
10 _Port
= namedtuple("_Port", "name direction")
11 _Cell
= namedtuple("_Cell", "name ports")
12 _Property
= namedtuple("_Property", "name value")
13 _Instance
= namedtuple("_Instance", "name cell properties")
14 _NetBranch
= namedtuple("_NetBranch", "portname instancename")
17 def _write_cells(cells
):
25 (interface""".format(cell
)
26 for port
in cell
.ports
:
28 (port {0.name} (direction {0.direction}))""".format(port
)
40 (port {0.name} (direction {0.direction}))""".format(s
)
44 def _write_instantiations(instances
, cell_library
):
46 for instance
in instances
:
49 (viewRef view_1 (cellRef {0.cell} (libraryRef {1})))""".format(instance
, cell_library
)
50 for prop
in instance
.properties
:
52 (property {0} (string "{1}"))""".format(prop
.name
, prop
.value
)
58 def _write_connections(connections
):
60 for netname
, branches
in connections
.items():
63 (joined""".format(netname
)
64 for branch
in branches
:
66 (portRef {0}{1})""".format(branch
.portname
, "" if branch
.instancename
== "" else " (instanceRef {})".format(branch
.instancename
))
73 def _write_edif(cells
, ios
, instances
, connections
, cell_library
, design_name
, part
, vendor
):
77 (keywordMap (keywordLevel 0))
80 (technology (numberDefinition))""".format(design_name
, cell_library
)
81 r
+= _write_cells(cells
)
86 (technology (numberDefinition))
91 (interface""".format(design_name
)
96 (contents""".format(part
)
97 r
+= _write_instantiations(instances
, cell_library
)
98 r
+= _write_connections(connections
)
105 (cellRef {0} (libraryRef {0}_lib))
106 (property PART (string "{1}") (owner "{2}"))
108 )""".format(design_name
, part
, vendor
)
113 def _generate_cells(f
):
114 cell_dict
= OrderedDict()
115 for special
in f
.specials
:
116 if isinstance(special
, Instance
):
118 for port
in special
.items
:
119 if isinstance(port
, Instance
.Input
):
120 port_list
.append(_Port(port
.name
, "INPUT"))
121 elif isinstance(port
, Instance
.Output
):
122 port_list
.append(_Port(port
.name
, "OUTPUT"))
123 elif isinstance(port
, Instance
.InOut
):
124 port_list
.append(_Port(port
.name
, "INOUT"))
125 elif isinstance(port
, Instance
.Parameter
):
128 raise NotImplementedError("Unsupported instance item")
129 if special
.of
in cell_dict
:
130 if set(port_list
) != set(cell_dict
[special
.of
]):
131 raise ValueError("All instances must have the same ports for EDIF conversion")
133 cell_dict
[special
.of
] = port_list
135 raise ValueError("EDIF conversion can only handle synthesized fragments")
136 return [_Cell(k
, v
) for k
, v
in cell_dict
.items()]
139 def _generate_instances(f
, ns
):
141 for special
in f
.specials
:
142 if isinstance(special
, Instance
):
144 for prop
in special
.items
:
145 if isinstance(prop
, Instance
.Input
):
147 elif isinstance(prop
, Instance
.Output
):
149 elif isinstance(prop
, Instance
.InOut
):
151 elif isinstance(prop
, Instance
.Parameter
):
152 props
.append(_Property(name
=prop
.name
, value
=prop
.value
))
154 raise NotImplementedError("Unsupported instance item")
155 instances
.append(_Instance(name
=ns
.get_name(special
), cell
=special
.of
, properties
=props
))
157 raise ValueError("EDIF conversion can only handle synthesized fragments")
161 def _generate_ios(f
, ios
, ns
):
162 outs
= list_special_ios(f
, False, True, False)
163 inouts
= list_special_ios(f
, False, False, True)
166 direction
= "OUTPUT" if io
in outs
else "INOUT" if io
in inouts
else "INPUT"
167 r
.append(_Port(name
=ns
.get_name(io
), direction
=direction
))
171 def _generate_connections(f
, ios
, ns
):
173 for special
in f
.specials
:
174 if isinstance(special
, Instance
):
175 instname
= ns
.get_name(special
)
176 for port
in special
.items
:
177 if isinstance(port
, Instance
._IO
):
178 s
= ns
.get_name(port
.expr
)
181 r
[s
].append(_NetBranch(portname
=port
.name
, instancename
=instname
))
182 elif isinstance(port
, Instance
.Parameter
):
185 raise NotImplementedError("Unsupported instance item")
187 raise ValueError("EDIF conversion can only handle synthesized fragments")
192 r
[io
].append(_NetBranch(portname
=io
, instancename
=""))
196 def convert(f
, ios
, cell_library
, vendor
, device
, name
="top"):
197 if not isinstance(f
, _Fragment
):
199 if f
.comb
!= [] or f
.sync
!= {}:
200 raise ValueError("EDIF conversion can only handle synthesized fragments")
203 cells
= _generate_cells(f
)
204 ns
= build_namespace(list_special_ios(f
, True, True, True))
205 instances
= _generate_instances(f
, ns
)
206 inouts
= _generate_ios(f
, ios
, ns
)
207 connections
= _generate_connections(f
, ios
, ns
)
208 src
= _write_edif(cells
, inouts
, instances
, connections
, cell_library
, name
, device
, vendor
)
211 r
.set_main_source(src
)