Integrate latest migen changes for lattice/icestorm.

Integrated up to 37db6bb52532b6d1c6bc8b724c2e8c6a38546c2a.
This commit is contained in:
Tim 'mithro' Ansell 2018-12-20 11:31:07 -08:00
parent 1c1c1bd122
commit 53731b792b
2 changed files with 51 additions and 34 deletions

View File

@ -86,15 +86,27 @@ class LatticeiCE40AsyncResetSynchronizer:
class LatticeiCE40TristateImpl(Module): class LatticeiCE40TristateImpl(Module):
def __init__(self, io, o, oe, i): def __init__(self, io, o, oe, i):
nbits, sign = value_bits_sign(io) nbits, sign = value_bits_sign(io)
for bit in range(nbits): if nbits == 1:
# If `io` is an expression like `port[x]`, it is not legal to index further
# into it if it is only 1 bit wide.
self.specials += \ self.specials += \
Instance("SB_IO", Instance("SB_IO",
p_PIN_TYPE=C(0b101001, 6), p_PIN_TYPE=C(0b101001, 6),
io_PACKAGE_PIN=io[bit], io_PACKAGE_PIN=io,
i_OUTPUT_ENABLE=oe, i_OUTPUT_ENABLE=oe,
i_D_OUT_0=o[bit], i_D_OUT_0=o,
o_D_IN_0=i[bit], o_D_IN_0=i,
) )
else:
for bit in range(nbits):
self.specials += \
Instance("SB_IO",
p_PIN_TYPE=C(0b101001, 6),
io_PACKAGE_PIN=io[bit],
i_OUTPUT_ENABLE=oe,
i_D_OUT_0=o[bit],
o_D_IN_0=i[bit],
)
class LatticeiCE40Tristate(Module): class LatticeiCE40Tristate(Module):

View File

