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

View File

@ -93,7 +93,7 @@ def _build_tcl(device, sources, vincpaths, build_name):
# Script -------------------------------------------------------------------------------------------
def _build_script(build_name, device, toolchain_path, ver=None):
def _build_script(build_name, device):
if sys.platform in ("win32", "cygwin"):
script_ext = ".bat"
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"
fail_stmt = ""
if sys.platform not in ("win32", "cygwin"):
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"),
script_contents += "pnmainc {tcl_script}{fail_stmt}\n".format(
tcl_script = build_name + ".tcl",
fail_stmt = fail_stmt)
for ext in (".bit", ".jed"):
@ -158,13 +154,10 @@ class LatticeDiamondToolchain:
def build(self, platform, fragment,
build_dir = "build",
build_name = "top",
toolchain_path = None,
run = True,
**kwargs):
# Create build directory
if toolchain_path is None:
toolchain_path = "/opt/Diamond"
os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd()
os.chdir(build_dir)
@ -188,7 +181,7 @@ class LatticeDiamondToolchain:
_build_tcl(platform.device, platform.sources, platform.verilog_include_paths, build_name)
# Generate build script
script = _build_script(build_name, platform.device, toolchain_path)
script = _build_script(build_name, platform.device)
# Run
if run:

View File

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

View File

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

View File

@ -184,7 +184,7 @@ def _build_timing_sdc(vns, clocks, false_paths, build_name, additional_timing_co
# Script -------------------------------------------------------------------------------------------
def _build_script(build_name, device, toolchain_path, ver=None):
def _build_script(build_name, device):
if sys.platform in ("win32", "cygwin"):
script_ext = ".bat"
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,
build_dir = "build",
build_name = "top",
toolchain_path = None,
run = False,
**kwargs):
@ -273,7 +272,7 @@ class MicrosemiLiberoSoCPolarfireToolchain:
self.additional_timing_constraints)
# Generate build script
script = _build_script(build_name, platform.device, toolchain_path)
script = _build_script(build_name, platform.device)
# Run
if run:

View File

@ -170,7 +170,7 @@ def _run_sim(build_name, as_root=False):
class SimVerilatorToolchain:
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",
trace=False, trace_fst=False, trace_start=0, trace_end=-1):

View File

@ -6,7 +6,6 @@
import os
import struct
from distutils.version import StrictVersion
import re
import subprocess
import sys
@ -39,21 +38,6 @@ def write_to_file(filename, contents, force_unix=False):
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):
for pattern, color in rules:
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),
]
# 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 ----------------------------------------------------------------------------------
class XilinxMultiRegImpl(MultiRegImpl):

View File

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

View File

@ -7,7 +7,6 @@
import os
import sys
import subprocess
from distutils.spawn import find_executable
from litex.build.generic_programmer import GenericProgrammer
from litex.build.xilinx import common
@ -122,25 +121,7 @@ quit
# Vivado -------------------------------------------------------------------------------------------
def _run_vivado(path, ver, cmds):
if sys.platform == "win32" or sys.platform == "cygwin":
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:
process.stdin.write(cmds.encode("ASCII"))
process.communicate()

View File

@ -5,7 +5,6 @@ import os
import subprocess
import sys
import math
from distutils.spawn import find_executable
from migen.fhdl.structure import _Fragment
@ -66,7 +65,7 @@ def _build_xdc(named_sc, named_pc):
# Script -------------------------------------------------------------------------------------------
def _build_script(build_name, vivado_path, source, ver=None):
def _build_script(build_name):
if sys.platform in ["win32", "cygwin"]:
script_contents = "REM Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\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)
else:
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_file = "build_" + build_name + ".sh"
tools.write_to_file(script_file, script_contents)
@ -305,16 +288,11 @@ class XilinxVivadoToolchain:
def build(self, platform, fragment,
build_dir = "build",
build_name = "top",
toolchain_path = None,
source = True, run=True,
run = True,
synth_mode = "vivado",
enable_xpm = False,
**kwargs):
# Get default toolchain path (if not specified)
if toolchain_path is None:
toolchain_path = "/opt/Xilinx/Vivado"
# Create build directory
os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd()
@ -351,7 +329,7 @@ class XilinxVivadoToolchain:
if run:
if synth_mode == "yosys":
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)
os.chdir(cwd)

View File

@ -45,7 +45,6 @@ class Builder:
generated_dir = None,
compile_software = True,
compile_gateware = True,
gateware_toolchain_path = None,
csr_json = None,
csr_csv = None):
self.soc = soc
@ -60,7 +59,6 @@ class Builder:
self.compile_software = compile_software
self.compile_gateware = compile_gateware
self.gateware_toolchain_path = gateware_toolchain_path
self.csr_csv = csr_csv
self.csr_json = csr_json
@ -168,7 +166,7 @@ class Builder:
bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness)
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
os.makedirs(self.gateware_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)
if self.gateware_toolchain_path is not None:
toolchain_path = self.gateware_toolchain_path
if "run" not in kwargs:
kwargs["run"] = self.compile_gateware
vns = self.soc.build(build_dir=self.gateware_dir,
toolchain_path=toolchain_path, **kwargs)
vns = self.soc.build(build_dir=self.gateware_dir, **kwargs)
self.soc.do_exit(vns=vns)
return vns
@ -215,9 +209,6 @@ def builder_args(parser):
parser.add_argument("--no-compile-gateware", action="store_true",
help="do not compile the gateware, only generate "
"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,
help="store CSR map in CSV format into the "
"specified file")
@ -235,7 +226,6 @@ def builder_argdict(args):
"generated_dir": args.generated_dir,
"compile_software": not args.no_compile_software,
"compile_gateware": not args.no_compile_gateware,
"gateware_toolchain_path": args.gateware_toolchain_path,
"csr_csv": args.csr_csv,
"csr_json": args.csr_json,
}