Skip to content

[pull] master from olofk:master #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 64 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
0e2438c
el_docker: Run docker as current user instead of root
olofk May 31, 2022
56ac4bc
Verilator: Remove unused variable
olofk May 31, 2022
b6de278
vcs: Support boolean plusargs without value
olofk May 31, 2022
d4f90f1
Copy get_edatool(s) into edatool.py
olofk Jun 11, 2022
45c3d12
Limit CPU usage in Verilator build #210
shareefj May 6, 2022
4e3cef6
Fix up VCS tests
olofk Jun 23, 2022
40be77f
Remove hooks as class variable in EdaFlow
olofk Jun 23, 2022
b936a1b
Restore Vivado run_main method
patrickerich May 18, 2022
2b81736
yosys: add support for verilog output format
trabucayre May 18, 2022
2aaf23b
add cologneChip GateMate toolchain support
trabucayre May 18, 2022
22e87e4
Add fix for ISE path handling on Windows
Jun 6, 2022
66d8abe
Ignore VS Code files
Pocketkid2 Jun 22, 2022
ef4e9b0
Refactor Edaflow so that multiple nodes can use the same options
Pocketkid2 Jun 22, 2022
0be41b9
Support assert reporting from test helper module
olofk Jul 11, 2022
98fa5b5
Refactor and introduce get_tool_options in flow
olofk Jul 2, 2022
2a70c44
Prepare for release
olofk Jul 12, 2022
f30505e
vcs: Add launcher support
olofk Aug 2, 2022
0c40a8d
tools: verilator: Fix broken include files support
olofk Aug 3, 2022
8c97cb9
tools: Add Icarus tool class
olofk Aug 3, 2022
3e86136
Refactor NextPNR for f4pga/symbiflow usage (nextpnr-xilinx specifical…
Pocketkid2 Aug 10, 2022
b381679
add check to ensure -pvector option is used only when output_format i…
Seyviour Aug 13, 2022
6264fd8
Refactor VPR for f4pga/symbiflow usage (includes vprfix)
Pocketkid2 Aug 8, 2022
1d18ec2
Allow for simpler environmental variable creation (#333)
Pocketkid2 Aug 29, 2022
00ea427
Use $(EDALIZE_LAUNCHER) envvar when calling xtclsh
hipolitoguzman Sep 9, 2022
8dbae8c
Set correct data types for board_device_index and speed
olofk Aug 27, 2022
27c79e6
Add build_main function to vivado build flow
GCHQDeveloper147 Aug 23, 2022
41b4f47
Prevent original option dictionary changing
GCHQDeveloper147 Aug 23, 2022
e499fb4
Remove extra blank line (run pre-commit)
GCHQDeveloper147 Sep 1, 2022
ac974d7
Refactor Yosys for f4pga/symbiflow usage
Pocketkid2 Aug 22, 2022
b8d9a9a
Update el_docker
solsjo Oct 2, 2022
4e98e04
Minor edits to utils.py to prevent bugs
Pocketkid2 Oct 3, 2022
6a499da
Further refactor of Yosys changes to better accomodate F4PGA flow
Pocketkid2 Oct 3, 2022
aa1bfa6
Simplify VPR even further
Pocketkid2 Oct 7, 2022
a061f77
Fix el_docker formatting so the test passes
Pocketkid2 Oct 7, 2022
5f3ec5b
Create F4PGA flow
Pocketkid2 Oct 3, 2022
b02e3eb
icarus: Add vvp_options
olofk Sep 22, 2022
4044f2d
Fix el_docker when EDALIZE_EXTRA_DOCKER_FLAGS is not set
olofk Oct 13, 2022
457f7d0
Fix multiple top levels with Icarus
olofk Nov 3, 2022
3606d9d
icarus: Fix vlogparam passing with multiple toplevels
olofk Nov 16, 2022
7c19718
F4PGA: Allow VPR options to be configured at the flow level
Pocketkid2 Oct 17, 2022
c207d19
Finalize basic NextPNR support
Pocketkid2 Oct 28, 2022
895d423
[feat] this commit adds slang support for edalize
tianrui-wei May 8, 2021
fa29e80
[feat] add user specified option support
tianrui-wei Aug 21, 2021
974e8ba
[fix] fix multiple definitions
tianrui-wei Aug 21, 2021
eaf21da
[fix] fix python3 subprocess error
tianrui-wei Aug 21, 2021
32b7057
[style] change extra_options to slang_options
tianrui-wei Aug 23, 2021
887c322
[feat] add support for vlogparam
tianrui-wei Aug 23, 2021
e465edc
tool openlanes missing systemVerilogSource
shuckc Nov 7, 2022
259e596
Change Modelsim options order
ttobsen Oct 31, 2022
d0a467c
Fix slang tests
olofk Dec 15, 2022
e8a366d
Fix OpenLANE tests
olofk Dec 15, 2022
8d1cb8c
Add Questa Formal Tool
ttobsen Nov 8, 2022
622bed6
vivado.py: set optional argument to _add_include_dir to force the rep…
phdussud Sep 19, 2022
6c7100e
ise: Allow families with spaces in name
olofk Dec 18, 2022
843a9ed
Don't capture output of script hooks
olofk Dec 26, 2022
f771ca5
Use a slightly newer openlane in el_docker
olofk Dec 26, 2022
e6ce94e
Prepare for release
olofk Dec 26, 2022
67fad10
Fix formatting
olofk Jan 1, 2023
0ff1f81
CI: Replace python 3.6 with 3.11
olofk Jan 1, 2023
af76f73
Fix test_edam_hooks by not expecting error code 1
olofk Jan 1, 2023
35b53b5
[fix] yosys: use default target name for Makefile
Henkru Dec 30, 2022
915da93
write_filelist: adding new filelist backend.
sjalloq Dec 10, 2021
3577d3f
Restore formatting
olofk Jan 6, 2023
ff0e113
Add common compilation mode to modelsim
olofk Jan 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ jobs:
#- { icon: 🍎, name: macos }
#- { icon: 🧊, name: windows }
pyver:
- '3.6'
- '3.7'
- '3.8'
- '3.9'
- '3.10'
- '3.11'
runs-on: ${{ matrix.os.name }}-latest
name: ${{ matrix.os.icon }} ${{ matrix.os.name }} | ${{ matrix.pyver }}
steps:
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ doc/_build/
__pycache__
/.eggs
/.tox
.vscode/
build/
dist/
venv/
.project
.pydevproject
/.pytest_cache/
27 changes: 27 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
0.4.1 2022-12-26 Olof Kindgren
======================================================
* New flows: f4pga
* New backends: slang, Questa Formal
* Migrated to flow API: icarus
* icarus: Add vvp_options, support multiple top levels
* ise: Support FPGA families with spaces in name
* openlane: Support SystemVerilog
* vcs: Support launchers
* verilator: Fix include files
* vivado: Support launchers, fix pnr=none, fix include dirs on windows
* yosys: Only use -pvector for edif
* el_docker: Support additional docker args, update openlane version
* Don't capture output of script hooks

0.4.0 2022-07-12 Olof Kindgren
======================================================
* New backends: OpenFPGA, VPR, Mistral, gatemate
* symbiflow: Support Quicklogic
* xsim: :Fix VHDL generics quotation
* ISE: Added option to Specify JTAG chain index, fix windows path handling
* verilator: Support EDALIZE_LAUNCHER, limit CPU usage
* icestorm: Add icepack_options
* el_docker: Run as user instead of root
* vcs: Support boolean plusargs without value
* yosys: Support verilog output
* Flow API: Add get_tool_options function
32 changes: 30 additions & 2 deletions edalize/edatool.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

import argparse
from collections import OrderedDict
from importlib import import_module
import os
from pkgutil import walk_packages

import subprocess
import logging
import sys
Expand All @@ -21,6 +24,32 @@
except ImportError:
_mswindows = False

NON_TOOL_PACKAGES = [
"flows",
"tools",
"utils",
"vunit_hooks",
"reporting",
"ise_reporting",
"vivado_reporting",
"quartus_reporting",
]


def get_edatool(name):
return getattr(import_module(f"edalize.{name}"), name.capitalize())


def walk_tool_packages():
for _, pkg_name, _ in walk_packages([os.path.dirname(__file__)], "edalize."):
pkg_parts = pkg_name.split(".")
if not pkg_parts[1] in NON_TOOL_PACKAGES:
yield pkg_parts[1]


def get_edatools():
return [get_edatool(pkg) for pkg in walk_tool_packages()]


def subprocess_run_3_9(
*popenargs, input=None, capture_output=False, timeout=None, check=False, **kwargs
Expand Down Expand Up @@ -121,7 +150,7 @@ def __init__(self, edam=None, work_root=None, eda_api=None, verbose=True):
except KeyError:
raise RuntimeError("Missing required parameter 'name'")

self.tool_options = edam.get("tool_options", {}).get(_tool_name, {})
self.tool_options = edam.get("tool_options", {}).get(_tool_name, {}).copy()

self.files = edam.get("files", [])
self.toplevel = edam.get("toplevel", [])
Expand Down Expand Up @@ -404,7 +433,6 @@ def _run_scripts(self, scripts, hook_name):
script["cmd"],
cwd=self.work_root,
env=_env,
capture_output=not self.verbose,
check=True,
)
except FileNotFoundError as e:
Expand Down
54 changes: 54 additions & 0 deletions edalize/f4pga.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright edalize contributors
# Licensed under the 2-Clause BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-2-Clause

from edalize.edatool import Edatool
from edalize.flows.f4pga import F4pga as F4pga_underlying


class F4pga(Edatool):
"""Edalize front-end F4PGA interface"""

@classmethod
def get_doc(cls, api_ver):
if api_ver == 0:
return {
"description": "F4PGA is an open-source flow for generating bitstreams from verilog/systemverilog code using Yosys and VPR/NextPNR. Currently only supports Xilinx 7-series boards with support for more coming in the future.",
"members": [
{
"name": "device",
"type": "str",
"desc": "(Required) The device type identifier. Example: 'artix7'",
},
{
"name": "part",
"type": "str",
"desc": "(Required) The FPGA part specifier. Example: 'xc7a35tcpg236-1'",
},
{
"name": "chip",
"type": "str",
"desc": "(Required) The FPGA chip specifier used by F4PGA. Example: 'xc7a50t_test'",
},
{
"name": "arch",
"type": "str",
"desc": "(Optional) The architecture specifier. Currently defaults to xilinx and is thus optional.",
},
{
"name": "pnr",
"type": "str",
"desc": "(Optional) The name of the place and route tool to use. Defaults to VPR and is thus optional.",
},
],
}

def __init__(self, edam=None, work_root=None, eda_api=None, verbose=True):
super().__init__(edam, work_root, eda_api, verbose)
self.f4pga = F4pga_underlying(edam, work_root, verbose)

def configure_main(self):
self.f4pga.configure()

def run_main(self):
pass
189 changes: 189 additions & 0 deletions edalize/filelist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Copyright edalize contributors
# Licensed under the 2-Clause BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-2-Clause

import os, sys, re
import logging

from edalize.edatool import Edatool
from pathlib import Path

logger = logging.getLogger(__name__)


class Filelist(Edatool):

# Currently only +define+ is supported in the VC file. Some tools allow parameters to be passed but the syntax is tool specific.
argtypes = ["vlogdefine"]

@classmethod
def get_doc(cls, api_ver):
if api_ver == 0:
return {
"description": "The filelist backend writes out a VC file to be used in tool flows not yet supported by Edalize",
"members": [
{
"name": "outpath",
"type": "String",
"desc": "Specify the output path for the VC file, can be absolute or relative to parent core file",
},
{
"name": "mode",
"type": "String",
"desc": "Select the output path style. Legal values are *absolute* or *relative*",
},
],
"lists": [
{
"name": "libext",
"type": "String",
"desc": "Provide a list of library extensions",
}
],
}

def configure_main(self):

core_file = Path(self.edam["top_core"])
core_name = core_file.name
core_path = core_file.parent

# If the user hasn't specified an output path, then default to the top core file location.
# REVISIT: should the default be to write the VC file to the working directory?
if not "outpath" in self.tool_options:
self.tool_options["outpath"] = core_path
else:
outpath = self.tool_options["outpath"]

if outpath.startswith("/"):
# outpath is absolute
self.tool_options["outpath"] = Path(outpath)
elif outpath.startswith("$"):
# outpath is using environment variable
self.tool_options["outpath"] = Path(self._resolve_env_var(outpath))
else:
# outpath is relative to core_file
self.tool_options["outpath"] = core_path / outpath

logger.debug("outpath={}".format(self.tool_options["outpath"]))

if self.tool_options["outpath"].suffix != "":
# If the user has sepcified a full path with a filename, then use that...
outfile = self.tool_options["outpath"]
else:
# ...else use the name of the core file.
outfile = self.tool_options["outpath"] / core_name.replace(".core", ".f")

# Validate the filelist mode
# REVISIT: if we are writing to the working directory, what file paths should be used?
mode = self.tool_options.get("mode", "absolute")
if mode not in ["absolute", "relative"]:
raise RuntimeError('Illegal filelist mode "{}"'.format(mode))

# Write out the VC file
with outfile.open("w") as f:
for libext in self.tool_options.get("libext", []):
f.write("+libext+{}\n".format(libext))

(src_files, incdirs) = self._convert_paths(
*self._get_fileset_files(force_slash=True), mode
)

for key, value in self.vlogdefine.items():
define_str = self._param_value_str(param_value=value)
f.write("+define+{}={}\n".format(key, define_str))

for id in incdirs:
f.write("+incdir+" + id + "\n")

for src_file in src_files:
if src_file.file_type.startswith(
"systemVerilogSource"
) or src_file.file_type.startswith("verilogSource"):
f.write(src_file.name + "\n")

logger.info("wrote filelist to {}".format(outfile))

def build(self):
pass

def run(self, args):
pass

def _resolve_env_var(self, outpath):
"""Resolves an environment variable in a path.

The argument `outpath` should be an environment variable, $VAR, or a concatenated path of the
form $VAR/the/rest/of/the/path.

Assumes that an environment variable will be of the form $VAR, $(VAR) or ${VAR}. The variable
itself will normally be of the form VAR or SOME_VAR but all alphanumeric names with underscores
will be detected.

"""

regex = re.compile(
r"""(\$ #
(?:[({])? # An optional opening brace or parnthesis
([A-Za-z0-9_]+) # The environment variable
(?:[)}])? # An optional closing brace or parenthesis
(?:(/.+))? # The rest of the path if there is one
$)""",
re.VERBOSE,
)

if match := regex.match(outpath):
envvar = match.group(2)
therest = match.group(3)
try:
return os.environ[envvar] + (therest if therest else "")
except KeyError:
logger.error(
'could not resolve environment variable in outpath="{}"'.format(
match.group(1)
)
)
raise RuntimeError()
else:
logger.error(
'did not recognise environment variable in outpath="{}"'.format(outpath)
)
raise RuntimeError()

def _convert_paths(self, src_files, incdirs, mode):
"""Converts the work_root relative file paths to absolute or core file relative.

The `src_files` and `incdirs` lists returned from `_get_fileset_files` are relative paths to
the FuseSoC working directory, `work_root`. This isn't particularly usefull for a generic
VC file so we convert them to either absolute paths or relative to the parent core file.

"""
_src_files = []
_incdirs = []

for src_file in src_files:
src_file.name = self._resolve_path(
Path(self.work_root) / src_file.name, mode
)
_src_files.append(src_file)

for incdir in incdirs:
_incdirs.append(self._resolve_path(Path(self.work_root) / incdir, mode))

return (_src_files, _incdirs)

def _resolve_path(self, path, mode):
"""Generates correct file paths.

Depending on the `mode` selected, we can generate absolute file paths or ones relative
to the output path where the .f file will be placed.

"""
if mode == "absolute":
return str(path.resolve())
elif mode == "relative":
return os.path.relpath(
path.resolve(), start=self.tool_options["outpath"].resolve()
)
else:
raise RuntimeError("illegal mode {}".format(mode))
Loading