@ -12,29 +12,27 @@ from litex.build import tools
from litex.build.lattice import common from litex.build.lattice import common
def _format_constraint(c):
pass
def _format_pcf(signame, pin, others, resname):
return "set_io " + signame + " " + pin + "\n"
def _build_pcf(named_sc, named_pc): def _build_pcf(named_sc, named_pc):
r = "" r = ""
for sig, pins, others, resname in named_sc: for sig, pins, others, resname in named_sc:
if len(pins) > 1: if len(pins) > 1:
for i, p in enumerate(pins): for bit, pin in enumerate(pins):
r += _format_pcf(sig + "[" + str(i) + "]", p, others, resname) r += "set_io {}[{}] {}\n".format(sig, bit, pin)
else: else:
r += _format_pcf(sig, pins[0], others, resname) r += "set_io {} {}\n".format(sig, pins[0])
if named_pc: if named_pc:
r += "\n" + "\n\n".join(named_pc) r += "\n" + "\n\n".join(named_pc)
return r return r
def _build_script(source, build_template, build_name, pnr_pkg_opts, def _build_pre_pack(vns, freq_cstrs):
icetime_pkg_opts, freq_constraint): r = ""
for sig in freq_cstrs:
r += """ctx.addClock("{}", {})\n""".format(vns.get_name(sig), freq_cstrs[sig])
return r
def _build_script(source, build_template, build_name, **kwargs):
if sys.platform in ("win32", "cygwin"): if sys.platform in ("win32", "cygwin"):
script_ext = ".bat" script_ext = ".bat"
build_script_contents = "@echo off\nrem Autogenerated by Migen\n\n" build_script_contents = "@echo off\nrem Autogenerated by Migen\n\n"
@ -47,10 +45,8 @@ def _build_script(source, build_template, build_name, pnr_pkg_opts,
for s in build_template: for s in build_template:
s_fail = s + "{fail_stmt}\n" # Required so Windows scripts fail early. s_fail = s + "{fail_stmt}\n" # Required so Windows scripts fail early.
build_script_contents += s_fail.format(build_name=build_name, build_script_contents += s_fail.format(build_name=build_name,
pnr_pkg_opts=pnr_pkg_opts, fail_stmt=fail_stmt,
icetime_pkg_opts=icetime_pkg_opts, **kwargs)
freq_constraint=freq_constraint,
fail_stmt=fail_stmt)
build_script_file = "build_" + build_name + script_ext build_script_file = "build_" + build_name + script_ext
tools.write_to_file(build_script_file, build_script_contents, tools.write_to_file(build_script_file, build_script_contents,
@ -101,7 +97,7 @@ class LatticeIceStormToolchain:
self.yosys_template = [ self.yosys_template = [
"{read_files}", "{read_files}",
"attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0", "attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0",
"synth_ice40 -top top -blif {build_name}.blif", "synth_ice40 -top {build_name} -blif {build_name}.blif",
] ]
self.build_template = [ self.build_template = [
@ -114,12 +110,12 @@ class LatticeIceStormToolchain:
self.nextpnr_yosys_template = [ self.nextpnr_yosys_template = [
"{read_files}", "{read_files}",
"attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0", "attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0",
"synth_ice40 -top top -json {build_name}.json", "synth_ice40 {synth_opts} -top {build_name} -json {build_name}.json",
] ]
self.nextpnr_build_template = [ self.nextpnr_build_template = [
"yosys -q -l {build_name}.rpt {build_name}.ys", "yosys -q -l {build_name}.rpt {build_name}.ys",
"nextpnr-ice40 {pnr_pkg_opts} --pcf {build_name}.pcf --json {build_name}.json --asc {build_name}.txt --freq {freq_constraint}", "nextpnr-ice40 {pnr_pkg_opts} --pcf {build_name}.pcf --json {build_name}.json --asc {build_name}.txt --pre-pack {build_name}_pre_pack.py",
"icepack {build_name}.txt {build_name}.bin" "icepack {build_name}.txt {build_name}.bin"
] ]
@ -127,7 +123,7 @@ class LatticeIceStormToolchain:
# platform.device should be of the form "ice40-{lp384, hx1k, etc}-{tq144, etc}" # platform.device should be of the form "ice40-{lp384, hx1k, etc}-{tq144, etc}"
def build(self, platform, fragment, build_dir="build", build_name="top", def build(self, platform, fragment, build_dir="build", build_name="top",
toolchain_path=None, use_nextpnr=True, run=True, **kwargs): toolchain_path=None, use_nextpnr=True, synth_opts="", run=True, **kwargs):
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd() cwd = os.getcwd()
os.chdir(build_dir) os.chdir(build_dir)
@ -146,7 +142,8 @@ class LatticeIceStormToolchain:
else: else:
chosen_yosys_template = self.yosys_template chosen_yosys_template = self.yosys_template
ys_contents = "\n".join(_.format(build_name=build_name, ys_contents = "\n".join(_.format(build_name=build_name,
read_files=self.gen_read_files(platform, v_file)) read_files=self.gen_read_files(platform, v_file),
synth_opts=synth_opts)
for _ in chosen_yosys_template) for _ in chosen_yosys_template)
ys_name = build_name + ".ys" ys_name = build_name + ".ys"
@ -161,6 +158,13 @@ class LatticeIceStormToolchain:
pnr_pkg_opts = "-d " + self.get_size_string(series_size) + \ pnr_pkg_opts = "-d " + self.get_size_string(series_size) + \
" -P " + package " -P " + package
icetime_pkg_opts = "-P " + package + " -d " + series_size icetime_pkg_opts = "-P " + package + " -d " + series_size
if use_nextpnr:
tools.write_to_file(build_name + "_pre_pack.py",
_build_pre_pack(v_output.ns, self.freq_constraints))
# icetime can only handle a single global constraint, so we test against the fastest
# clock; though imprecise, if the global design satisfies the fastest clock, we can
# be sure all other constraints are satisfied.
freq_constraint = str(max(self.freq_constraints.values(), freq_constraint = str(max(self.freq_constraints.values(),
default=0.0)) default=0.0))
@ -168,8 +172,12 @@ class LatticeIceStormToolchain:
chosen_build_template = self.nextpnr_build_template chosen_build_template = self.nextpnr_build_template
else: else:
chosen_build_template = self.build_template chosen_build_template = self.build_template
script = _build_script(False, chosen_build_template, build_name, script = _build_script(source=False,
pnr_pkg_opts, icetime_pkg_opts, freq_constraint) build_template=chosen_build_template,
build_name=build_name,
pnr_pkg_opts=pnr_pkg_opts,
icetime_pkg_opts=icetime_pkg_opts,
freq_constraint=freq_constraint)
if run: if run:
_run_script(script) _run_script(script)
@ -190,7 +198,9 @@ class LatticeIceStormToolchain:
"hx1k": ["vq100", "cb132", "tq144"], "hx1k": ["vq100", "cb132", "tq144"],
"lp8k": ["cm81", "cm81:4k", "cm121", "cm121:4k", "cm225", "lp8k": ["cm81", "cm81:4k", "cm121", "cm121:4k", "cm225",
"cm225:4k"], "cm225:4k"],
"hx8k": ["cb132", "cb132:4k", "tq144:4k", "cm225", "ct256"], "hx8k": ["bg121", "bg121:4k", "cb132", "cb132:4k", "cm121",
"cm121:4k", "cm225", "cm225:4k", "cm81", "cm81:4k",
"ct256", "tq144:4k"],
"up3k": ["sg48", "uwg30"], "up3k": ["sg48", "uwg30"],
"up5k": ["sg48", "uwg30"], "up5k": ["sg48", "uwg30"],
} }
@ -219,11 +229,6 @@ class LatticeIceStormToolchain:
filename)) filename))
return "\n".join(read_files) return "\n".join(read_files)
# icetime can only handle a single global constraint. Pending more
# finely-tuned analysis features in arachne-pnr and IceStorm, save
# all the constraints in a dictionary and test against the fastest clk.
# Though imprecise, if the global design satisfies the fastest clock,
# we can be sure all other constraints are satisfied.
def add_period_constraint(self, platform, clk, period): def add_period_constraint(self, platform, clk, period):
new_freq = 1000.0/period new_freq = 1000.0/period