build: assume vendor tools are in the PATH and remove automatic sourcing, source and toolchain_path parameters.

Automatic sourcing was not consistent between build backends (and only really supported by ISE/Vivado)
and had no real additional value vs the complexity needed to support it. Now just assume required vendor
tools are in the PATH.

This also removes distutils dependency.
This commit is contained in:
Florent Kermarrec 2020-03-04 09:06:27 +01:00
parent 1d7c6943af
commit 0b923aa497
12 changed files with 20 additions and 153 deletions

View File

@ -123,7 +123,7 @@ def _build_qsf(device, ips, sources, vincpaths, named_sc, named_pc, build_name,
# Script ------------------------------------------------------------------------------------------- # Script -------------------------------------------------------------------------------------------
def _build_script(build_name, quartus_path, create_rbf): def _build_script(build_name, create_rbf):
if sys.platform in ["win32", "cygwin"]: if sys.platform in ["win32", "cygwin"]:
script_contents = "REM Autogenerated by LiteX / git: " + tools.get_litex_git_revision() script_contents = "REM Autogenerated by LiteX / git: " + tools.get_litex_git_revision()
script_file = "build_" + build_name + ".bat" script_file = "build_" + build_name + ".bat"
@ -168,14 +168,9 @@ class AlteraQuartusToolchain:
def build(self, platform, fragment, def build(self, platform, fragment,
build_dir = "build", build_dir = "build",
build_name = "top", build_name = "top",
toolchain_path = None,
run = True, run = True,
**kwargs): **kwargs):
# Get default toolchain path (if not specified)
if toolchain_path is None:
toolchain_path = "/opt/Altera"
# Create build directory # Create build directory
cwd = os.getcwd() cwd = os.getcwd()
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
@ -214,7 +209,7 @@ class AlteraQuartusToolchain:
additional_qsf_commands = self.additional_qsf_commands) additional_qsf_commands = self.additional_qsf_commands)
# Generate build script # Generate build script
script = _build_script(build_name, toolchain_path, platform.create_rbf) script = _build_script(build_name, platform.create_rbf)
# Run # Run
if run: if run:

View File

@ -93,7 +93,7 @@ def _build_tcl(device, sources, vincpaths, build_name):
# Script ------------------------------------------------------------------------------------------- # Script -------------------------------------------------------------------------------------------
def _build_script(build_name, device, toolchain_path, ver=None): def _build_script(build_name, device):
if sys.platform in ("win32", "cygwin"): if sys.platform in ("win32", "cygwin"):
script_ext = ".bat" script_ext = ".bat"
script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n"
@ -105,11 +105,7 @@ def _build_script(build_name, device, toolchain_path, ver=None):
copy_stmt = "cp" copy_stmt = "cp"
fail_stmt = "" fail_stmt = ""
if sys.platform not in ("win32", "cygwin"): script_contents += "pnmainc {tcl_script}{fail_stmt}\n".format(
script_contents += "bindir={}\n".format(toolchain_path)
script_contents += ". ${{bindir}}/diamond_env{fail_stmt}\n".format(fail_stmt=fail_stmt)
script_contents += "{pnmainc} {tcl_script}{fail_stmt}\n".format(
pnmainc = os.path.join(toolchain_path, "pnmainc"),
tcl_script = build_name + ".tcl", tcl_script = build_name + ".tcl",
fail_stmt = fail_stmt) fail_stmt = fail_stmt)
for ext in (".bit", ".jed"): for ext in (".bit", ".jed"):
@ -158,13 +154,10 @@ class LatticeDiamondToolchain:
def build(self, platform, fragment, def build(self, platform, fragment,
build_dir = "build", build_dir = "build",
build_name = "top", build_name = "top",
toolchain_path = None,
run = True, run = True,
**kwargs): **kwargs):
# Create build directory # Create build directory
if toolchain_path is None:
toolchain_path = "/opt/Diamond"
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd() cwd = os.getcwd()
os.chdir(build_dir) os.chdir(build_dir)
@ -188,7 +181,7 @@ class LatticeDiamondToolchain:
_build_tcl(platform.device, platform.sources, platform.verilog_include_paths, build_name) _build_tcl(platform.device, platform.sources, platform.verilog_include_paths, build_name)
# Generate build script # Generate build script
script = _build_script(build_name, platform.device, toolchain_path) script = _build_script(build_name, platform.device)
# Run # Run
if run: if run:

