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/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7342662bee80
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8c30147e39cc
Choose a head ref
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on Sep 11, 2019

  1. back: return name map from convert_fragment().

    whitequark committed Sep 11, 2019
    Copy the full SHA
    d1779bd View commit details
  2. build.plat,vendor: allow clock constraints on arbitrary signals.

    Currently only done for Synopsys based toolchains (i.e. not nextpnr).
    
    Refs #88.
    whitequark committed Sep 11, 2019
    Copy the full SHA
    8c30147 View commit details
Showing with 33 additions and 15 deletions.
  1. +19 −8 nmigen/back/rtlil.py
  2. +2 −2 nmigen/back/verilog.py
  3. +8 −1 nmigen/build/plat.py
  4. +1 −1 nmigen/vendor/lattice_ecp5.py
  5. +1 −1 nmigen/vendor/xilinx_7series.py
  6. +2 −2 nmigen/vendor/xilinx_spartan_3_6.py
27 changes: 19 additions & 8 deletions nmigen/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -716,7 +716,7 @@ def on_statements(self, stmts):
self.on_statement(stmt)


def _convert_fragment(builder, fragment, hierarchy):
def _convert_fragment(builder, fragment, name_map, hierarchy):
if isinstance(fragment, ir.Instance):
port_map = OrderedDict()
for port_name, (value, dir) in fragment.named_ports.items():
@@ -803,7 +803,8 @@ def _convert_fragment(builder, fragment, hierarchy):
sub_params[param_name] = param_value

sub_type, sub_port_map = \
_convert_fragment(builder, subfragment, hierarchy=hierarchy + (sub_name,))
_convert_fragment(builder, subfragment, name_map,
hierarchy=hierarchy + (sub_name,))

sub_ports = OrderedDict()
for port, value in sub_port_map.items():
@@ -924,23 +925,33 @@ def _convert_fragment(builder, fragment, hierarchy):
wire_curr, _ = compiler_state.wires[wire]
module.connect(wire_curr, rhs_compiler(ast.Const(wire.reset, wire.nbits)))

# Finally, collect the names we've given to our ports in RTLIL, and correlate these with
# the signals represented by these ports. If we are a submodule, this will be necessary
# to create a cell for us in the parent module.
# Collect the names we've given to our ports in RTLIL, and correlate these with the signals
# represented by these ports. If we are a submodule, this will be necessary to create a cell
# for us in the parent module.
port_map = OrderedDict()
for signal in fragment.ports:
port_map[compiler_state.resolve_curr(signal)] = signal

# Finally, collect tha names we've given to each wire in RTLIL, and provide these to
# the caller, to allow manipulating them in the toolchain.
for signal in compiler_state.wires:
wire_name = compiler_state.resolve_curr(signal)
if wire_name.startswith("\\"):
wire_name = wire_name[1:]
name_map[signal] = hierarchy + (wire_name,)

return module.name, port_map


def convert_fragment(fragment, name="top"):
assert isinstance(fragment, ir.Fragment)
builder = _Builder()
_convert_fragment(builder, fragment, hierarchy=(name,))
return str(builder)
name_map = ast.SignalDict()
_convert_fragment(builder, fragment, name_map, hierarchy=(name,))
return str(builder), name_map


def convert(elaboratable, name="top", platform=None, **kwargs):
fragment = ir.Fragment.get(elaboratable, platform).prepare(**kwargs)
return convert_fragment(fragment, name)
il_text, name_map = convert_fragment(fragment, name)
return il_text
4 changes: 2 additions & 2 deletions nmigen/back/verilog.py
Original file line number Diff line number Diff line change
@@ -59,8 +59,8 @@ def _convert_il_text(il_text, strip_src):


def convert_fragment(*args, strip_src=False, **kwargs):
il_text = rtlil.convert_fragment(*args, **kwargs)
return _convert_il_text(il_text, strip_src)
il_text, name_map = rtlil.convert_fragment(*args, **kwargs)
return _convert_il_text(il_text, strip_src), name_map


def convert(*args, strip_src=False, **kwargs):
9 changes: 8 additions & 1 deletion nmigen/build/plat.py
Original file line number Diff line number Diff line change
@@ -254,9 +254,12 @@ def toolchain_prepare(self, fragment, name, **kwargs):
# and to incorporate the nMigen version into generated code.
autogenerated = "Automatically generated by nMigen {}. Do not edit.".format(__version__)

name_map = None
def emit_design(backend):
nonlocal name_map
backend_mod = {"rtlil": rtlil, "verilog": verilog}[backend]
return backend_mod.convert_fragment(fragment, name=name)
design_text, name_map = backend_mod.convert_fragment(fragment, name=name)
return design_text

def emit_commands(format):
commands = []
@@ -293,6 +296,9 @@ def options(opts):
else:
return " ".join(opts)

def hierarchy(signal, separator):
return separator.join(name_map[signal][1:])

def verbose(arg):
if "NMIGEN_verbose" in os.environ:
return arg
@@ -310,6 +316,7 @@ def render(source, origin):
source = textwrap.dedent(source).strip()
compiled = jinja2.Template(source, trim_blocks=True, lstrip_blocks=True)
compiled.environment.filters["options"] = options
compiled.environment.filters["hierarchy"] = hierarchy
except jinja2.TemplateSyntaxError as e:
e.args = ("{} (at {}:{})".format(e.message, origin, e.lineno),)
raise
2 changes: 1 addition & 1 deletion nmigen/vendor/lattice_ecp5.py
Original file line number Diff line number Diff line change
@@ -209,7 +209,7 @@ class LatticeECP5Platform(TemplatedPlatform):
""",
"{{name}}.sdc": r"""
{% for signal, frequency in platform.iter_clock_constraints() -%}
create_clock -period {{1000000000/frequency}} [get_ports {{signal.name}}]
create_clock -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
{% endfor %}
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
""",
2 changes: 1 addition & 1 deletion nmigen/vendor/xilinx_7series.py
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
{% endfor %}
{% endfor %}
{% for signal, frequency in platform.iter_clock_constraints() -%}
create_clock -name {{signal.name}} -period {{1000000000/frequency}} [get_ports {{signal.name}}]
create_clock -name {{signal.name}} -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
{% endfor %}
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
"""
4 changes: 2 additions & 2 deletions nmigen/vendor/xilinx_spartan_3_6.py
Original file line number Diff line number Diff line change
@@ -127,8 +127,8 @@ def family(self):
{% endfor %}
{% endfor %}
{% for signal, frequency in platform.iter_clock_constraints() -%}
NET "{{signal.name}}" TNM_NET="PRD{{signal.name}}";
TIMESPEC "TS{{signal.name}}"=PERIOD "PRD{{signal.name}}" {{1000000000/frequency}} ns HIGH 50%;
NET "{{signal|hierarchy("/")}}" TNM_NET="PRD{{signal|hierarchy("/")}}";
TIMESPEC "TS{{signal|hierarchy("/")}}"=PERIOD "PRD{{signal|hierarchy("/")}}" {{1000000000/frequency}} ns HIGH 50%;
{% endfor %}
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
"""