5163d9227590e9e33326fc969a07027ac9330e24
3 from migen
.fhdl
.structure
import Signal
4 from migen
.genlib
.record
import Record
5 from migen
.genlib
.io
import CRG
6 from migen
.fhdl
import verilog
, edif
7 from migen
.build
import tools
10 class ConstraintError(Exception):
15 def __init__(self
, *identifiers
):
18 self
.identifiers
+= i
.split()
21 return "{}('{}')".format(self
.__class
__.__name
__,
22 " ".join(self
.identifiers
))
26 def __init__(self
, name
):
30 return "{}('{}')".format(self
.__class
__.__name
__, self
.name
)
34 def __init__(self
, strength
):
35 self
.strength
= strength
38 return "{}('{}')".format(self
.__class
__.__name
__, self
.strength
)
42 def __init__(self
, misc
):
46 return "{}({})".format(self
.__class
__.__name
__, repr(self
.misc
))
50 def __init__(self
, name
, *constraints
):
52 self
.constraints
= list(constraints
)
55 return "{}('{}', {})".format(
56 self
.__class
__.__name
__,
58 ", ".join([repr(constr
) for constr
in self
.constraints
]))
62 def __init__(self
, info
):
66 return "{}({})".format(self
.__class
__.__name
__, repr(self
.info
))
69 def _lookup(description
, name
, number
):
70 for resource
in description
:
71 if resource
[0] == name
and (number
is None or resource
[1] == number
):
73 raise ConstraintError("Resource not found: {}:{}".format(name
, number
))
76 def _resource_type(resource
):
78 for element
in resource
[2:]:
79 if isinstance(element
, Pins
):
81 t
= len(element
.identifiers
)
82 elif isinstance(element
, Subsignal
):
86 assert(isinstance(t
, list))
88 for c
in element
.constraints
:
89 if isinstance(c
, Pins
):
90 assert(n_bits
is None)
91 n_bits
= len(c
.identifiers
)
93 t
.append((element
.name
, n_bits
))
98 class ConnectorManager
:
99 def __init__(self
, connectors
):
100 self
.connector_table
= dict()
101 for connector
in connectors
:
102 cit
= iter(connector
)
103 conn_name
= next(cit
)
104 if isinstance(connector
[1], str):
107 pin_list
+= pins
.split()
108 pin_list
= [None if pin
== "None" else pin
for pin
in pin_list
]
109 elif isinstance(connector
[1], dict):
110 pin_list
= connector
[1]
112 raise ValueError("Unsupported pin list type {} for connector"
113 " {}".format(type(connector
[1]), conn_name
))
114 if conn_name
in self
.connector_table
:
116 "Connector specified more than once: {}".format(conn_name
))
118 self
.connector_table
[conn_name
] = pin_list
120 def resolve_identifiers(self
, identifiers
):
122 for identifier
in identifiers
:
123 if ":" in identifier
:
124 conn
, pn
= identifier
.split(":")
128 r
.append(self
.connector_table
[conn
][pn
])
135 def _separate_pins(constraints
):
138 for c
in constraints
:
139 if isinstance(c
, Pins
):
148 class ConstraintManager
:
149 def __init__(self
, io
, connectors
):
150 self
.available
= list(io
)
152 self
.platform_commands
= []
153 self
.connector_manager
= ConnectorManager(connectors
)
155 def add_extension(self
, io
):
156 self
.available
.extend(io
)
158 def request(self
, name
, number
=None):
159 resource
= _lookup(self
.available
, name
, number
)
160 rt
= _resource_type(resource
)
161 if isinstance(rt
, int):
162 obj
= Signal(rt
, name_override
=resource
[0])
164 obj
= Record(rt
, name
=resource
[0])
166 for element
in resource
[2:]:
167 if isinstance(element
, PlatformInfo
):
168 obj
.platform_info
= element
.info
171 self
.available
.remove(resource
)
172 self
.matched
.append((resource
, obj
))
175 def lookup_request(self
, name
, number
=None):
176 for resource
, obj
in self
.matched
:
177 if resource
[0] == name
and (number
is None or
178 resource
[1] == number
):
181 raise ConstraintError("Resource not found: {}:{}".format(name
, number
))
183 def add_platform_command(self
, command
, **signals
):
184 self
.platform_commands
.append((command
, signals
))
186 def get_io_signals(self
):
188 for resource
, obj
in self
.matched
:
189 if isinstance(obj
, Signal
):
192 r
.update(obj
.flatten())
196 def get_sig_constraints(self
):
198 for resource
, obj
in self
.matched
:
201 has_subsignals
= False
203 for element
in resource
[2:]:
204 if isinstance(element
, Subsignal
):
205 has_subsignals
= True
207 top_constraints
.append(element
)
210 for element
in resource
[2:]:
211 if isinstance(element
, Subsignal
):
212 sig
= getattr(obj
, element
.name
)
213 pins
, others
= _separate_pins(top_constraints
+
215 pins
= self
.connector_manager
.resolve_identifiers(pins
)
216 r
.append((sig
, pins
, others
,
217 (name
, number
, element
.name
)))
219 pins
, others
= _separate_pins(top_constraints
)
220 pins
= self
.connector_manager
.resolve_identifiers(pins
)
221 r
.append((obj
, pins
, others
, (name
, number
, None)))
225 def get_platform_commands(self
):
226 return self
.platform_commands
229 class GenericPlatform
:
230 def __init__(self
, device
, io
, connectors
=[], name
=None):
232 self
.constraint_manager
= ConstraintManager(io
, connectors
)
234 name
= self
.__module
__.split(".")[-1]
237 self
.verilog_include_paths
= set()
238 self
.finalized
= False
240 def request(self
, *args
, **kwargs
):
241 return self
.constraint_manager
.request(*args
, **kwargs
)
243 def lookup_request(self
, *args
, **kwargs
):
244 return self
.constraint_manager
.lookup_request(*args
, **kwargs
)
246 def add_period_constraint(self
, clk
, period
):
247 raise NotImplementedError
249 def add_platform_command(self
, *args
, **kwargs
):
250 return self
.constraint_manager
.add_platform_command(*args
, **kwargs
)
252 def add_extension(self
, *args
, **kwargs
):
253 return self
.constraint_manager
.add_extension(*args
, **kwargs
)
255 def finalize(self
, fragment
, *args
, **kwargs
):
257 raise ConstraintError("Already finalized")
258 # if none exists, create a default clock domain and drive it
259 if not fragment
.clock_domains
:
260 if not hasattr(self
, "default_clk_name"):
261 raise NotImplementedError(
262 "No default clock and no clock domain defined")
263 crg
= CRG(self
.request(self
.default_clk_name
))
264 fragment
+= crg
.get_fragment()
266 self
.do_finalize(fragment
, *args
, **kwargs
)
267 self
.finalized
= True
269 def do_finalize(self
, fragment
, *args
, **kwargs
):
270 """overload this and e.g. add_platform_command()'s after the modules
272 if hasattr(self
, "default_clk_period"):
274 self
.add_period_constraint(
275 self
.lookup_request(self
.default_clk_name
),
276 self
.default_clk_period
)
277 except ConstraintError
:
280 def add_source(self
, filename
, language
=None, library
=None):
282 language
= tools
.language_by_filename(filename
)
289 self
.sources
.add((os
.path
.abspath(filename
), language
, library
))
291 def add_sources(self
, path
, *filenames
, language
=None, library
=None):
293 self
.add_source(os
.path
.join(path
, f
), language
, library
)
295 def add_source_dir(self
, path
, recursive
=True, library
=None):
298 for root
, dirs
, files
in os
.walk(path
):
299 for filename
in files
:
300 dir_files
.append(os
.path
.join(root
, filename
))
302 for item
in os
.listdir(path
):
303 if os
.path
.isfile(os
.path
.join(path
, item
)):
304 dir_files
.append(os
.path
.join(path
, item
))
305 for filename
in dir_files
:
306 language
= tools
.language_by_filename(filename
)
307 if language
is not None:
308 self
.add_source(filename
, language
, library
)
310 def add_verilog_include_path(self
, path
):
311 self
.verilog_include_paths
.add(os
.path
.abspath(path
))
313 def resolve_signals(self
, vns
):
314 # resolve signal names in constraints
315 sc
= self
.constraint_manager
.get_sig_constraints()
316 named_sc
= [(vns
.get_name(sig
), pins
, others
, resource
)
317 for sig
, pins
, others
, resource
in sc
]
318 # resolve signal names in platform commands
319 pc
= self
.constraint_manager
.get_platform_commands()
321 for template
, args
in pc
:
322 name_dict
= dict((k
, vns
.get_name(sig
)) for k
, sig
in args
.items())
323 named_pc
.append(template
.format(**name_dict
))
325 return named_sc
, named_pc
327 def get_verilog(self
, fragment
, **kwargs
):
328 return verilog
.convert(
330 self
.constraint_manager
.get_io_signals(),
331 create_clock_domains
=False, **kwargs
)
333 def get_edif(self
, fragment
, cell_library
, vendor
, device
, **kwargs
):
336 self
.constraint_manager
.get_io_signals(),
337 cell_library
, vendor
, device
, **kwargs
)
339 def build(self
, fragment
):
340 raise NotImplementedError("GenericPlatform.build must be overloaded")
342 def create_programmer(self
):
343 raise NotImplementedError