View File

@ -151,7 +151,6 @@ class LatticeIceStormToolchain:
def build(self, platform, fragment, def build(self, platform, fragment,
build_dir = "build", build_dir = "build",
build_name = "top", build_name = "top",
toolchain_path = None,
synth_opts = "", synth_opts = "",
run = True, run = True,
**kwargs): **kwargs):

View File

@ -178,17 +178,12 @@ class LatticeTrellisToolchain:
def build(self, platform, fragment, def build(self, platform, fragment,
build_dir = "build", build_dir = "build",
build_name = "top", build_name = "top",
toolchain_path = None,
run = True, run = True,
nowidelut = False, nowidelut = False,
timingstrict = False, timingstrict = False,
ignoreloops = False, ignoreloops = False,
**kwargs): **kwargs):
# Get default toolchain path (if not specified)
if toolchain_path is None:
toolchain_path = "/usr/share/trellis/"
# Create build directory # Create build directory
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd() cwd = os.getcwd()

View File

@ -184,7 +184,7 @@ def _build_timing_sdc(vns, clocks, false_paths, build_name, additional_timing_co
# Script ------------------------------------------------------------------------------------------- # Script -------------------------------------------------------------------------------------------
def _build_script(build_name, device, toolchain_path, ver=None): def _build_script(build_name, device):
if sys.platform in ("win32", "cygwin"): if sys.platform in ("win32", "cygwin"):
script_ext = ".bat" script_ext = ".bat"
script_contents = "@echo off\nREM Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" script_contents = "@echo off\nREM Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n"
@ -238,7 +238,6 @@ class MicrosemiLiberoSoCPolarfireToolchain:
def build(self, platform, fragment, def build(self, platform, fragment,
build_dir = "build", build_dir = "build",
build_name = "top", build_name = "top",
toolchain_path = None,
run = False, run = False,
**kwargs): **kwargs):
@ -273,7 +272,7 @@ class MicrosemiLiberoSoCPolarfireToolchain:
self.additional_timing_constraints) self.additional_timing_constraints)
# Generate build script # Generate build script
script = _build_script(build_name, platform.device, toolchain_path) script = _build_script(build_name, platform.device)
# Run # Run
if run: if run:

View File

@ -170,7 +170,7 @@ def _run_sim(build_name, as_root=False):
class SimVerilatorToolchain: class SimVerilatorToolchain:
def build(self, platform, fragment, build_dir="build", build_name="dut", def build(self, platform, fragment, build_dir="build", build_name="dut",
toolchain_path=None, serial="console", build=True, run=True, threads=1, serial="console", build=True, run=True, threads=1,
verbose=True, sim_config=None, coverage=False, opt_level="O0", verbose=True, sim_config=None, coverage=False, opt_level="O0",
trace=False, trace_fst=False, trace_start=0, trace_end=-1): trace=False, trace_fst=False, trace_start=0, trace_end=-1):

View File

@ -6,7 +6,6 @@
import os import os
import struct import struct
from distutils.version import StrictVersion
import re import re
import subprocess import subprocess
import sys import sys
@ -39,21 +38,6 @@ def write_to_file(filename, contents, force_unix=False):
f.write(contents) f.write(contents)
def arch_bits():
return struct.calcsize("P")*8
def versions(path):
for n in os.listdir(path):
full = os.path.join(path, n)
if not os.path.isdir(full):
continue
try:
yield StrictVersion(n)
except ValueError:
continue
def sub_rules(line, rules, max_matches=1): def sub_rules(line, rules, max_matches=1):
for pattern, color in rules: for pattern, color in rules:
line, matches = re.subn(pattern, color, line, max_matches) line, matches = re.subn(pattern, color, line, max_matches)

