Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/migen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2274a75b7104
Choose a base ref
...
head repository: m-labs/migen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 109f2dd1ac1d
Choose a head ref
  • 20 commits
  • 7 files changed
  • 1 contributor

Commits on Nov 13, 2017

  1. Copy the full SHA
    6767966 View commit details
  2. Copy the full SHA
    c09edd4 View commit details
  3. Copy the full SHA
    2e5bf6f View commit details
  4. Copy the full SHA
    3f16323 View commit details
  5. Copy the full SHA
    8f18c28 View commit details
  6. Copy the full SHA
    3336ade View commit details
  7. lattice: PEP8

    cr1901 authored and sbourdeauducq committed Nov 13, 2017
    Copy the full SHA
    87bba69 View commit details
  8. Copy the full SHA
    ccc12d3 View commit details
  9. Copy the full SHA
    4811212 View commit details
  10. Copy the full SHA
    e7cb96f View commit details
  11. Copy the full SHA
    763994b View commit details
  12. lattice/icestorm: Improve comments.

    cr1901 authored and sbourdeauducq committed Nov 13, 2017
    Copy the full SHA
    7c95ac3 View commit details
  13. Copy the full SHA
    ca8d681 View commit details
  14. Copy the full SHA
    ed934f2 View commit details
  15. Copy the full SHA
    047a211 View commit details
  16. Copy the full SHA
    64d0aa6 View commit details
  17. Copy the full SHA
    3ce9d11 View commit details
  18. lattice/icestorm: PEP8.

    cr1901 authored and sbourdeauducq committed Nov 13, 2017
    Copy the full SHA
    b96cba7 View commit details
  19. Copy the full SHA
    a12c771 View commit details
  20. Copy the full SHA
    109f2dd View commit details
72 changes: 57 additions & 15 deletions migen/build/lattice/common.py
Original file line number Diff line number Diff line change
@@ -4,38 +4,80 @@
from migen.genlib.resetsync import AsyncResetSynchronizer


class LatticeAsyncResetSynchronizerImpl(Module):
class DiamondAsyncResetSynchronizerImpl(Module):
def __init__(self, cd, async_reset):
rst1 = Signal()
self.specials += [
Instance("FD1S3BX", i_D=0, i_PD=async_reset,
i_CK=cd.clk, o_Q=rst1),
i_CK=cd.clk, o_Q=rst1),
Instance("FD1S3BX", i_D=rst1, i_PD=async_reset,
i_CK=cd.clk, o_Q=cd.rst)
i_CK=cd.clk, o_Q=cd.rst)
]


class LatticeAsyncResetSynchronizer:
class DiamondAsyncResetSynchronizer:
@staticmethod
def lower(dr):
return LatticeAsyncResetSynchronizerImpl(dr.cd, dr.async_reset)
return DiamondAsyncResetSynchronizerImpl(dr.cd, dr.async_reset)


class LatticeDDROutputImpl(Module):
class DiamondDDROutputImpl(Module):
def __init__(self, i1, i2, o, clk):
self.specials += Instance("ODDRXD1",
synthesis_directive="ODDRAPPS=\"SCLK_ALIGNED\"",
i_SCLK=clk,
i_DA=i1, i_DB=i2, o_Q=o,
)
synthesis_directive="ODDRAPPS=\"SCLK_ALIGNED\"",
i_SCLK=clk,
i_DA=i1, i_DB=i2, o_Q=o)


class LatticeDDROutput:
class DiamondDDROutput:
@staticmethod
def lower(dr):
return LatticeDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk)
return DiamondDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk)

