Skip to content

Commit

Permalink
Refactor build script toolchain lookups.
Browse files Browse the repository at this point in the history
Now environment variable overrides no longer infect the build scripts.

_toolchain.overrides is dropped as probably misguided in the first place.

Fixes #251.
  • Loading branch information
emilazy authored and whitequark committed Oct 13, 2019
1 parent 2925329 commit a783e46
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 50 deletions.
33 changes: 12 additions & 21 deletions nmigen/_toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,36 @@
import shutil


__all__ = ["ToolNotFound", "get_tool", "has_tool", "require_tool"]
__all__ = ["ToolNotFound", "tool_env_var", "has_tool", "require_tool"]


class ToolNotFound(Exception):
pass


def _tool_env_var(name):
def tool_env_var(name):
return name.upper().replace("-", "_")


def get_tool(name):
return os.environ.get(_tool_env_var(name), overrides.get(name, name))
def _get_tool(name):
return os.environ.get(tool_env_var(name), name)


def has_tool(name):
return shutil.which(get_tool(name)) is not None
return shutil.which(_get_tool(name)) is not None


def require_tool(name):
env_var = _tool_env_var(name)
path = get_tool(name)
env_var = tool_env_var(name)
path = _get_tool(name)
if shutil.which(path) is None:
if path == name:
if env_var in os.environ:
raise ToolNotFound("Could not find required tool {} in {} as "
"specified via the {} environment variable".
format(name, path, env_var))
else:
raise ToolNotFound("Could not find required tool {} in PATH. Place "
"it directly in PATH or specify path explicitly "
"via the {} environment variable".
format(name, env_var))
else:
if os.getenv(env_var):
via = "the {} environment variable".format(env_var)
else:
via = "your packager's toolchain overrides. This is either an " \
"nMigen bug or a packaging error"
raise ToolNotFound("Could not find required tool {} in {} as "
"specified via {}".format(name, path, via))
return path