View File

@ -39,36 +39,6 @@ if _have_colorama:
r"\g<0>" + colorama.Style.RESET_ALL), r"\g<0>" + colorama.Style.RESET_ALL),
] ]
# Settings -----------------------------------------------------------------------------------------
def settings(path, ver=None, sub=None):
if ver is None:
vers = list(tools.versions(path))
if not vers:
raise OSError("no version directory for Xilinx tools found in "
+ path)
ver = max(vers)
full = os.path.join(path, str(ver))
if sub:
full = os.path.join(full, sub)
search = [64, 32]
if tools.arch_bits() == 32:
search.reverse()
if sys.platform == "win32" or sys.platform == "cygwin":
script_ext = "bat"
else:
script_ext = "sh"
for b in search:
settings = os.path.join(full, "settings{0}.{1}".format(b, script_ext))
if os.path.exists(settings):
return settings
raise OSError("no Xilinx tools settings file found")
# Common MultiReg ---------------------------------------------------------------------------------- # Common MultiReg ----------------------------------------------------------------------------------
class XilinxMultiRegImpl(MultiRegImpl): class XilinxMultiRegImpl(MultiRegImpl):

View File

@ -105,23 +105,17 @@ write_edif -pvector bra {build_name}.edif""".format(build_name=build_name, famil
# ISE Run ------------------------------------------------------------------------------------------ # ISE Run ------------------------------------------------------------------------------------------
def _run_ise(build_name, ise_path, source, mode, ngdbuild_opt, def _run_ise(build_name, mode, ngdbuild_opt, toolchain, platform):
toolchain, platform, ver=None):
if sys.platform == "win32" or sys.platform == "cygwin": if sys.platform == "win32" or sys.platform == "cygwin":
source_cmd = "call "
script_ext = ".bat" script_ext = ".bat"
shell = ["cmd", "/c"] shell = ["cmd", "/c"]
build_script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n" build_script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n"
fail_stmt = " || exit /b" fail_stmt = " || exit /b"
else: else:
source_cmd = "source "
script_ext = ".sh" script_ext = ".sh"
shell = ["bash"] shell = ["bash"]
build_script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n" build_script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n"
fail_stmt = "" fail_stmt = ""
if source:
settings = common.settings(ise_path, ver, "ISE_DS")
build_script_contents += source_cmd + tools.cygpath(settings) + "\n"
if mode == "edif": if mode == "edif":
ext = "ngo" ext = "ngo"
build_script_contents += """ build_script_contents += """
@ -189,21 +183,10 @@ class XilinxISEToolchain:
def build(self, platform, fragment, def build(self, platform, fragment,
build_dir = "build", build_dir = "build",
build_name = "top", build_name = "top",
toolchain_path = None,
source = True,
run = True, run = True,
mode = "xst", mode = "xst",
**kwargs): **kwargs):
# Get default toolchain path (if not specified)
if toolchain_path is None:
if sys.platform == "win32":
toolchain_path = "C:\\Xilinx"
elif sys.platform == "cygwin":
toolchain_path = "/cygdrive/c/Xilinx"
else:
toolchain_path = "/opt/Xilinx"
# Create build directory # Create build directory
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd() cwd = os.getcwd()
@ -250,7 +233,7 @@ class XilinxISEToolchain:
# Run ISE # Run ISE
if run: if run:
_run_ise(build_name, toolchain_path, source, isemode, self.ngdbuild_opt, self, platform) _run_ise(build_name, isemode, self.ngdbuild_opt, self, platform)
finally: finally:
os.chdir(cwd) os.chdir(cwd)

View File

@ -7,7 +7,6 @@
import os import os
import sys import sys
import subprocess import subprocess
from distutils.spawn import find_executable
from litex.build.generic_programmer import GenericProgrammer from litex.build.generic_programmer import GenericProgrammer
from litex.build.xilinx import common from litex.build.xilinx import common
@ -122,25 +121,7 @@ quit
# Vivado ------------------------------------------------------------------------------------------- # Vivado -------------------------------------------------------------------------------------------
def _run_vivado(path, ver, cmds): def _run_vivado(path, ver, cmds):
if sys.platform == "win32" or sys.platform == "cygwin": vivado_cmd = "vivado -mode tcl"
vivado_cmd = "vivado -mode tcl"
else:
vivado_cmd = ""
if not find_executable("vivado"):
# For backwards compatibility with ISE paths, also
# look for a version in a subdirectory named "Vivado"
# under the current directory.
paths_to_try = [path, os.path.join(path, "Vivado")]
for p in paths_to_try:
try:
settings = common.settings(p, ver)
except OSError:
continue
break
else:
raise OSError("Unable to locate Vivado directory or settings.")
vivado_cmd += "source " + settings + " && "
vivado_cmd += "vivado -mode tcl"
with subprocess.Popen(vivado_cmd, stdin=subprocess.PIPE, shell=True) as process: with subprocess.Popen(vivado_cmd, stdin=subprocess.PIPE, shell=True) as process:
process.stdin.write(cmds.encode("ASCII")) process.stdin.write(cmds.encode("ASCII"))
process.communicate() process.communicate()

View File

@ -5,7 +5,6 @@ import os
import subprocess import subprocess
import sys import sys
import math import math
from distutils.spawn import find_executable
from migen.fhdl.structure import _Fragment from migen.fhdl.structure import _Fragment
@ -66,7 +65,7 @@ def _build_xdc(named_sc, named_pc):
# Script ------------------------------------------------------------------------------------------- # Script -------------------------------------------------------------------------------------------
def _build_script(build_name, vivado_path, source, ver=None): def _build_script(build_name):
if sys.platform in ["win32", "cygwin"]: if sys.platform in ["win32", "cygwin"]:
script_contents = "REM Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n" script_contents = "REM Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n"
script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" script_contents += "vivado -mode batch -source " + build_name + ".tcl\n"
@ -74,22 +73,6 @@ def _build_script(build_name, vivado_path, source, ver=None):
tools.write_to_file(script_file, script_contents) tools.write_to_file(script_file, script_contents)
else: else:
script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n" script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n"
# Only source Vivado settings if not already in our $PATH
if not find_executable("vivado"):
# For backwards compatibility with ISE paths, also
# look for a version in a subdirectory named "Vivado"
# under the current directory.
paths_to_try = [vivado_path, os.path.join(vivado_path, "Vivado")]
for p in paths_to_try:
try:
settings = common.settings(p, ver)
except OSError:
continue
break
else:
raise OSError("Unable to locate Vivado directory or settings.")
script_contents += "source " + settings + "\n"
script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" script_contents += "vivado -mode batch -source " + build_name + ".tcl\n"
script_file = "build_" + build_name + ".sh" script_file = "build_" + build_name + ".sh"
tools.write_to_file(script_file, script_contents) tools.write_to_file(script_file, script_contents)
@ -303,18 +286,13 @@ class XilinxVivadoToolchain:
) )
def build(self, platform, fragment, def build(self, platform, fragment,
build_dir = "build", build_dir = "build",
build_name = "top", build_name = "top",
toolchain_path = None, run = True,
source = True, run=True, synth_mode = "vivado",
synth_mode = "vivado", enable_xpm = False,
enable_xpm = False,
**kwargs): **kwargs):
# Get default toolchain path (if not specified)
if toolchain_path is None:
toolchain_path = "/opt/Xilinx/Vivado"
# Create build directory # Create build directory
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd() cwd = os.getcwd()
@ -351,7 +329,7 @@ class XilinxVivadoToolchain:
if run: if run:
if synth_mode == "yosys": if synth_mode == "yosys":
common._run_yosys(platform.device, platform.sources, platform.verilog_include_paths, build_name) common._run_yosys(platform.device, platform.sources, platform.verilog_include_paths, build_name)
script = _build_script(build_name, toolchain_path, source) script = _build_script(build_name)
_run_script(script) _run_script(script)
os.chdir(cwd) os.chdir(cwd)

View File

@ -45,7 +45,6 @@ class Builder:
generated_dir = None, generated_dir = None,
compile_software = True, compile_software = True,
compile_gateware = True, compile_gateware = True,
gateware_toolchain_path = None,
csr_json = None, csr_json = None,
csr_csv = None): csr_csv = None):
self.soc = soc self.soc = soc
@ -60,7 +59,6 @@ class Builder:
self.compile_software = compile_software self.compile_software = compile_software
self.compile_gateware = compile_gateware self.compile_gateware = compile_gateware
self.gateware_toolchain_path = gateware_toolchain_path
self.csr_csv = csr_csv self.csr_csv = csr_csv
self.csr_json = csr_json self.csr_json = csr_json
@ -168,7 +166,7 @@ class Builder:
bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness) bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness)
self.soc.initialize_rom(bios_data) self.soc.initialize_rom(bios_data)
def build(self, toolchain_path=None, **kwargs): def build(self, **kwargs):
self.soc.platform.output_dir = self.output_dir self.soc.platform.output_dir = self.output_dir
os.makedirs(self.gateware_dir, exist_ok=True) os.makedirs(self.gateware_dir, exist_ok=True)
os.makedirs(self.software_dir, exist_ok=True) os.makedirs(self.software_dir, exist_ok=True)
@ -185,13 +183,9 @@ class Builder:
self._generate_csr_map(self.csr_json, self.csr_csv) self._generate_csr_map(self.csr_json, self.csr_csv)
if self.gateware_toolchain_path is not None:
toolchain_path = self.gateware_toolchain_path
if "run" not in kwargs: if "run" not in kwargs:
kwargs["run"] = self.compile_gateware kwargs["run"] = self.compile_gateware
vns = self.soc.build(build_dir=self.gateware_dir, vns = self.soc.build(build_dir=self.gateware_dir, **kwargs)
toolchain_path=toolchain_path, **kwargs)
self.soc.do_exit(vns=vns) self.soc.do_exit(vns=vns)
return vns return vns
@ -215,9 +209,6 @@ def builder_args(parser):
parser.add_argument("--no-compile-gateware", action="store_true", parser.add_argument("--no-compile-gateware", action="store_true",
help="do not compile the gateware, only generate " help="do not compile the gateware, only generate "
"HDL source files and build scripts") "HDL source files and build scripts")
parser.add_argument("--gateware-toolchain-path", default=None,
help="set gateware toolchain (ISE, Quartus, etc.) "
"installation path")
parser.add_argument("--csr-csv", default=None, parser.add_argument("--csr-csv", default=None,
help="store CSR map in CSV format into the " help="store CSR map in CSV format into the "
"specified file") "specified file")
@ -235,7 +226,6 @@ def builder_argdict(args):
"generated_dir": args.generated_dir, "generated_dir": args.generated_dir,
"compile_software": not args.no_compile_software, "compile_software": not args.no_compile_software,
"compile_gateware": not args.no_compile_gateware, "compile_gateware": not args.no_compile_gateware,
"gateware_toolchain_path": args.gateware_toolchain_path,
"csr_csv": args.csr_csv, "csr_csv": args.csr_csv,
"csr_json": args.csr_json, "csr_json": args.csr_json,
} }