lattice_special_overrides = {
AsyncResetSynchronizer: LatticeAsyncResetSynchronizer,
DDROutput: LatticeDDROutput
diamond_special_overrides = {
AsyncResetSynchronizer: DiamondAsyncResetSynchronizer,
DDROutput: DiamondDDROutput
}


class IcestormAsyncResetSynchronizerImpl(Module):
def __init__(self, cd, async_reset):
rst1 = Signal()
self.specials += [
Instance("SB_DFFS", i_D=0, i_S=async_reset,
i_C=cd.clk, o_Q=rst1),
Instance("SB_DFFS", i_D=rst1, i_S=async_reset,
i_C=cd.clk, o_Q=cd.rst)
]


class IcestormAsyncResetSynchronizer:
@staticmethod
def lower(dr):
return IcestormAsyncResetSynchronizerImpl(dr.cd, dr.async_reset)


class IcestormDifferentialOutputImpl(Module):
def __init__(self, i, o_p, o_n):
self.specials += Instance("SB_IO",
p_PIN_TYPE=C(0b011000, 6),
p_IO_STANDARD="SB_LVCMOS",
io_PACKAGE_PIN=o_p,
i_D_OUT_0=i)

self.specials += Instance("SB_IO",
p_PIN_TYPE=C(0b011000, 6),
p_IO_STANDARD="SB_LVCMOS",
io_PACKAGE_PIN=o_n,
i_D_OUT_0=~i)


class IcestormDifferentialOutput:
@staticmethod
def lower(dr):
return IcestormDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n)

icestorm_special_overrides = {
AsyncResetSynchronizer: IcestormAsyncResetSynchronizer,
DifferentialOutput: IcestormDifferentialOutput
}
5 changes: 5 additions & 0 deletions migen/build/lattice/diamond.py
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
import shutil

from migen.fhdl.structure import _Fragment
from migen.fhdl.verilog import DummyAttrTranslate

from migen.build.generic_platform import *
from migen.build import tools
@@ -77,6 +78,10 @@ def _run_diamond(build_name, source, ver=None):


class LatticeDiamondToolchain:
attr_translate = DummyAttrTranslate()

special_overrides = common.diamond_special_overrides

def build(self, platform, fragment, build_dir="build", build_name="top",
toolchain_path="/opt/Diamond", run=True):
os.makedirs(build_dir, exist_ok=True)
155 changes: 102 additions & 53 deletions migen/build/lattice/icestorm.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This file is Copyright (c) 2016 William D. Jones <thor0505@comcast.net>
# This file is Copyright (c) 2016-2017 William D. Jones <thor0505@comcast.net>
# License: BSD

import os
@@ -9,6 +9,7 @@

from migen.build.generic_platform import *
from migen.build import tools
from migen.build.lattice import common


def _format_constraint(c):
@@ -32,46 +33,27 @@ def _build_pcf(named_sc, named_pc):
return r


def _build_yosys(device, sources, vincpaths, build_name):
ys_contents = ""
incflags = ""
for path in vincpaths:
incflags += " -I" + path
for filename, language, library in sources:
ys_contents += "read_{}{} {}\n".format(language, incflags, filename)

ys_contents += """synth_ice40 -top top -blif {build_name}.blif""".format(
build_name=build_name)

ys_name = build_name + ".ys"
tools.write_to_file(ys_name, ys_contents)


def _run_icestorm(build_name, source, yosys_opt, pnr_opt,
icetime_opt, icepack_opt):
def _run_icestorm(source, build_template, build_name, pnr_pkg_opts,
icetime_pkg_opts, icetime_constraint):
if sys.platform == "win32" or sys.platform == "cygwin":
source_cmd = "call "
script_ext = ".bat"
shell = ["cmd", "/c"]
build_script_contents = "@echo off\nrem Autogenerated by Migen\n"
build_script_contents = "@echo off\nrem Autogenerated by Migen\n\n"
fail_stmt = " || exit /b"
else:
source_cmd = "source "
script_ext = ".sh"
shell = ["bash"]
build_script_contents = "# Autogenerated by Migen\nset -e\n"
build_script_contents = "# Autogenerated by Migen\nset -e\n\n"
fail_stmt = ""

