Commit 9165fe28 authored by Robert Jordens's avatar Robert Jordens
Browse files

Merge branch 'asr-false-path'

* asr-false-path:
  vivado: create ars_meta, ars_false_path properties
  verilog: add space before instance attrs
  fhdl: add attr to Instances
  vivado/AsyncResetSync: use asr_async_reg property
  vivado: (fix) copy async reg to driving cells
  vivado/AsyncResetSync: only wrap async_reset input when necessary
  vivado: fix abbreviation
  vivado: copy async_reg from wires to cell inputs
  vivado/AsyncResetSync: constrain metastable path, fix false_path
  vivado: save project
  xilinx: false_path the first register in AsyncResetSynchronizer
  vivado: create project explicitly
parents 00c6f582 171860af
......@@ -76,15 +76,18 @@ class XilinxMultiReg:
class XilinxAsyncResetSynchronizerImpl(Module):
def __init__(self, cd, async_reset):
rst1 = Signal()
if not hasattr(async_reset, "attr"):
i, async_reset = async_reset, Signal()
self.comb += async_reset.eq(i)
rst_meta = Signal()
self.specials += [
Instance("FDPE", p_INIT=1, i_D=0, i_PRE=async_reset,
i_CE=1, i_C=cd.clk, o_Q=rst1),
Instance("FDPE", p_INIT=1, i_D=rst1, i_PRE=async_reset,
i_CE=1, i_C=cd.clk, o_Q=cd.rst)
i_CE=1, i_C=cd.clk, o_Q=rst_meta, attr={"async_reg"}),
Instance("FDPE", p_INIT=1, i_D=rst_meta, i_PRE=async_reset,
i_CE=1, i_C=cd.clk, o_Q=cd.rst, attr={"async_reg"})
]
rst1.attr.add("async_reg")
cd.rst.attr.add("async_reg")
async_reset.attr.add("ars_false_path")
rst_meta.attr.add("ars_meta")
class XilinxAsyncResetSynchronizer:
......
......@@ -129,6 +129,8 @@ class XilinxISEToolchain:
"keep": ("keep", "true"),
"no_retiming": ("register_balancing", "no"),
"async_reg": None,
"ars_false_path": None,
"ars_meta": None,
"no_shreg_extract": ("shreg_extract", "no")
}
......
......@@ -75,6 +75,8 @@ class XilinxVivadoToolchain:
"keep": ("dont_touch", "true"),
"no_retiming": ("dont_touch", "true"),
"async_reg": ("async_reg", "true"),
"ars_meta": ("ars_meta", "true"), # user-defined attribute
"ars_false_path": ("ars_false_path", "true"), # user-defined attribute
"no_shreg_extract": None
}
......@@ -88,6 +90,10 @@ class XilinxVivadoToolchain:
def _build_batch(self, platform, sources, build_name):
tcl = []
tcl.append("create_project -force -part {} {}".format(
platform.device, build_name))
tcl.append("create_property ars_meta net")
tcl.append("create_property ars_false_path net")
for filename, language, library in sources:
filename_tcl = "{" + filename + "}"
tcl.append("add_files " + filename_tcl)
......@@ -143,6 +149,20 @@ class XilinxVivadoToolchain:
del self.clocks
del self.false_paths
def _constrain(self, platform):
# The asychronous reset input to the AsyncResetSynchronizer is a false
# path
platform.add_platform_command(
"set_false_path -quiet -through "
"[get_nets -hier -filter {{ars_false_path==true}}]"
)
# clock_period-2ns to resolve metastability on the wire between the
# AsyncResetSynchronizer FFs
platform.add_platform_command(
"set_max_delay 2 -quiet -through "
"[get_nets -hier -filter {{ars_meta==true}}]"
)
def build(self, platform, fragment, build_dir="build", build_name="top",
toolchain_path="/opt/Xilinx/Vivado", source=True, run=True):
os.makedirs(build_dir, exist_ok=True)
......@@ -153,6 +173,7 @@ class XilinxVivadoToolchain:
fragment = fragment.get_fragment()
platform.finalize(fragment)
self._convert_clocks(platform)
self._constrain(platform)
v_output = platform.get_verilog(fragment)
named_sc, named_pc = platform.resolve_signals(v_output.ns)
v_file = build_name + ".v"
......
......@@ -101,7 +101,8 @@ class Instance(Special):
class PreformattedParam(str):
pass
def __init__(self, of, *items, name="", synthesis_directive=None, **kwargs):
def __init__(self, of, *items, name="", synthesis_directive=None,
attr=None, **kwargs):
Special.__init__(self)
self.of = of
if name:
......@@ -110,6 +111,9 @@ class Instance(Special):
self.name_override = of
self.items = list(items)
self.synthesis_directive = synthesis_directive
if attr is None:
attr = set()
self.attr = attr
for k, v in sorted(kwargs.items(), key=itemgetter(0)):
try:
item_type, item_name = k.split("_", maxsplit=1)
......
......@@ -165,10 +165,10 @@ def _list_comb_wires(f):
r |= g[0]
return r
def _printattr(sig, attr_translate):
def _printattr(attr, attr_translate):
r = ""
firsta = True
for attr in sorted(sig.attr,
for attr in sorted(attr,
key=lambda x: ("", x) if isinstance(x, str) else x):
if isinstance(attr, tuple):
# platform-dependent attribute
......@@ -201,7 +201,7 @@ def _printheader(f, ios, name, ns, attr_translate,
if not firstp:
r += ",\n"
firstp = False
attr = _printattr(sig, attr_translate)
attr = _printattr(sig.attr, attr_translate)
if attr:
r += "\t" + attr
if sig in inouts:
......@@ -215,7 +215,7 @@ def _printheader(f, ios, name, ns, attr_translate,
r += "\tinput " + _printsig(ns, sig)
r += "\n);\n\n"
for sig in sorted(sigs - ios, key=lambda x: x.duid):
attr = _printattr(sig, attr_translate)
attr = _printattr(sig.attr, attr_translate)
if attr:
r += attr + " "
if sig in wires:
......@@ -291,9 +291,13 @@ def _printsync(f, ns):
return r
def _printspecials(overrides, specials, ns, add_data_file):
def _printspecials(overrides, specials, ns, add_data_file, attr_translate):
r = ""
for special in sorted(specials, key=lambda x: x.duid):
if hasattr(special, "attr"):
attr = _printattr(special.attr, attr_translate)
if attr:
r += attr + " "
pr = call_special_classmethod(overrides, special, "emit_verilog", ns, add_data_file)
if pr is None:
raise NotImplementedError("Special " + str(special) + " failed to implement emit_verilog")
......@@ -353,7 +357,8 @@ def convert(f, ios=None, name="top",
dummy_signal=not asic_syntax,
blocking_assign=asic_syntax)
src += _printsync(f, ns)
src += _printspecials(special_overrides, f.specials - lowered_specials, ns, r.add_data_file)
src += _printspecials(special_overrides, f.specials - lowered_specials,
ns, r.add_data_file, attr_translate)
src += "endmodule\n"
r.set_main_source(src)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment