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):
def __init__(self, io, o, oe, i):
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 += \
Instance("SB_IO",
p_PIN_TYPE=C(0b101001, 6),
io_PACKAGE_PIN=io[bit],
io_PACKAGE_PIN=io,
i_OUTPUT_ENABLE=oe,
i_D_OUT_0=o[bit],
o_D_IN_0=i[bit],
i_D_OUT_0=o,
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):

View File

@ -12,29 +12,27 @@ from litex.build import tools
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):
r = ""
for sig, pins, others, resname in named_sc:
if len(pins) > 1:
for i, p in enumerate(pins):
r += _format_pcf(sig + "[" + str(i) + "]", p, others, resname)
for bit, pin in enumerate(pins):
r += "set_io {}[{}] {}\n".format(sig, bit, pin)
else:
r += _format_pcf(sig, pins[0], others, resname)
r += "set_io {} {}\n".format(sig, pins[0])
if named_pc:
r += "\n" + "\n\n".join(named_pc)
return r
def _build_script(source, build_template, build_name, pnr_pkg_opts,
icetime_pkg_opts, freq_constraint):
def _build_pre_pack(vns, freq_cstrs):
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"):
script_ext = ".bat"
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:
s_fail = s + "{fail_stmt}\n" # Required so Windows scripts fail early.
build_script_contents += s_fail.format(build_name=build_name,
pnr_pkg_opts=pnr_pkg_opts,
icetime_pkg_opts=icetime_pkg_opts,
freq_constraint=freq_constraint,
fail_stmt=fail_stmt)
fail_stmt=fail_stmt,
**kwargs)
build_script_file = "build_" + build_name + script_ext
tools.write_to_file(build_script_file, build_script_contents,
@ -101,7 +97,7 @@ class LatticeIceStormToolchain:
self.yosys_template = [
"{read_files}",
"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 = [
@ -114,12 +110,12 @@ class LatticeIceStormToolchain:
self.nextpnr_yosys_template = [
"{read_files}",
"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 = [
"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"
]
@ -127,7 +123,7 @@ class LatticeIceStormToolchain:
# platform.device should be of the form "ice40-{lp384, hx1k, etc}-{tq144, etc}"
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)
cwd = os.getcwd()
os.chdir(build_dir)
@ -146,7 +142,8 @@ class LatticeIceStormToolchain:
else:
chosen_yosys_template = self.yosys_template
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)
ys_name = build_name + ".ys"
@ -161,6 +158,13 @@ class LatticeIceStormToolchain:
pnr_pkg_opts = "-d " + self.get_size_string(series_size) + \
" -P " + package
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(),
default=0.0))
@ -168,8 +172,12 @@ class LatticeIceStormToolchain:
chosen_build_template = self.nextpnr_build_template
else:
chosen_build_template = self.build_template
script = _build_script(False, chosen_build_template, build_name,
pnr_pkg_opts, icetime_pkg_opts, freq_constraint)
script = _build_script(source=False,
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:
_run_script(script)
@ -190,7 +198,9 @@ class LatticeIceStormToolchain:
"hx1k": ["vq100", "cb132", "tq144"],
"lp8k": ["cm81", "cm81:4k", "cm121", "cm121:4k", "cm225",
"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"],
"up5k": ["sg48", "uwg30"],
}
@ -219,11 +229,6 @@ class LatticeIceStormToolchain:
filename))
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):
new_freq = 1000.0/period