build_script_contents += """
yosys {yosys_opt} -l {build_name}.rpt {build_name}.ys{fail_stmt}
arachne-pnr {pnr_opt} -p {build_name}.pcf {build_name}.blif -o {build_name}.txt{fail_stmt}
icetime {icetime_opt} -t -p {build_name}.pcf -r {build_name}.tim {build_name}.txt{fail_stmt}
icepack {icepack_opt} {build_name}.txt {build_name}.bin{fail_stmt}
"""
build_script_contents = build_script_contents.format(
build_name=build_name,
yosys_opt=yosys_opt, pnr_opt=pnr_opt, icepack_opt=icepack_opt,
icetime_opt=icetime_opt, fail_stmt=fail_stmt)
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,
icetime_constraint=icetime_constraint,
fail_stmt=fail_stmt)

build_script_file = "build_" + build_name + script_ext
tools.write_to_file(build_script_file, build_script_contents,
force_unix=False)
@@ -82,14 +64,47 @@ def _run_icestorm(build_name, source, yosys_opt, pnr_opt,


class LatticeIceStormToolchain:
attr_translate = {
"keep": ("keep", "true"),
"no_retiming": None, # yosys can do retiming via the (non-default)
# "-retime" option to "synth_ice40", but
# yosys does not check for an equivalent
# constraint to prevent retiming on signals.
"async_reg": None, # yosys has no equivalent, and arachne-pnr
# wouldn't take advantage of it anyway.

# While custom attributes are supported in yosys, neither
# arachne-pnr nor icetime currently can take advantage of them
# to add fine-grained timing constraints.
"mr_ff": None, # user-defined attribute
"mr_false_path": None, # user-defined attribute
"ars_ff1": None, # user-defined attribute
"ars_ff2": None, # user-defined attribute
"ars_false_path": None, # user-defined attribute

# ice40 does not have a shift register primitive.
"no_shreg_extract": None
}

special_overrides = common.icestorm_special_overrides

def __init__(self):
self.yosys_opt = "-q"
self.pnr_opt = "-q"
self.icetime_opt = ""
self.icepack_opt = ""
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",
]

self.build_template = [
"yosys -q -l {build_name}.rpt {build_name}.ys",
"arachne-pnr -q {pnr_pkg_opts} -p {build_name}.pcf {build_name}.blif -o {build_name}.txt",
"icetime {icetime_pkg_opts} -c {icetime_constraint} -t -p {build_name}.pcf -r {build_name}.tim {build_name}.txt",
"icepack {build_name}.txt {build_name}.bin"
]

self.freq_constraints = dict()

