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: c8e6ec2ac703
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: 3c3ab4ae4c82
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Sep 22, 2019

  1. build.plat: restrict design names to alphanumeric to avoid quoting is…

    …sues.
    whitequark committed Sep 22, 2019
    Copy the full SHA
    ee1ad2d View commit details
  2. vendor.altera: add Quartus support. (WIP)

    whitequark committed Sep 22, 2019
    Copy the full SHA
    3c3ab4a View commit details
Showing with 176 additions and 0 deletions.
  1. +11 −0 nmigen/build/plat.py
  2. +165 −0 nmigen/vendor/altera.py
11 changes: 11 additions & 0 deletions nmigen/build/plat.py
Original file line number Diff line number Diff line change
@@ -257,6 +257,17 @@ class TemplatedPlatform(Platform):
}

def toolchain_prepare(self, fragment, name, **kwargs):
# Restrict the name of the design to a strict alphanumeric character set. Platforms will
# interpolate the name of the design in many different contexts: filesystem paths, Python
# scripts, Tcl scripts, ad-hoc constraint files, and so on. It is not practical to add
# escaping code that handles every one of their edge cases, so make sure we never hit them
# in the first place.
invalid_char = re.match(r"[^A-Za-z0-9_]", name)
if invalid_char:
raise ValueError("Design name {!r} contains invalid character {!r}; only alphanumeric "
"characters are valid in design names"
.format(name, invalid_char.group(0)))

# This notice serves a dual purpose: to explain that the file is autogenerated,
# and to incorporate the nMigen version into generated code.
autogenerated = "Automatically generated by nMigen {}. Do not edit.".format(__version__)
165 changes: 165 additions & 0 deletions nmigen/vendor/altera.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
from abc import abstractproperty

from ..hdl import *
from ..build import *


__all__ = ["AlteraPlatform"]


class AlteraPlatform(TemplatedPlatform):
"""
Required tools:
* ``quartus_map``
* ``quartus_fit``
* ``quartus_asm``
* ``quartus_sta``
The environment is populated by running the script specified in the environment variable
``NMIGEN_Quartus_env``, if present.
Available overrides:
* ``nproc``: sets the number of cores used by all tools.
* ``quartus_map_opts``: adds extra options for ``quartus_map``.
* ``quartus_fit_opts``: adds extra options for ``quartus_fit``.
* ``quartus_asm_opts``: adds extra options for ``quartus_asm``.
* ``quartus_sta_opts``: adds extra options for ``quartus_sta``.
Build products:
* ``*.rpt``: toolchain reports.
* ``{{name}}.rbf``: raw binary bitstream.
"""

toolchain = "Quartus"

device = abstractproperty()
package = abstractproperty()
speed = abstractproperty()
suffix = ""

file_templates = {
**TemplatedPlatform.build_script_templates,
"build_{{name}}.sh": r"""
# {{autogenerated}}
if [ -n "$NMIGEN_{{platform.toolchain}}_env" ]; then
QUARTUS_ROOTDIR=$(dirname $(dirname "$NMIGEN_{{platform.toolchain}}_env"))
# Quartus' qenv.sh does not work with `set -e`.
. "$NMIGEN_{{platform.toolchain}}_env"
fi
set -e{{verbose("x")}}
{{emit_commands("sh")}}
""",
"{{name}}.v": r"""
/* {{autogenerated}} */
{{emit_design("verilog")}}
""",
"{{name}}.qsf": r"""
# {{autogenerated}}
{% if get_override("nproc") -%}
set_global_assignment -name NUM_PARALLEL_PROCESSORS {{get_override("nproc")}}
{% endif %}
{% for file in platform.iter_extra_files(".v") -%}
set_global_assignment -name VERILOG_FILE "{{file}}"
{% endfor %}
{% for file in platform.iter_extra_files(".sv") -%}
set_global_assignment -name SYSTEMVERILOG_FILE "{{file}}"
{% endfor %}
set_global_assignment -name VERILOG_FILE {{name}}.v
set_global_assignment -name TOP_LEVEL_ENTITY {{name}}
set_global_assignment -name DEVICE {{platform.device}}{{platform.package}}{{platform.speed}}{{platform.suffix}}
{% for port_name, pin_name, extras in platform.iter_port_constraints_bits() -%}
set_location_assignment -to "{{port_name}}" PIN_{{pin_name}}
{% for key, value in extras.items() -%}
set_instance_assignment -to "{{port_name}}" -name {{key}} "{{value}}"
{% endfor %}
{% endfor %}
set_global_assignment -name GENERATE_RBF_FILE ON
""",
"{{name}}.sdc": r"""
{% for signal, frequency in platform.iter_clock_constraints() -%}
create_clock -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
{% endfor %}
""",
}
command_templates = [
r"""
{{get_tool("quartus_map")}}
{{get_override("quartus_map_opts")|options}}
--rev={{name}} {{name}}
""",
r"""
{{get_tool("quartus_fit")}}
{{get_override("quartus_fit_opts")|options}}
--rev={{name}} {{name}}
""",
r"""
{{get_tool("quartus_asm")}}
{{get_override("quartus_asm_opts")|options}}
--rev={{name}} {{name}}
""",
r"""
{{get_tool("quartus_sta")}}
{{get_override("quartus_sta_opts")|options}}
--rev={{name}} {{name}}
""",
]

def create_missing_domain(self, name):
# TODO: investigate this
return super().create_missing_domain(name)

# TODO: fix all of the following
@staticmethod
def _invert_if(invert, value):
if invert:
return ~value
else:
return value

def get_input(self, pin, port, attrs, invert):
self._check_feature("single-ended input", pin, attrs,
valid_xdrs=(0,), valid_attrs=True)

m = Module()
m.d.comb += pin.i.eq(self._invert_if(invert, port))
return m

def get_output(self, pin, port, attrs, invert):
self._check_feature("single-ended output", pin, attrs,
valid_xdrs=(0,), valid_attrs=True)

m = Module()
m.d.comb += port.eq(self._invert_if(invert, pin.o))
return m

def get_tristate(self, pin, port, attrs, invert):
self._check_feature("single-ended tristate", pin, attrs,
valid_xdrs=(0,), valid_attrs=True)

m = Module()
m.submodules += Instance("$tribuf",
p_WIDTH=pin.width,
i_EN=pin.oe,
i_A=self._invert_if(invert, pin.o),
o_Y=port,
)
return m

def get_input_output(self, pin, port, attrs, invert):
self._check_feature("single-ended input/output", pin, attrs,
valid_xdrs=(0,), valid_attrs=True)

m = Module()
m.submodules += Instance("$tribuf",
p_WIDTH=pin.width,
i_EN=pin.oe,
i_A=self._invert_if(invert, pin.o),
o_Y=port,
)
m.d.comb += pin.i.eq(self._invert_if(invert, port))
return m

# TODO: support differential IO