# Packages for systems like Nix can inject full paths to certain tools by adding them in
# this dictionary, e.g. ``overrides = {"yosys": "/full/path/to/yosys"}``.
overrides = {}
42 changes: 36 additions & 6 deletions nmigen/build/plat.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,14 @@ class TemplatedPlatform(Platform):
# {{autogenerated}}
set -e{{verbose("x")}}
[ -n "${{platform._toolchain_env_var}}" ] && . "${{platform._toolchain_env_var}}"
{{emit_prelude("sh")}}
{{emit_commands("sh")}}
""",
"build_{{name}}.bat": """
@rem {{autogenerated}}
{{quiet("@echo off")}}
if defined {{platform._toolchain_env_var}} call %{{platform._toolchain_env_var}}%
{{emit_prelude("bat")}}
{{emit_commands("bat")}}
""",
}
Expand Down Expand Up @@ -286,14 +288,30 @@ def emit_debug_verilog(opts=()):
return verilog._convert_rtlil_text(rtlil_text,
strip_internal_attrs=False, write_verilog_opts=opts)

def emit_commands(format):
def emit_prelude(syntax):
commands = []
for name in self.required_tools:
env_var = tool_env_var(name)
if syntax == "sh":
template = ": ${{{env_var}:={name}}}"
elif syntax == "bat":
template = \
"if [%{env_var}%] eq [\"\"] set {env_var}=\n" \
"if [%{env_var}%] eq [] set {env_var}={name}"
else:
assert False
commands.append(template.format(env_var=env_var, name=name))
return "\n".join(commands)

def emit_commands(syntax):
commands = []
for index, command_tpl in enumerate(self.command_templates):
command = render(command_tpl, origin="<command#{}>".format(index + 1))
command = render(command_tpl, origin="<command#{}>".format(index + 1),
syntax=syntax)
command = re.sub(r"\s+", " ", command)
if format == "sh":
if syntax == "sh":
commands.append(command)
elif format == "bat":
elif syntax == "bat":
commands.append(command + " || exit /b")
else:
assert False
Expand All @@ -315,6 +333,16 @@ def get_override(var):
else:
return jinja2.Undefined(name=var)

@jinja2.contextfunction
def invoke_tool(context, name):
env_var = tool_env_var(name)
if context.parent["syntax"] == "sh":
return "\"${}\"".format(env_var)
elif context.parent["syntax"] == "bat":
return "%{}%".format(env_var)
else:
assert False

def options(opts):
if isinstance(opts, str):
return opts
Expand All @@ -336,7 +364,7 @@ def quiet(arg):
else:
return arg

def render(source, origin):
def render(source, origin, syntax=None):
try:
source = textwrap.dedent(source).strip()
compiled = jinja2.Template(source, trim_blocks=True, lstrip_blocks=True)
Expand All @@ -351,8 +379,10 @@ def render(source, origin):
"emit_rtlil": emit_rtlil,
"emit_verilog": emit_verilog,
"emit_debug_verilog": emit_debug_verilog,
"emit_prelude": emit_prelude,
"emit_commands": emit_commands,
"get_tool": get_tool,
"syntax": syntax,
"invoke_tool": invoke_tool,
"get_override": get_override,
"verbose": verbose,
"quiet": quiet,
Expand Down
8 changes: 4 additions & 4 deletions nmigen/vendor/intel.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,22 @@ class IntelPlatform(TemplatedPlatform):
}
command_templates = [
r"""
{{get_tool("quartus_map")}}
{{invoke_tool("quartus_map")}}
{{get_override("quartus_map_opts")|options}}
--rev={{name}} {{name}}
""",
r"""
{{get_tool("quartus_fit")}}
{{invoke_tool("quartus_fit")}}
{{get_override("quartus_fit_opts")|options}}
--rev={{name}} {{name}}
""",
r"""
{{get_tool("quartus_asm")}}
{{invoke_tool("quartus_asm")}}
{{get_override("quartus_asm_opts")|options}}
--rev={{name}} {{name}}
""",
r"""
{{get_tool("quartus_sta")}}
{{invoke_tool("quartus_sta")}}
{{get_override("quartus_sta_opts")|options}}
--rev={{name}} {{name}}
""",
Expand Down
12 changes: 6 additions & 6 deletions nmigen/vendor/lattice_ecp5.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,14 @@ class LatticeECP5Platform(TemplatedPlatform):
}
_trellis_command_templates = [
r"""
{{get_tool("yosys")}}
{{invoke_tool("yosys")}}
{{quiet("-q")}}
{{get_override("yosys_opts")|options}}
-l {{name}}.rpt
{{name}}.ys
""",
r"""
{{get_tool("nextpnr-ecp5")}}
{{invoke_tool("nextpnr-ecp5")}}
{{quiet("--quiet")}}
{{get_override("nextpnr_opts")|options}}
--log {{name}}.tim
Expand All @@ -155,7 +155,7 @@ class LatticeECP5Platform(TemplatedPlatform):
--textcfg {{name}}.config
""",
r"""
{{get_tool("ecppack")}}
{{invoke_tool("ecppack")}}
{{verbose("--verbose")}}
{{get_override("ecppack_opts")|options}}
--input {{name}}.config
Expand Down Expand Up @@ -235,16 +235,16 @@ class LatticeECP5Platform(TemplatedPlatform):
_diamond_command_templates = [
# These don't have any usable command-line option overrides.
r"""
{{get_tool("pnmainc")}}
{{invoke_tool("pnmainc")}}
{{name}}.tcl
""",
r"""
{{get_tool("ddtcmd")}}
{{invoke_tool("ddtcmd")}}
-oft -bit
-if {{name}}_impl/{{name}}_impl.bit -of {{name}}.bit
""",
r"""
{{get_tool("ddtcmd")}}
{{invoke_tool("ddtcmd")}}
-oft -svfsingle -revd -op "Fast Program"
-if {{name}}_impl/{{name}}_impl.bit -of {{name}}.svf
""",
Expand Down
6 changes: 3 additions & 3 deletions nmigen/vendor/lattice_ice40.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,14 @@ class LatticeICE40Platform(TemplatedPlatform):
}
_icestorm_command_templates = [
r"""
{{get_tool("yosys")}}
{{invoke_tool("yosys")}}
{{quiet("-q")}}
{{get_override("yosys_opts")|options}}
-l {{name}}.rpt
{{name}}.ys
""",
r"""
{{get_tool("nextpnr-ice40")}}
{{invoke_tool("nextpnr-ice40")}}
{{quiet("--quiet")}}
{{get_override("nextpnr_opts")|options}}
--log {{name}}.tim
Expand All @@ -160,7 +160,7 @@ class LatticeICE40Platform(TemplatedPlatform):
--asc {{name}}.asc
""",
r"""
{{get_tool("icepack")}}
{{invoke_tool("icepack")}}
{{verbose("-v")}}
{{name}}.asc
{{name}}.bin
Expand Down
6 changes: 3 additions & 3 deletions nmigen/vendor/lattice_machxo2.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,17 @@ class LatticeMachXO2Platform(TemplatedPlatform):
command_templates = [
# These don't have any usable command-line option overrides.
r"""
{{get_tool("pnmainc")}}
{{invoke_tool("pnmainc")}}
{{name}}.tcl
""",
r"""
{{get_tool("ddtcmd")}}
{{invoke_tool("ddtcmd")}}
-oft -jed
-dev {{platform.device}}-{{platform.speed}}{{platform.package}}{{platform.grade}}
-if {{name}}_impl/{{name}}_impl.jed -of {{name}}.jed
""",
r"""
{{get_tool("ddtcmd")}}
{{invoke_tool("ddtcmd")}}
-oft -svfsingle -revd -op "FLASH Erase,Program,Verify"
-if {{name}}_impl/{{name}}_impl.jed -of {{name}}.svf
""",
Expand Down
2 changes: 1 addition & 1 deletion nmigen/vendor/xilinx_7series.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
}
command_templates = [
r"""
{{get_tool("vivado")}}
{{invoke_tool("vivado")}}
{{verbose("-verbose")}}
{{get_override("vivado_opts")|options}}
-mode batch
Expand Down
10 changes: 5 additions & 5 deletions nmigen/vendor/xilinx_spartan_3_6.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,20 +141,20 @@ def family(self):
}
command_templates = [
r"""
{{get_tool("xst")}}
{{invoke_tool("xst")}}
{{get_override("xst_opts")|options}}
-ifn {{name}}.xst
""",
r"""
{{get_tool("ngdbuild")}}
{{invoke_tool("ngdbuild")}}
{{quiet("-quiet")}}
{{verbose("-verbose")}}
{{get_override("ngdbuild_opts")|options}}
-uc {{name}}.ucf
{{name}}.ngc
""",
r"""
{{get_tool("map")}}
{{invoke_tool("map")}}
{{verbose("-detail")}}
{{get_override("map_opts")|default([])|options}}
-w
Expand All @@ -163,15 +163,15 @@ def family(self):
{{name}}.pcf
""",
r"""
{{get_tool("par")}}
{{invoke_tool("par")}}
{{get_override("par_opts")|default([])|options}}
-w
{{name}}_map.ncd
{{name}}_par.ncd
{{name}}.pcf
""",
r"""
{{get_tool("bitgen")}}
{{invoke_tool("bitgen")}}
{{get_override("bitgen_opts")|default(["-g Compress"])|options}}
-w
-g Binary:Yes
Expand Down
2 changes: 1 addition & 1 deletion nmigen/vendor/xilinx_ultrascale.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class XilinxUltraScalePlatform(TemplatedPlatform):
}
command_templates = [
r"""
{{get_tool("vivado")}}
{{invoke_tool("vivado")}}
{{verbose("-verbose")}}
{{get_override("vivado_opts")|options}}
-mode batch
Expand Down

0 comments on commit a783e46

Please sign in to comment.