# platform.device should be of the form "ice40-{1k,8k}-{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",
run=True):
os.makedirs(build_dir, exist_ok=True)
@@ -104,35 +119,69 @@ def build(self, platform, fragment, build_dir="build", build_name="top",
named_sc, named_pc = platform.resolve_signals(v_output.ns)
v_file = build_name + ".v"
v_output.write(v_file)
sources = platform.sources | {(v_file, "verilog", "work")}
_build_yosys(platform.device, sources, platform.verilog_include_paths,
build_name)

ys_contents = "\n".join(_.format(build_name=build_name,
read_files=self.gen_read_files(platform, v_file))
for _ in self.yosys_template)

ys_name = build_name + ".ys"
tools.write_to_file(ys_name, ys_contents)

tools.write_to_file(build_name + ".pcf",
_build_pcf(named_sc, named_pc))
if run:
(family, size, package) = self.parse_device_string(platform.device)
pnr_opt = self.pnr_opt + " -d " + size + " -P " + package
# TODO: PNR will probably eventually support LP devices.
icetime_opt = self.icetime_opt + " -P " + package + \
" -d " + "hx" + size + " -c " + \
str(max(self.freq_constraints.values(), default=0.0))
_run_icestorm(build_name, False, self.yosys_opt, pnr_opt,
icetime_opt, self.icepack_opt)
(family, series_size, package) = self.parse_device_string(platform.device)
pnr_pkg_opts = "-d " + self.get_size_string(series_size) + \
" -P " + package
icetime_pkg_opts = "-P " + package + " -d " + series_size
icetime_constraint = str(max(self.freq_constraints.values(),
default=0.0))

_run_icestorm(False, self.build_template, build_name, pnr_pkg_opts,
icetime_pkg_opts, icetime_constraint)

os.chdir(cwd)

return v_output.ns

def parse_device_string(self, device_str):
(family, size, package) = device_str.split("-")
# Arachne only understands packages based on the device size, but
# LP for a given size supports packages that HX for the same size
# doesn't and vice versa; we need to know the device series due to
# icetime.
valid_packages = {
"lp384": ["qn32", "cm36", "cm49"],
"lp1k": ["swg16tr", "cm36", "cm49", "cm81", "cb81", "qn84",
"cm121", "cb121"],
"hx1k": ["vq100", "cb132", "tq144"],
"lp8k": ["cm81", "cm81:4k", "cm121", "cm121:4k", "cm225",
"cm225:4k"],
"hx8k": ["cb132", "cb132:4k", "tq144:4k", "cm225", "ct256"],
}

(family, series_size, package) = device_str.split("-")
if family not in ["ice40"]:
raise ValueError("Unknown device family")
if size not in ["1k", "8k"]:
raise ValueError("Invalid device size")
if package not in ["tq144", "ct256", "vq100"]:
if series_size not in ["lp384", "lp1k", "hx1k", "lp8k", "hx8k"]:
raise ValueError("Invalid device series/size")
if package not in valid_packages[series_size]:
raise ValueError("Invalid device package")
return (family, size, package)
return (family, series_size, package)

def get_size_string(self, series_size_str):
return series_size_str[2:]

def gen_read_files(self, platform, main):
sources = platform.sources | {(main, "verilog", "work")}
incflags = ""
read_files = list()
for path in platform.verilog_include_paths:
incflags += " -I" + path
for filename, language, library in sources:
read_files.append("read_{}{} {}".format(language,
incflags,
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
7 changes: 5 additions & 2 deletions migen/build/lattice/platform.py
Original file line number Diff line number Diff line change
@@ -16,9 +16,12 @@ def __init__(self, *args, toolchain="diamond", **kwargs):
raise ValueError("Unknown toolchain")

def get_verilog(self, *args, special_overrides=dict(), **kwargs):
so = dict(common.lattice_special_overrides)
so = dict() # No common overrides between ECP and ice40.
so.update(self.toolchain.special_overrides)
so.update(special_overrides)
return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs)
return GenericPlatform.get_verilog(self, *args, special_overrides=so,
attr_translate=self.toolchain.attr_translate,
**kwargs)

def build(self, *args, **kwargs):
return self.toolchain.build(self, *args, **kwargs)
4 changes: 2 additions & 2 deletions migen/build/platforms/ice40_hx1k_blink_evn.py
Original file line number Diff line number Diff line change
@@ -23,8 +23,8 @@ class Platform(LatticePlatform):
default_clk_period = 303.0303

def __init__(self):
LatticePlatform.__init__(self, "ice40-1k-vq100", _io,
toolchain="icestorm")
LatticePlatform.__init__(self, "ice40-hx1k-vq100", _io,
toolchain="icestorm")

def create_programmer(self, iceburn_path="./iCEburn.py"):
return IceBurnProgrammer(iceburn_path)
4 changes: 2 additions & 2 deletions migen/build/platforms/ice40_hx8k_b_evn.py
Original file line number Diff line number Diff line change
@@ -33,8 +33,8 @@ class Platform(LatticePlatform):
default_clk_period = 83.333

def __init__(self):
LatticePlatform.__init__(self, "ice40-8k-ct256", _io,
toolchain="icestorm")
LatticePlatform.__init__(self, "ice40-hx8k-ct256", _io,
toolchain="icestorm")

def create_programmer(self):
return IceStormProgrammer()
4 changes: 2 additions & 2 deletions migen/build/platforms/icestick.py
Original file line number Diff line number Diff line change
@@ -50,8 +50,8 @@ class Platform(LatticePlatform):
default_clk_period = 83.333

def __init__(self):
LatticePlatform.__init__(self, "ice40-1k-tq144", _io, _connectors,
toolchain="icestorm")
LatticePlatform.__init__(self, "ice40-hx1k-tq144", _io, _connectors,
toolchain="icestorm")

def create_programmer(self):
return IceStormProgrammer()