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: ...@@ -76,15 +76,18 @@ class XilinxMultiReg:
class XilinxAsyncResetSynchronizerImpl(Module): class XilinxAsyncResetSynchronizerImpl(Module):
def __init__(self, cd, async_reset): 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 += [ self.specials += [
Instance("FDPE", p_INIT=1, i_D=0, i_PRE=async_reset, Instance("FDPE", p_INIT=1, i_D=0, i_PRE=async_reset,
i_CE=1, i_C=cd.clk, o_Q=rst1), i_CE=1, i_C=cd.clk, o_Q=rst_meta, attr={"async_reg"}),
Instance("FDPE", p_INIT=1, i_D=rst1, i_PRE=async_reset, Instance("FDPE", p_INIT=1, i_D=rst_meta, i_PRE=async_reset,
i_CE=1, i_C=cd.clk, o_Q=cd.rst) i_CE=1, i_C=cd.clk, o_Q=cd.rst, attr={"async_reg"})
] ]
rst1.attr.add("async_reg") async_reset.attr.add("ars_false_path")
cd.rst.attr.add("async_reg") rst_meta.attr.add("ars_meta")
class XilinxAsyncResetSynchronizer: class XilinxAsyncResetSynchronizer:
......
...@@ -129,6 +129,8 @@ class XilinxISEToolchain: ...@@ -129,6 +129,8 @@ class XilinxISEToolchain:
"keep": ("keep", "true"), "keep": ("keep", "true"),
"no_retiming": ("register_balancing", "no"), "no_retiming": ("register_balancing", "no"),
"async_reg": None, "async_reg": None,
"ars_false_path": None,
"ars_meta": None,
"no_shreg_extract": ("shreg_extract", "no") "no_shreg_extract": ("shreg_extract", "no")
} }
......
...@@ -75,6 +75,8 @@ class XilinxVivadoToolchain: ...@@ -75,6 +75,8 @@ class XilinxVivadoToolchain:
"keep": ("dont_touch", "true"), "keep": ("dont_touch", "true"),
"no_retiming": ("dont_touch", "true"), "no_retiming": ("dont_touch", "true"),
"async_reg": ("async_reg", "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 "no_shreg_extract": None
} }
...@@ -88,6 +90,10 @@ class XilinxVivadoToolchain: ...@@ -88,6 +90,10 @@ class XilinxVivadoToolchain:
def _build_batch(self, platform, sources, build_name): def _build_batch(self, platform, sources, build_name):
tcl = [] 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: for filename, language, library in sources:
filename_tcl = "{" + filename + "}" filename_tcl = "{" + filename + "}"
tcl.append("add_files " + filename_tcl) tcl.append("add_files " + filename_tcl)
...@@ -143,6 +149,20 @@ class XilinxVivadoToolchain: ...@@ -143,6 +149,20 @@ class XilinxVivadoToolchain:
del self.clocks del self.clocks
del self.false_paths 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", def build(self, platform, fragment, build_dir="build", build_name="top",
toolchain_path="/opt/Xilinx/Vivado", source=True, run=True): toolchain_path="/opt/Xilinx/Vivado", source=True, run=True):
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
...@@ -153,6 +173,7 @@ class XilinxVivadoToolchain: ...@@ -153,6 +173,7 @@ class XilinxVivadoToolchain:
fragment = fragment.get_fragment() fragment = fragment.get_fragment()
platform.finalize(fragment) platform.finalize(fragment)
self._convert_clocks(platform) self._convert_clocks(platform)
self._constrain(platform)
v_output = platform.get_verilog(fragment) v_output = platform.get_verilog(fragment)
named_sc, named_pc = platform.resolve_signals(v_output.ns) named_sc, named_pc = platform.resolve_signals(v_output.ns)
v_file = build_name + ".v" v_file = build_name + ".v"
......
...@@ -101,7 +101,8 @@ class Instance(Special): ...@@ -101,7 +101,8 @@ class Instance(Special):
class PreformattedParam(str): class PreformattedParam(str):
pass 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) Special.__init__(self)
self.of = of self.of = of
if name: if name:
...@@ -110,6 +111,9 @@ class Instance(Special): ...@@ -110,6 +111,9 @@ class Instance(Special):
self.name_override = of self.name_override = of
self.items = list(items) self.items = list(items)
self.synthesis_directive = synthesis_directive self.synthesis_directive = synthesis_directive
if attr is None:
attr = set()
self.attr = attr
for k, v in sorted(kwargs.items(), key=itemgetter(0)): for k, v in sorted(kwargs.items(), key=itemgetter(0)):
try: try:
item_type, item_name = k.split("_", maxsplit=1) item_type, item_name = k.split("_", maxsplit=1)
......
...@@ -165,10 +165,10 @@ def _list_comb_wires(f): ...@@ -165,10 +165,10 @@ def _list_comb_wires(f):
r |= g[0] r |= g[0]
return r return r
def _printattr(sig, attr_translate): def _printattr(attr, attr_translate):
r = "" r = ""
firsta = True firsta = True
for attr in sorted(sig.attr, for attr in sorted(attr,
key=lambda x: ("", x) if isinstance(x, str) else x): key=lambda x: ("", x) if isinstance(x, str) else x):
if isinstance(attr, tuple): if isinstance(attr, tuple):
# platform-dependent attribute # platform-dependent attribute
...@@ -201,7 +201,7 @@ def _printheader(f, ios, name, ns, attr_translate, ...@@ -201,7 +201,7 @@ def _printheader(f, ios, name, ns, attr_translate,
if not firstp: if not firstp:
r += ",\n" r += ",\n"
firstp = False firstp = False
attr = _printattr(sig, attr_translate) attr = _printattr(sig.attr, attr_translate)
if attr: if attr:
r += "\t" + attr r += "\t" + attr
if sig in inouts: if sig in inouts:
...@@ -215,7 +215,7 @@ def _printheader(f, ios, name, ns, attr_translate, ...@@ -215,7 +215,7 @@ def _printheader(f, ios, name, ns, attr_translate,
r += "\tinput " + _printsig(ns, sig) r += "\tinput " + _printsig(ns, sig)
r += "\n);\n\n" r += "\n);\n\n"
for sig in sorted(sigs - ios, key=lambda x: x.duid): for sig in sorted(sigs - ios, key=lambda x: x.duid):
attr = _printattr(sig, attr_translate) attr = _printattr(sig.attr, attr_translate)
if attr: if attr:
r += attr + " " r += attr + " "
if sig in wires: if sig in wires:
...@@ -291,9 +291,13 @@ def _printsync(f, ns): ...@@ -291,9 +291,13 @@ def _printsync(f, ns):
return r return r
def _printspecials(overrides, specials, ns, add_data_file): def _printspecials(overrides, specials, ns, add_data_file, attr_translate):
r = "" r = ""
for special in sorted(specials, key=lambda x: x.duid): 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) pr = call_special_classmethod(overrides, special, "emit_verilog", ns, add_data_file)
if pr is None: if pr is None:
raise NotImplementedError("Special " + str(special) + " failed to implement emit_verilog") raise NotImplementedError("Special " + str(special) + " failed to implement emit_verilog")
...@@ -353,7 +357,8 @@ def convert(f, ios=None, name="top", ...@@ -353,7 +357,8 @@ def convert(f, ios=None, name="top",
dummy_signal=not asic_syntax, dummy_signal=not asic_syntax,
blocking_assign=asic_syntax) blocking_assign=asic_syntax)
src += _printsync(f, ns) 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" src += "endmodule\n"
r.set_main_source(src) 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