-
Notifications
You must be signed in to change notification settings - Fork 194
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial and basic VPR support with the new Edalize API (#304)
* Enable VPR flow Signed-off-by: Alessandro Comodi <[email protected]> Co-authored-by: Mateusz Kosmala <[email protected]>
- Loading branch information
Showing
5 changed files
with
277 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Copyright edalize contributors | ||
# Licensed under the 2-Clause BSD License, see LICENSE for details. | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import os.path | ||
|
||
from edalize.flows.edaflow import Edaflow | ||
|
||
|
||
class Vpr(Edaflow): | ||
"""VPR is an open source academic CAD tool designed for the exploration of new FPGA architectures and CAD algorithms, at the packing, placement and routing phases of the CAD flow""" | ||
|
||
argtypes = ["vlogdefine", "vlogparam"] | ||
|
||
FLOW = [ | ||
("yosys", ["vpr"], {"output_format": "blif"}), | ||
("vpr", [], {}), | ||
] | ||
|
||
FLOW_OPTIONS = {} | ||
|
||
def build_tool_graph(self): | ||
return super().build_tool_graph() | ||
|
||
def configure_tools(self, nodes): | ||
super().configure_tools(nodes) | ||
name = self.edam["name"] | ||
self.commands.set_default_target(name + ".analysis") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
# Copyright edalize contributors | ||
# Licensed under the 2-Clause BSD License, see LICENSE for details. | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import shutil | ||
from edalize.tools.edatool import Edatool | ||
from edalize.utils import EdaCommands | ||
import logging | ||
import pathlib | ||
import os.path | ||
import platform | ||
import re | ||
import subprocess | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Vpr(Edatool): | ||
""" | ||
VPR tool Backend | ||
The VPR backend performs Packing, Placement, Routing & Timing Analysis. | ||
""" | ||
|
||
TOOL_OPTIONS = { | ||
"arch_xml": { | ||
"type": "str", | ||
"desc": "Path to target architecture in XML format", | ||
}, | ||
"vpr_options": { | ||
"type": "str", | ||
"desc": "Additional options for VPR.", | ||
"list": True, | ||
}, | ||
} | ||
|
||
def get_version(self): | ||
""" | ||
Get tool version. | ||
This gets the VPR version by running "vpr --version" and | ||
parsing the output. | ||
If this command fails, "unknown" is returned. | ||
""" | ||
version = "unknown" | ||
try: | ||
vpr_output = subprocess.Popen( | ||
["vpr", "--version"], stdout=subprocess.PIPE, env=os.environ | ||
).communicate()[0] | ||
version_exp = r"Version:(.*)" | ||
match = re.search(version_exp, str(vpr_output.decode())) | ||
if match: | ||
version = match.groups()[0] | ||
except Exception: | ||
logger.warning("Unable to recognize VPR version") | ||
return version | ||
|
||
def configure(self, edam): | ||
""" | ||
Configuration is the first phase of the build. | ||
This writes the project TCL files and Makefile. It first collects all | ||
sources, IPs and constraints and then writes them to the TCL file along | ||
with the build steps. | ||
""" | ||
super().configure(edam) | ||
|
||
src_files = [] | ||
incdirs = set() | ||
|
||
file_netlist = [] | ||
timing_constraints = [] | ||
|
||
for f in src_files: | ||
if f.file_type in ["blif", "eblif"]: | ||
file_netlist.append(f.name) | ||
if f.file_type in ["SDC"]: | ||
timing_constraints.append(f.name) | ||
|
||
arch_xml = self.tool_options.get("arch_xml") | ||
if not arch_xml: | ||
logger.error('Missing required "arch" parameter') | ||
|
||
_vo = self.tool_options.get("vpr_options") | ||
|
||
vpr_options = _vo if _vo else [] | ||
sdc_opts = ["--sdc_file"] + timing_constraints if timing_constraints else [] | ||
|
||
commands = EdaCommands() | ||
|
||
depends = self.name + ".blif" | ||
targets = self.name + ".net" | ||
command = ["vpr", arch_xml, self.name + ".blif", "--pack"] | ||
command += sdc_opts + vpr_options | ||
commands.add(command, [targets], [depends]) | ||
|
||
depends = self.name + ".net" | ||
targets = self.name + ".place" | ||
command = ["vpr", arch_xml, self.name + ".blif", "--place"] | ||
command += sdc_opts + vpr_options | ||
commands.add(command, [targets], [depends]) | ||
|
||
depends = self.name + ".place" | ||
targets = self.name + ".route" | ||
command = ["vpr", arch_xml, self.name + ".blif", "--route"] | ||
command += sdc_opts + vpr_options | ||
commands.add(command, [targets], [depends]) | ||
|
||
depends = self.name + ".route" | ||
targets = self.name + ".analysis" | ||
command = ["vpr", arch_xml, self.name + ".blif", "--analysis"] | ||
command += sdc_opts + vpr_options | ||
commands.add(command, [targets], [depends]) | ||
|
||
for ext in [".net", ".place", ".route", ".analysis"]: | ||
self.edam["files"].append( | ||
{"name": self.name + str(ext), "file_type": "vpr_" + str(ext[1:])} | ||
) | ||
|
||
self.commands = commands.commands | ||
commands.set_default_target(targets) | ||
commands.write(os.path.join(self.work_root, "Makefile")) | ||
|
||
def build(self): | ||
logger.info("Building") | ||
return ("make", self.args, self.work_root) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Copyright edalize contributors | ||
# Licensed under the 2-Clause BSD License, see LICENSE for details. | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import logging | ||
import os.path | ||
import platform | ||
import re | ||
import subprocess | ||
|
||
from edalize.edatool import Edatool | ||
from edalize.flows.vpr import Vpr | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Vpr(Edatool): | ||
""" | ||
VPR tool Backend | ||
The VPR backend performs Packing, Placement, Routing & Timing Analysis. | ||
VPR is an open source academic CAD tool designed for the exploration of new FPGA architectures and CAD algorithms, at the packing, placement and routing phases of the CAD flow | ||
""" | ||
|
||
@classmethod | ||
def get_doc(cls, api_ver): | ||
if api_ver == 0: | ||
return { | ||
"description": "The VPR backend performs Packing, Placement, Routing & Timing Analysis.", | ||
"members": [ | ||
{ | ||
"name": "arch_xml", | ||
"type": "String", | ||
"desc": "Path to target architecture.", | ||
}, | ||
{ | ||
"name": "vpr_options", | ||
"type": "String", | ||
"desc": "Additional options for VPR.", | ||
}, | ||
], | ||
} | ||
|
||
def __init__(self, edam=None, work_root=None, eda_api=None, verbose=True): | ||
super().__init__(edam, work_root, eda_api, verbose) | ||
edam["flow_options"] = edam["tool_options"]["vpr"] | ||
self.vpr = VPR(edam, work_root, verbose) | ||
|
||
def configure_main(self): | ||
self.vpr.configure() | ||
|
||
def build_pre(self): | ||
pass | ||
|
||
def build_post(self): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import os | ||
import pytest | ||
from edalize_common import make_edalize_test | ||
|
||
|
||
@pytest.mark.parametrize("params", [("minimal", "vpr")]) | ||
def test_vpr(params, tmpdir): | ||
import os | ||
import edalize | ||
from edalize_common import compare_files, tests_dir | ||
|
||
test_name = "vpr" | ||
ref_dir = os.path.join(tests_dir, __name__, test_name) | ||
os.environ["PATH"] = ( | ||
os.path.join(tests_dir, "mock_commands") + ":" + os.environ["PATH"] | ||
) | ||
tool = "vpr" | ||
name = "test_vpr_{}_0".format(test_name) | ||
work_root = str(tmpdir) | ||
|
||
edam = { | ||
"name": name, | ||
"flow_options": { | ||
"arch": "xilinx", | ||
"arch_xml": "/tmp/k6_N10_mem32K_40nm.xml", | ||
"vpr_options": [], | ||
}, | ||
} | ||
|
||
vpr_flow = edalize.get_flow("vpr") | ||
vpr_backend = vpr_flow(edam=edam, work_root=work_root) | ||
vpr_backend.configure() | ||
config_file_list = [ | ||
"Makefile", | ||
] | ||
compare_files(ref_dir, work_root, config_file_list) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#Auto generated by Edalize | ||
|
||
all: post_build | ||
|
||
pre_build: | ||
|
||
test_vpr_vpr_0.blif: edalize_yosys_template.tcl | pre_build | ||
$(EDALIZE_LAUNCHER) yosys -l yosys.log -p 'tcl edalize_yosys_template.tcl' | ||
|
||
test_vpr_vpr_0.net: test_vpr_vpr_0.blif | ||
$(EDALIZE_LAUNCHER) vpr /tmp/k6_N10_mem32K_40nm.xml test_vpr_vpr_0.blif --pack | ||
|
||
test_vpr_vpr_0.place: test_vpr_vpr_0.net | ||
$(EDALIZE_LAUNCHER) vpr /tmp/k6_N10_mem32K_40nm.xml test_vpr_vpr_0.blif --place | ||
|
||
test_vpr_vpr_0.route: test_vpr_vpr_0.place | ||
$(EDALIZE_LAUNCHER) vpr /tmp/k6_N10_mem32K_40nm.xml test_vpr_vpr_0.blif --route | ||
|
||
test_vpr_vpr_0.analysis: test_vpr_vpr_0.route | ||
$(EDALIZE_LAUNCHER) vpr /tmp/k6_N10_mem32K_40nm.xml test_vpr_vpr_0.blif --analysis | ||
|
||
post_build: test_vpr_vpr_0.analysis | ||
|
||
pre_run: | ||
|
||
run: pre_run | ||
|
||
post_run: run |