import subprocess
from migen.fhdl.structure import _Fragment
-from mibuild.generic_platform import *
+from mibuild.generic_platform import (Pins, IOStandard, Misc)
from mibuild import tools
-from mibuild.xilinx import common
-def _format_constraint(c):
+def _format_constraint(c, signame, fmt_r):
if isinstance(c, Pins):
- return "set_location_assignment PIN_" + c.identifiers[0]
+ return "set_location_assignment -comment \"{name}\" " \
+ "-to {signame} Pin_{pin}".format(
+ signame=signame,
+ name=fmt_r,
+ pin=c.identifiers[0])
elif isinstance(c, IOStandard):
- return "set_instance_assignment -name IO_STANDARD " + "\"" + c.name + "\""
+ return "set_instance_assignment -name io_standard " \
+ "-comment \"{name}\" \"{std}\" -to {signame}".format(
+ signame=signame,
+ name=fmt_r,
+ std=c.name)
elif isinstance(c, Misc):
- return c.misc
+ if not isinstance(c.misc, str) and len(c.misc) == 2:
+ return "set_instance_assignment -comment \"{name}\" " \
+ "-name {misc[0]} \"{misc[1]}\" -to {signame}".format(
+ signame=signame,
+ name=fmt_r,
+ misc=c.misc)
+ else:
+ return "set_instance_assignment -comment \"{name}\" " \
+ "-name {misc} " \
+ "-to {signame}".format(
+ signame=signame,
+ name=fmt_r,
+ misc=c.misc)
def _format_qsf(signame, pin, others, resname):
- fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)]
- fmt_r = resname[0] + ":" + str(resname[1])
+ fmt_r = "{}:{}".format(*resname[:2])
if resname[2] is not None:
fmt_r += "." + resname[2]
- r = ""
- for c in fmt_c:
- r += c + " -to " + signame + " # " + fmt_r + "\n"
- return r
+
+ fmt_c = [_format_constraint(c, signame, fmt_r) for c in
+ ([Pins(pin)] + others)]
+
+ return '\n'.join(fmt_c)
def _build_qsf(named_sc, named_pc):
- r = ""
+ lines = []
for sig, pins, others, resname in named_sc:
if len(pins) > 1:
for i, p in enumerate(pins):
- r += _format_qsf(sig + "[" + str(i) + "]", p, others, resname)
+ lines.append(
+ _format_qsf("{}[{}]".format(sig, i), p, others, resname))
else:
- r += _format_qsf(sig, pins[0], others, resname)
+ lines.append(_format_qsf(sig, pins[0], others, resname))
+
if named_pc:
- r += "\n" + "\n\n".join(named_pc)
- r += "set_global_assignment -name top_level_entity top\n"
- return r
+ lines.append("")
+ lines.append("\n\n".join(named_pc))
+
+ lines.append("set_global_assignment -name top_level_entity top")
+ return "\n".join(lines)
def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
- qsf_contents = ""
+ lines = []
for filename, language, library in sources:
- # Enforce use of SystemVerilog (Quartus does not support global parameters in Verilog)
+ # Enforce use of SystemVerilog
+ # (Quartus does not support global parameters in Verilog)
if language == "verilog":
language = "systemverilog"
- qsf_contents += "set_global_assignment -name " + language.upper() + "_FILE " + filename + " -library " + library + " \n"
+ lines.append(
+ "set_global_assignment -name {lang}_FILE {path} "
+ "-library {lib}".format(
+ lang=language.upper(),
+ path=filename.replace("\\", "/"),
+ lib=library))
for path in vincpaths:
- qsf_contents += "set_global_assignment -name SEARCH_PATH " + path + "\n"
+ lines.append("set_global_assignment -name SEARCH_PATH {}".format(
+ path.replace("\\", "/")))
- qsf_contents += _build_qsf(named_sc, named_pc)
- qsf_contents += "set_global_assignment -name DEVICE " + device
- tools.write_to_file(build_name + ".qsf", qsf_contents)
+ lines.append(_build_qsf(named_sc, named_pc))
+ lines.append("set_global_assignment -name DEVICE {}".format(device))
+ tools.write_to_file("{}.qsf".format(build_name), "\n".join(lines))
def _run_quartus(build_name, quartus_path):
quartus_asm --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}
quartus_sta {build_name} -c {build_name}
-""".format(build_name=build_name)
+""".format(build_name=build_name) # noqa
build_script_file = "build_" + build_name + ".sh"
- tools.write_to_file(build_script_file, build_script_contents, force_unix=True)
+ tools.write_to_file(build_script_file,
+ build_script_contents,
+ force_unix=True)
- r = subprocess.call(["bash", build_script_file])
- if r != 0:
+ if subprocess.call(["bash", build_script_file]):
raise OSError("Subprocess failed")
class AlteraQuartusToolchain:
def build(self, platform, fragment, build_dir="build", build_name="top",
- quartus_path="/opt/Altera", run=True):
+ quartus_path="/opt/Altera", run=True):
tools.mkdir_noerror(build_dir)
os.chdir(build_dir)
v_file = build_name + ".v"
v_output.write(v_file)
sources = platform.sources | {(v_file, "verilog", "work")}
- _build_files(platform.device, sources, platform.verilog_include_paths, named_sc, named_pc, build_name)
+ _build_files(platform.device,
+ sources,
+ platform.verilog_include_paths,
+ named_sc,
+ named_pc,
+ build_name)
if run:
_run_quartus(build_name, quartus_path)
def add_period_constraint(self, platform, clk, period):
# TODO: handle differential clk
- platform.add_platform_command("""set_global_assignment -name DUTY_CYCLE 50 -section_id {clk}""", clk=clk)
- platform.add_platform_command("""set_global_assignment -name FMAX_REQUIREMENT "{freq} MHz" -section_id {clk}\n""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk)
+ platform.add_platform_command(
+ "set_global_assignment -name duty_cycle 50 -section_id {clk}",
+ clk=clk)
+ platform.add_platform_command(
+ "set_global_assignment -name fmax_requirement \"{freq} MHz\" "
+ "-section_id {clk}".format(freq=(1. / period) * 1000,
+ clk="{clk}"),
+ clk=clk)
import os
import sys
-from migen.fhdl.std import *
-from migen.fhdl.structure import _Fragment
+from migen.fhdl.std import Signal
from migen.genlib.record import Record
from migen.genlib.io import CRG
from migen.fhdl import verilog, edif
for i in identifiers:
self.identifiers += i.split()
+ def __repr__(self):
+ return "{}('{}')".format(self.__class__.__name__,
+ " ".join(self.identifiers))
+
class IOStandard:
def __init__(self, name):
self.name = name
+ def __repr__(self):
+ return "{}('{}')".format(self.__class__.__name__, self.name)
+
class Drive:
def __init__(self, strength):
self.strength = strength
+ def __repr__(self):
+ return "{}('{}')".format(self.__class__.__name__, self.strength)
+
class Misc:
def __init__(self, misc):
self.misc = misc
+ def __repr__(self):
+ return "{}({})".format(self.__class__.__name__, repr(self.misc))
+
class Subsignal:
def __init__(self, name, *constraints):
self.name = name
self.constraints = list(constraints)
+ def __repr__(self):
+ return "{}('{}', {})".format(
+ self.__class__.__name__,
+ self.name,
+ ", ".join([repr(constr) for constr in self.constraints]))
+
class PlatformInfo:
def __init__(self, info):
self.info = info
+ def __repr__(self):
+ return "{}({})".format(self.__class__.__name__, repr(self.info))
+
def _lookup(description, name, number):
for resource in description:
if resource[0] == name and (number is None or resource[1] == number):
return resource
- raise ConstraintError("Resource not found: " + name + ":" + str(number))
+ raise ConstraintError("Resource not found: {}:{}".format(name, number))
def _resource_type(resource):
elif isinstance(element, Subsignal):
if t is None:
t = []
+
assert(isinstance(t, list))
n_bits = None
for c in element.constraints:
if isinstance(c, Pins):
assert(n_bits is None)
n_bits = len(c.identifiers)
+
t.append((element.name, n_bits))
+
return t
pin_list = connector[1]
else:
raise ValueError("Unsupported pin list type {} for connector"
- " {}".format(type(connector[1]), conn_name))
+ " {}".format(type(connector[1]), conn_name))
if conn_name in self.connector_table:
- raise ValueError("Connector specified more than once: "+conn_name)
+ raise ValueError(
+ "Connector specified more than once: {}".format(conn_name))
+
self.connector_table[conn_name] = pin_list
def resolve_identifiers(self, identifiers):
conn, pn = identifier.split(":")
if pn.isdigit():
pn = int(pn)
+
r.append(self.connector_table[conn][pn])
else:
r.append(identifier)
+
return r
pins = c.identifiers
else:
others.append(c)
+
return pins, others
obj = Signal(rt, name_override=resource[0])
else:
obj = Record(rt, name=resource[0])
+
for element in resource[2:]:
if isinstance(element, PlatformInfo):
obj.platform_info = element.info
break
+
self.available.remove(resource)
self.matched.append((resource, obj))
return obj
def lookup_request(self, name, number=None):
for resource, obj in self.matched:
- if resource[0] == name and (number is None or resource[1] == number):
+ if resource[0] == name and (number is None or
+ resource[1] == number):
return obj
- raise ConstraintError("Resource not found: " + name + ":" + str(number))
+
+ raise ConstraintError("Resource not found: {}:{}".format(name, number))
def add_platform_command(self, command, **signals):
self.platform_commands.append((command, signals))
r.add(obj)
else:
r.update(obj.flatten())
+
return r
def get_sig_constraints(self):
has_subsignals = True
else:
top_constraints.append(element)
+
if has_subsignals:
for element in resource[2:]:
if isinstance(element, Subsignal):
sig = getattr(obj, element.name)
- pins, others = _separate_pins(top_constraints + element.constraints)
+ pins, others = _separate_pins(top_constraints +
+ element.constraints)
pins = self.connector_manager.resolve_identifiers(pins)
- r.append((sig, pins, others, (name, number, element.name)))
+ r.append((sig, pins, others,
+ (name, number, element.name)))
else:
pins, others = _separate_pins(top_constraints)
pins = self.connector_manager.resolve_identifiers(pins)
r.append((obj, pins, others, (name, number, None)))
+
return r
def get_platform_commands(self):
# if none exists, create a default clock domain and drive it
if not fragment.clock_domains:
if not hasattr(self, "default_clk_name"):
- raise NotImplementedError("No default clock and no clock domain defined")
+ raise NotImplementedError(
+ "No default clock and no clock domain defined")
crg = CRG(self.request(self.default_clk_name))
fragment += crg.get_fragment()
+
self.do_finalize(fragment, *args, **kwargs)
self.finalized = True
def do_finalize(self, fragment, *args, **kwargs):
- """overload this and e.g. add_platform_command()'s after the modules had their say"""
+ """overload this and e.g. add_platform_command()'s after the modules
+ had their say"""
if hasattr(self, "default_clk_period"):
try:
- self.add_period_constraint(self.lookup_request(self.default_clk_name), self.default_clk_period)
+ self.add_period_constraint(
+ self.lookup_request(self.default_clk_name),
+ self.default_clk_period)
except ConstraintError:
pass
def add_source(self, filename, language=None, library=None):
if language is None:
language = tools.language_by_filename(filename)
+
if language is None:
language = "verilog" # default to Verilog
+
if library is None:
library = "work" # default to work
+
filename = os.path.abspath(filename)
if sys.platform == "win32" or sys.platform == "cygwin":
filename = filename.replace("\\", "/")
def resolve_signals(self, vns):
# resolve signal names in constraints
sc = self.constraint_manager.get_sig_constraints()
- named_sc = [(vns.get_name(sig), pins, others, resource) for sig, pins, others, resource in sc]
+ named_sc = [(vns.get_name(sig), pins, others, resource)
+ for sig, pins, others, resource in sc]
# resolve signal names in platform commands
pc = self.constraint_manager.get_platform_commands()
named_pc = []
for template, args in pc:
name_dict = dict((k, vns.get_name(sig)) for k, sig in args.items())
named_pc.append(template.format(**name_dict))
+
return named_sc, named_pc
def get_verilog(self, fragment, **kwargs):
- return verilog.convert(fragment, self.constraint_manager.get_io_signals(), create_clock_domains=False, **kwargs)
+ return verilog.convert(
+ fragment,
+ self.constraint_manager.get_io_signals(),
+ create_clock_domains=False, **kwargs)
def get_edif(self, fragment, cell_library, vendor, device, **kwargs):
- return edif.convert(fragment, self.constraint_manager.get_io_signals(), cell_library, vendor, device, **kwargs)
+ return edif.convert(
+ fragment,
+ self.constraint_manager.get_io_signals(),
+ cell_library, vendor, device, **kwargs)
def build(self, fragment):
raise NotImplementedError("GenericPlatform.build must be overloaded")
def build_cmdline(self, *args, **kwargs):
arg = sys.argv[1:]
if len(arg) % 2:
- print("Missing value for option: "+sys.argv[-1])
+ print("Missing value for option: {}".format(sys.argv[-1]))
sys.exit(1)
- argdict = dict((k, autotype(v)) for k, v in zip(*[iter(arg)]*2))
+
+ argdict = dict((k, autotype(v)) for k, v in zip(*[iter(arg)] * 2))
kwargs.update(argdict)
self.build(*args, **kwargs)