diff --git a/bfasst/ninja_flows/flow.py b/bfasst/ninja_flows/flow.py index de141a1af..2a4add5e7 100644 --- a/bfasst/ninja_flows/flow.py +++ b/bfasst/ninja_flows/flow.py @@ -1,7 +1,7 @@ """Base class for all ninja flows""" import abc -from bfasst.ninja_tools.vivado.vivado import Vivado +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth from bfasst.paths import BUILD_DIR, DESIGNS_PATH @@ -29,7 +29,7 @@ def add_ninja_deps(self): def get_top_level_flow_path(self) -> str: """Get the path to the top level flow file for this flow""" - def configure_vivado_tool(self, design, flow_args, ooc=False): + def configure_vivado_synth_tool(self, design, flow_args, ooc=False): if isinstance(flow_args, dict) and "synth" in flow_args: - return Vivado(design, flow_args["synth"], ooc) - return Vivado(design, ooc=ooc) + return VivadoSynth(design, flow_args["synth"], ooc) + return VivadoSynth(design, ooc=ooc) diff --git a/bfasst/ninja_flows/vivado.py b/bfasst/ninja_flows/vivado.py index 031836733..6f93ff3d3 100644 --- a/bfasst/ninja_flows/vivado.py +++ b/bfasst/ninja_flows/vivado.py @@ -1,5 +1,6 @@ """Flow to create Vivado synthesis and implementation ninja snippets.""" from bfasst.ninja_flows.flow import Flow +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.paths import NINJA_FLOWS_PATH @@ -9,16 +10,20 @@ class Vivado(Flow): def __init__(self, design, flow_args=None, ooc=False): super().__init__(design) self.ooc = ooc - self.vivado_tool = self.configure_vivado_tool(design, flow_args, ooc) + self.vivado_synth_tool = self.configure_vivado_synth_tool(design, flow_args, ooc) + self.vivado_impl_tool = VivadoImpl(design, ooc) def create_rule_snippets(self): - self.vivado_tool.create_rule_snippets() + self.vivado_synth_tool.create_rule_snippets() + self.vivado_impl_tool.create_rule_snippets() def create_build_snippets(self): - self.vivado_tool.create_build_snippets() + self.vivado_synth_tool.create_build_snippets() + self.vivado_impl_tool.create_build_snippets() def add_ninja_deps(self, deps): - self.vivado_tool.add_ninja_deps(deps) + self.vivado_synth_tool.add_ninja_deps(deps) + self.vivado_impl_tool.add_ninja_deps(deps) deps.append(NINJA_FLOWS_PATH / "vivado.py") if self.ooc: deps.append(NINJA_FLOWS_PATH / "vivado_ooc.py") diff --git a/bfasst/ninja_flows/vivado_bit_analysis.py b/bfasst/ninja_flows/vivado_bit_analysis.py index ab79b67ac..0617e1ddf 100644 --- a/bfasst/ninja_flows/vivado_bit_analysis.py +++ b/bfasst/ninja_flows/vivado_bit_analysis.py @@ -3,6 +3,7 @@ import pathlib from bfasst.ninja_flows.flow import Flow +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.rev_bit.xray import Xray as XrevTool from bfasst.ninja_tools.transform.netlist_cleanup import NetlistCleanupTool from bfasst.ninja_tools.transform.netlist_phys_to_logical import NetlistPhysToLogicalTool @@ -13,20 +14,23 @@ class VivadoBitAnalysis(Flow): def __init__(self, design, flow_args=None): super().__init__(design) - self.vivado_tool = self.configure_vivado_tool(design, flow_args) + self.vivado_synth_tool = self.configure_vivado_synth_tool(design, flow_args) + self.vivado_impl_tool = VivadoImpl(design) self.xrev_tool = XrevTool(design) self.netlist_cleanup_tool = NetlistCleanupTool(design) self.netlist_phys_to_logical = NetlistPhysToLogicalTool(design) def create_rule_snippets(self): - self.vivado_tool.create_rule_snippets() + self.vivado_synth_tool.create_rule_snippets() + self.vivado_impl_tool.create_rule_snippets() self.xrev_tool.create_rule_snippets() self.netlist_cleanup_tool.create_rule_snippets() self.netlist_phys_to_logical.create_rule_snippets() def create_build_snippets(self): - self.vivado_tool.create_build_snippets() - self.xrev_tool.create_build_snippets(str(self.vivado_tool.outputs["bitstream"])) + self.vivado_synth_tool.create_build_snippets() + self.vivado_impl_tool.create_build_snippets() + self.xrev_tool.create_build_snippets(str(self.vivado_impl_tool.outputs["bitstream"])) self.netlist_cleanup_tool.create_build_snippets( netlist_in_path=self.xrev_tool.outputs["xray_netlist"], ) @@ -35,7 +39,8 @@ def create_build_snippets(self): ) def add_ninja_deps(self, deps): - self.vivado_tool.add_ninja_deps(deps) + self.vivado_synth_tool.add_ninja_deps(deps) + self.vivado_impl_tool.add_ninja_deps(deps) self.xrev_tool.add_ninja_deps(deps) self.netlist_cleanup_tool.add_ninja_deps(deps) self.netlist_phys_to_logical.add_ninja_deps(deps) diff --git a/bfasst/ninja_flows/vivado_conformal.py b/bfasst/ninja_flows/vivado_conformal.py index 4bb775214..290c6b01f 100644 --- a/bfasst/ninja_flows/vivado_conformal.py +++ b/bfasst/ninja_flows/vivado_conformal.py @@ -1,6 +1,7 @@ """Run vivado, phys_netlist, reverse with xray, then compare with conformal.""" from bfasst.ninja_flows.flow import Flow +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.compare.conformal.conformal import Conformal from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.paths import NINJA_FLOWS_PATH @@ -12,26 +13,30 @@ class VivadoConformal(Flow): def __init__(self, design, flow_args=None): super().__init__(design) - self.vivado_tool = self.configure_vivado_tool(design, flow_args) + self.vivado_synth_tool = self.configure_vivado_synth_tool(design, flow_args) + self.vivado_impl_tool = VivadoImpl(design) self.xrev_tool = Xray(design) self.conformal_tool = Conformal(design) def create_rule_snippets(self): - self.vivado_tool.create_rule_snippets() + self.vivado_synth_tool.create_rule_snippets() + self.vivado_impl_tool.create_rule_snippets() self.xrev_tool.create_rule_snippets() self.conformal_tool.create_rule_snippets() def create_build_snippets(self): - self.vivado_tool.create_build_snippets() - self.xrev_tool.create_build_snippets(str(self.vivado_tool.outputs["bitstream"])) + self.vivado_synth_tool.create_build_snippets() + self.vivado_impl_tool.create_build_snippets() + self.xrev_tool.create_build_snippets(str(self.vivado_impl_tool.outputs["bitstream"])) self.conformal_tool.create_build_snippets( - impl_netlist=str(self.vivado_tool.outputs["impl_verilog"]), + impl_netlist=str(self.vivado_impl_tool.outputs["impl_verilog"]), rev_netlist=str(self.xrev_tool.outputs["xray_netlist"]), vendor=Vendor.XILINX, ) def add_ninja_deps(self, deps): - self.vivado_tool.add_ninja_deps(deps) + self.vivado_synth_tool.add_ninja_deps(deps) + self.vivado_impl_tool.add_ninja_deps(deps) self.xrev_tool.add_ninja_deps(deps) self.conformal_tool.add_ninja_deps(deps) deps.append(NINJA_FLOWS_PATH / "vivado_conformal.py") diff --git a/bfasst/ninja_flows/vivado_phys_netlist.py b/bfasst/ninja_flows/vivado_phys_netlist.py index d848cf071..32bdbddb4 100644 --- a/bfasst/ninja_flows/vivado_phys_netlist.py +++ b/bfasst/ninja_flows/vivado_phys_netlist.py @@ -1,6 +1,7 @@ """Creates a Vivado netlist that has only physical primitives.""" from bfasst.ninja_flows.flow import Flow +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.transform.phys_netlist import PhysNetlist from bfasst.paths import NINJA_FLOWS_PATH @@ -10,22 +11,28 @@ class VivadoPhysNetlist(Flow): def __init__(self, design, flow_args=None): super().__init__(design) - self.vivado_tool = self.configure_vivado_tool(design, flow_args) + self.vivado_synth_tool = self.configure_vivado_synth_tool(design, flow_args) + self.vivado_impl_tool = VivadoImpl(design) self.phys_netlist_tool = PhysNetlist(design) def create_rule_snippets(self): - self.vivado_tool.create_rule_snippets() + self.vivado_synth_tool.create_rule_snippets() + self.vivado_impl_tool.create_rule_snippets() self.phys_netlist_tool.create_rule_snippets() def create_build_snippets(self): - self.vivado_tool.create_build_snippets() + # pylint: disable=duplicate-code + self.vivado_synth_tool.create_build_snippets() + self.vivado_impl_tool.create_build_snippets() self.phys_netlist_tool.create_build_snippets( - impl_dcp=self.vivado_tool.outputs["impl_checkpoint"], - impl_edf=self.vivado_tool.outputs["impl_edf"], + impl_dcp=self.vivado_impl_tool.outputs["impl_checkpoint"], + impl_edf=self.vivado_impl_tool.outputs["impl_edf"], ) + # pylint: enable=duplicate-code def add_ninja_deps(self, deps): - self.vivado_tool.add_ninja_deps(deps) + self.vivado_synth_tool.add_ninja_deps(deps) + self.vivado_impl_tool.add_ninja_deps(deps) self.phys_netlist_tool.add_ninja_deps(deps) deps.append(NINJA_FLOWS_PATH / "vivado_phys_netlist.py") diff --git a/bfasst/ninja_flows/vivado_phys_netlist_cmp.py b/bfasst/ninja_flows/vivado_phys_netlist_cmp.py index 3b59d61e0..d2d557d15 100644 --- a/bfasst/ninja_flows/vivado_phys_netlist_cmp.py +++ b/bfasst/ninja_flows/vivado_phys_netlist_cmp.py @@ -1,6 +1,7 @@ """Structural Comparison of physical netlist and reversed netlist""" from bfasst.ninja_flows.flow import Flow +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.compare.structural.structural import Structural from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.ninja_tools.transform.phys_netlist import PhysNetlist @@ -12,32 +13,38 @@ class VivadoPhysNetlistCmp(Flow): def __init__(self, design, flow_args=None): super().__init__(design) - self.vivado_tool = self.configure_vivado_tool(design, flow_args) + self.vivado_synth_tool = self.configure_vivado_synth_tool(design, flow_args) + self.vivado_impl_tool = VivadoImpl(design) self.phys_netlist_tool = PhysNetlist(design) self.xray_tool = Xray(design) self.compare_tool = Structural(design) def create_rule_snippets(self): - self.vivado_tool.create_rule_snippets() + self.vivado_synth_tool.create_rule_snippets() + self.vivado_impl_tool.create_rule_snippets() self.phys_netlist_tool.create_rule_snippets() self.xray_tool.create_rule_snippets() self.compare_tool.create_rule_snippets() def create_build_snippets(self): - self.vivado_tool.create_build_snippets() + # pylint: disable=duplicate-code + self.vivado_synth_tool.create_build_snippets() + self.vivado_impl_tool.create_build_snippets() self.phys_netlist_tool.create_build_snippets( - impl_dcp=self.vivado_tool.outputs["impl_checkpoint"], - impl_edf=self.vivado_tool.outputs["impl_edf"], + impl_dcp=self.vivado_impl_tool.outputs["impl_checkpoint"], + impl_edf=self.vivado_impl_tool.outputs["impl_edf"], ) - self.xray_tool.create_build_snippets(str(self.vivado_tool.outputs["bitstream"])) + self.xray_tool.create_build_snippets(str(self.vivado_impl_tool.outputs["bitstream"])) self.compare_tool.create_build_snippets( netlist_a=self.xray_tool.outputs["xray_netlist"], netlist_b=self.phys_netlist_tool.outputs["viv_impl_physical_v"], log_name="struct_cmp.log", ) + # pylint: enable=duplicate-code def add_ninja_deps(self, deps): - self.vivado_tool.add_ninja_deps(deps) + self.vivado_synth_tool.add_ninja_deps(deps) + self.vivado_impl_tool.add_ninja_deps(deps) self.phys_netlist_tool.add_ninja_deps(deps) self.xray_tool.add_ninja_deps(deps) self.compare_tool.add_ninja_deps(deps) diff --git a/bfasst/ninja_flows/vivado_phys_netlist_xrev.py b/bfasst/ninja_flows/vivado_phys_netlist_xrev.py index b00ba6947..2cd104080 100644 --- a/bfasst/ninja_flows/vivado_phys_netlist_xrev.py +++ b/bfasst/ninja_flows/vivado_phys_netlist_xrev.py @@ -2,6 +2,7 @@ from bfasst.ninja_flows.flow import Flow +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.ninja_tools.transform.phys_netlist import PhysNetlist from bfasst.paths import NINJA_FLOWS_PATH @@ -12,27 +13,31 @@ class VivadoPhysNetlistXrev(Flow): def __init__(self, design, flow_args=None): super().__init__(design) - self.vivado_tool = self.configure_vivado_tool(design, flow_args) + self.vivado_synth_tool = self.configure_vivado_synth_tool(design, flow_args) + self.vivado_impl_tool = VivadoImpl(design) self.phys_netlist_tool = PhysNetlist(design) self.xrev_tool = Xray(design) def create_rule_snippets(self): """Create the rule snippets for the flow and append them to build.ninja.""" - self.vivado_tool.create_rule_snippets() + self.vivado_synth_tool.create_rule_snippets() + self.vivado_impl_tool.create_rule_snippets() self.phys_netlist_tool.create_rule_snippets() self.xrev_tool.create_rule_snippets() def create_build_snippets(self): """Create the build snippets for the flow and append them to build.ninja.""" - self.vivado_tool.create_build_snippets() + self.vivado_synth_tool.create_build_snippets() + self.vivado_impl_tool.create_build_snippets() self.phys_netlist_tool.create_build_snippets( - impl_dcp=self.vivado_tool.outputs["impl_checkpoint"], - impl_edf=self.vivado_tool.outputs["impl_edf"], + impl_dcp=self.vivado_impl_tool.outputs["impl_checkpoint"], + impl_edf=self.vivado_impl_tool.outputs["impl_edf"], ) - self.xrev_tool.create_build_snippets(self.vivado_tool.outputs["bitstream"]) + self.xrev_tool.create_build_snippets(self.vivado_impl_tool.outputs["bitstream"]) def add_ninja_deps(self, deps): - self.vivado_tool.add_ninja_deps(deps) + self.vivado_synth_tool.add_ninja_deps(deps) + self.vivado_impl_tool.add_ninja_deps(deps) self.phys_netlist_tool.add_ninja_deps(deps) self.xrev_tool.add_ninja_deps(deps) deps.append(NINJA_FLOWS_PATH / "vivado_phys_netlist_xrev.py") diff --git a/bfasst/ninja_flows/vivado_structural_error_injection.py b/bfasst/ninja_flows/vivado_structural_error_injection.py index eaf041af2..3a4f069d4 100644 --- a/bfasst/ninja_flows/vivado_structural_error_injection.py +++ b/bfasst/ninja_flows/vivado_structural_error_injection.py @@ -3,6 +3,7 @@ import random from bfasst.ninja_flows.flow import Flow +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.compare.structural.structural import Structural from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.ninja_tools.transform.error_injector import ErrorInjector @@ -18,7 +19,8 @@ class VivadoStructuralErrorInjection(Flow): def __init__(self, design, flow_args=None): super().__init__(design) random.seed(0) - self.vivado_tool = self.configure_vivado_tool(design, flow_args) + self.vivado_synth_tool = self.configure_vivado_synth_tool(design, flow_args) + self.vivado_impl_tool = VivadoImpl(design) self.phys_netlist_tool = PhysNetlist(design) self.xrev_tool = Xray(design) self.error_injector_tool = ErrorInjector(design) @@ -28,19 +30,21 @@ def __init__(self, design, flow_args=None): def create_rule_snippets(self): """Create the rule snippets for the flow and append them to build.ninja.""" - self.vivado_tool.create_rule_snippets() + self.vivado_synth_tool.create_rule_snippets() + self.vivado_impl_tool.create_rule_snippets() self.phys_netlist_tool.create_rule_snippets() self.xrev_tool.create_rule_snippets() self.error_injector_tool.create_rule_snippets() self.compare_tool.create_rule_snippets() def create_build_snippets(self): - self.vivado_tool.create_build_snippets() + self.vivado_synth_tool.create_build_snippets() + self.vivado_impl_tool.create_build_snippets() self.phys_netlist_tool.create_build_snippets( - impl_dcp=self.vivado_tool.outputs["impl_checkpoint"], - impl_edf=self.vivado_tool.outputs["impl_edf"], + impl_dcp=self.vivado_impl_tool.outputs["impl_checkpoint"], + impl_edf=self.vivado_impl_tool.outputs["impl_edf"], ) - self.xrev_tool.create_build_snippets(self.vivado_tool.outputs["bitstream"]) + self.xrev_tool.create_build_snippets(self.vivado_impl_tool.outputs["bitstream"]) random_seed_multiplier = 1 error_type = [ErrorType.BIT_FLIP, ErrorType.WIRE_SWAP] @@ -62,7 +66,8 @@ def create_build_snippets(self): ) def add_ninja_deps(self, deps): - self.vivado_tool.add_ninja_deps(deps) + self.vivado_synth_tool.add_ninja_deps(deps) + self.vivado_impl_tool.add_ninja_deps(deps) self.phys_netlist_tool.add_ninja_deps(deps) self.xrev_tool.add_ninja_deps(deps) self.error_injector_tool.add_ninja_deps(deps) diff --git a/bfasst/ninja_flows/vivado_yosys_impl.py b/bfasst/ninja_flows/vivado_yosys_impl.py index 8aa2bdd49..17d105714 100644 --- a/bfasst/ninja_flows/vivado_yosys_impl.py +++ b/bfasst/ninja_flows/vivado_yosys_impl.py @@ -1,5 +1,6 @@ """Flow to compare reversed netlist to original using yosys.""" from bfasst.ninja_flows.flow import Flow +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.compare.yosys.yosys import Yosys from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.paths import NINJA_FLOWS_PATH @@ -10,25 +11,29 @@ class VivadoYosysImpl(Flow): def __init__(self, design, flow_args=None): super().__init__(design) - self.vivado_tool = self.configure_vivado_tool(design, flow_args) + self.vivado_synth_tool = self.configure_vivado_synth_tool(design, flow_args) + self.vivado_impl_tool = VivadoImpl(design) self.xrev_tool = Xray(design) self.yosys_tool = Yosys(design) def create_rule_snippets(self): - self.vivado_tool.create_rule_snippets() + self.vivado_synth_tool.create_rule_snippets() + self.vivado_impl_tool.create_rule_snippets() self.xrev_tool.create_rule_snippets() self.yosys_tool.create_rule_snippets() def create_build_snippets(self): - self.vivado_tool.create_build_snippets() - self.xrev_tool.create_build_snippets(str(self.vivado_tool.outputs["bitstream"])) + self.vivado_synth_tool.create_build_snippets() + self.vivado_impl_tool.create_build_snippets() + self.xrev_tool.create_build_snippets(str(self.vivado_impl_tool.outputs["bitstream"])) self.yosys_tool.create_build_snippets( - gold_netlist=self.vivado_tool.outputs["impl_verilog"], + gold_netlist=self.vivado_impl_tool.outputs["impl_verilog"], rev_netlist=self.xrev_tool.outputs["xray_netlist"], ) def add_ninja_deps(self, deps): - self.vivado_tool.add_ninja_deps(deps) + self.vivado_synth_tool.add_ninja_deps(deps) + self.vivado_impl_tool.add_ninja_deps(deps) self.xrev_tool.add_ninja_deps(deps) self.yosys_tool.add_ninja_deps(deps) deps.append(NINJA_FLOWS_PATH / "vivado_yosys_impl.py") diff --git a/bfasst/ninja_tools/impl/viv_impl.ninja.mustache b/bfasst/ninja_tools/vivado/impl/viv_impl.ninja.mustache similarity index 100% rename from bfasst/ninja_tools/impl/viv_impl.ninja.mustache rename to bfasst/ninja_tools/vivado/impl/viv_impl.ninja.mustache diff --git a/bfasst/ninja_tools/impl/viv_impl.tcl.mustache b/bfasst/ninja_tools/vivado/impl/viv_impl.tcl.mustache similarity index 100% rename from bfasst/ninja_tools/impl/viv_impl.tcl.mustache rename to bfasst/ninja_tools/vivado/impl/viv_impl.tcl.mustache diff --git a/bfasst/ninja_tools/vivado/impl/vivado_impl.py b/bfasst/ninja_tools/vivado/impl/vivado_impl.py new file mode 100644 index 000000000..f8da8c297 --- /dev/null +++ b/bfasst/ninja_tools/vivado/impl/vivado_impl.py @@ -0,0 +1,71 @@ +"""Tool to create Vivado implementation ninja snippets.""" +import json +import chevron +from bfasst.ninja_tools.vivado.vivado import Vivado +from bfasst.paths import ( + NINJA_VIVADO_IMPL_TOOL_PATH, + NINJA_BUILD_PATH, +) + + +class VivadoImpl(Vivado): + """Tool to create Vivado implementation ninja snippets.""" + + def __init__(self, design, ooc=False): + super().__init__(design, ooc) + self.build_path = self.build_path / "impl" + self._create_build_dir() + + # outputs must be initialized AFTER output paths are set + self._init_outputs() + + def _write_json_file(self): + """Specify implementation arguments in a json file. + Chevron will use the file to fill in the tcl template.""" + impl = { + "part": self.part, + "xdc": str(self.build_path.parent / "synth" / (self.top + ".xdc")) + if not self.ooc + else False, + "bit": str(self.build_path / (self.top + ".bit")) if not self.ooc else False, + "impl_output": str(self.build_path), + "synth_output": str(self.build_path.parent / "synth"), + } + impl_json = json.dumps(impl, indent=4) + + self._json_write(self.build_path / "impl.json", impl_json) + + def _append_build_snippets(self): + """Create ninja snippets for vivado implementation in build.ninja""" + with open(NINJA_VIVADO_IMPL_TOOL_PATH / "viv_impl.ninja.mustache") as f: + impl_ninja = chevron.render( + f, + { + "in_context": not self.ooc, + "impl_output": str(self.build_path), + "synth_output": str(self.build_path.parent / "synth"), + "impl_library": NINJA_VIVADO_IMPL_TOOL_PATH, + "top": self.top, + }, + ) + + with open(NINJA_BUILD_PATH, "a") as f: + f.write(impl_ninja) + + def _init_outputs(self): + self.outputs["impl_tcl"] = self.build_path / "impl.tcl" + self.outputs["impl_json"] = self.build_path / "impl.json" + self.outputs["impl_verilog"] = self.build_path / "viv_impl.v" + self.outputs["impl_edf"] = self.build_path / "viv_impl.edf" + self.outputs["impl_checkpoint"] = self.build_path / "impl.dcp" + self.outputs["utilization"] = self.build_path / "utiliztion.txt" + self.outputs["impl_journal"] = self.build_path / "vivado.jou" + self.outputs["impl_log"] = self.build_path / "vivado.log" + + if not self.ooc: + self.outputs["bitstream"] = self.build_path / (self.top + ".bit") + + def add_ninja_deps(self, deps): + """Add dependencies to the master ninja file that would cause it to rebuild if modified.""" + self._add_ninja_deps_default(deps, __file__) + deps.append(NINJA_VIVADO_IMPL_TOOL_PATH / "viv_impl.ninja.mustache") diff --git a/bfasst/ninja_tools/synth/viv_synth.ninja.mustache b/bfasst/ninja_tools/vivado/synth/viv_synth.ninja.mustache similarity index 100% rename from bfasst/ninja_tools/synth/viv_synth.ninja.mustache rename to bfasst/ninja_tools/vivado/synth/viv_synth.ninja.mustache diff --git a/bfasst/ninja_tools/synth/viv_synth.tcl.mustache b/bfasst/ninja_tools/vivado/synth/viv_synth.tcl.mustache similarity index 100% rename from bfasst/ninja_tools/synth/viv_synth.tcl.mustache rename to bfasst/ninja_tools/vivado/synth/viv_synth.tcl.mustache diff --git a/bfasst/ninja_tools/vivado/synth/vivado_synth.py b/bfasst/ninja_tools/vivado/synth/vivado_synth.py new file mode 100644 index 000000000..3e6dd32b9 --- /dev/null +++ b/bfasst/ninja_tools/vivado/synth/vivado_synth.py @@ -0,0 +1,72 @@ +"""Tool to create Vivado synthesis ninja snippets.""" +import json +import chevron +from bfasst.ninja_tools.vivado.vivado import Vivado +from bfasst.paths import NINJA_BUILD_PATH, NINJA_VIVADO_SYNTH_TOOL_PATH + + +class VivadoSynth(Vivado): + """Tool to create vivado synthesis ninja snippets.""" + + def __init__(self, design, flow_args=None, ooc=False): + super().__init__(design, ooc) + self.flow_args = flow_args + + self.build_path = self.build_path / "synth" + self._create_build_dir() + + # outputs must be initialized AFTER output paths are set + self._init_outputs() + + def _write_json_file(self): + """Specify synthesis arguments in a json file. + Chevron will use this file to fill in the tcl template.""" + synth = { + "part": self.part, + "top": self.top, + "vhdl": self.vhdl, + "vhdl_libs": list(self.vhdl_file_lib_map.items()), + "verilog": self.verilog, + "system_verilog": self.system_verilog, + "io": str(self.build_path / "report_io.txt") if not self.ooc else False, + "synth_output": str(self.build_path), + "flow_args": self.flow_args if self.flow_args else "", + } + synth_json = json.dumps(synth, indent=4) + + self._json_write(self.build_path / "synth.json", synth_json) + + def _append_build_snippets(self): + """Create ninja snippets for vivado synthesis in build.ninja""" + with open(NINJA_VIVADO_SYNTH_TOOL_PATH / "viv_synth.ninja.mustache") as f: + synth_ninja = chevron.render( + f, + { + "in_context": not self.ooc, + "synth_output": str(self.build_path), + "synth_library": NINJA_VIVADO_SYNTH_TOOL_PATH, + "top": self.top, + "verilog": self.verilog, + "system_verilog": self.system_verilog, + }, + ) + + with open(NINJA_BUILD_PATH, "a") as f: + f.write(synth_ninja) + + def _init_outputs(self): + self.outputs["synth_tcl"] = self.build_path / "synth.tcl" + self.outputs["synth_json"] = self.build_path / "synth.json" + self.outputs["synth_edf"] = self.build_path / "viv_synth.edf" + self.outputs["synth_dcp"] = self.build_path / "synth.dcp" + self.outputs["synth_journal"] = self.build_path / "vivado.jou" + self.outputs["synth_log"] = self.build_path / "vivado.log" + + if not self.ooc: + self.outputs["io_report"] = self.build_path / "report_io.txt" + self.outputs["synth_constraints"] = self.build_path / (self.top + ".xdc") + + def add_ninja_deps(self, deps): + """Add dependencies to the master ninja file that would cause it to rebuild if modified""" + self._add_ninja_deps_default(deps, __file__) + deps.append(NINJA_VIVADO_SYNTH_TOOL_PATH / "viv_synth.ninja.mustache") diff --git a/bfasst/ninja_tools/vivado/vivado.py b/bfasst/ninja_tools/vivado/vivado.py index 3f9b43316..0bd10e2a6 100644 --- a/bfasst/ninja_tools/vivado/vivado.py +++ b/bfasst/ninja_tools/vivado/vivado.py @@ -1,54 +1,38 @@ -"""Tool to create Vivado synthesis and implementation ninja snippets.""" -import json +"""Parent tool for vivado synth and impl tools.""" from pathlib import Path +from abc import ABC import chevron -from bfasst import config from bfasst.ninja_tools.tool import Tool -from bfasst.paths import ( - NINJA_IMPL_TOOLS_PATH, - NINJA_BUILD_PATH, - NINJA_SYNTH_TOOLS_PATH, - NINJA_UTILS_PATH, - VIVADO_RULES_PATH, -) -from bfasst.utils import compare_json +from bfasst.paths import NINJA_BUILD_PATH, NINJA_UTILS_PATH, VIVADO_RULES_PATH +from bfasst import config +from bfasst.utils.general import compare_json + from bfasst.yaml_parser import YamlParser -class Vivado(Tool): - """Tool to create Vivado synthesis and implementation ninja snippets.""" +class Vivado(Tool, ABC): + """Parent tool for vivado synth and impl tools.""" - def __init__(self, design, flow_args=None, ooc=False): - super().__init__(design) - self.flow_args = flow_args + # Static method to prevent rule duplication across all children tools + rules_appended_to_build = False + def __init__(self, design, ooc=False): + super().__init__(design) self.ooc = ooc if ooc: self.build_path = self.design_build_path / "ooc" else: self.build_path = self.design_build_path / "in_context" - self.synth_output = self.build_path / "synth" - self.impl_output = self.build_path / "impl" self._create_build_dir() - self.top = YamlParser(self.design_path / "design.yaml").parse_top_module() - # outputs must be initialized AFTER output paths are set - self._init_outputs() - self._read_hdl_files() - self.vhdl_file_lib_map = {} self.__read_vhdl_libs() self.part = config.PART - def _create_build_dir(self): - super()._create_build_dir() - self.synth_output.mkdir(exist_ok=True) - self.impl_output.mkdir(exist_ok=True) - def __read_vhdl_libs(self): if not self.vhdl_libs: return @@ -62,131 +46,45 @@ def __read_vhdl_libs(self): key = str(file) self.vhdl_file_lib_map[key] = Path(lib).name + def _create_build_dir(self): + super()._create_build_dir() + def create_rule_snippets(self): - with open(VIVADO_RULES_PATH, "r") as f: - vivado_ninja = chevron.render( - f, - { - "vivado_path": config.VIVADO_BIN_PATH, - "utils": str(NINJA_UTILS_PATH), - "in_context": not self.ooc, - }, - ) - with open(NINJA_BUILD_PATH, "a") as f: - f.write(vivado_ninja) + if not Vivado.rules_appended_to_build: + with open(VIVADO_RULES_PATH, "r") as f: + vivado_ninja = chevron.render( + f, + { + "vivado_path": config.VIVADO_BIN_PATH, + "utils": str(NINJA_UTILS_PATH), + "in_context": not self.ooc, + }, + ) + with open(NINJA_BUILD_PATH, "a") as f: + f.write(vivado_ninja) + Vivado.rules_appended_to_build = True def create_build_snippets(self): - self.__write_json_files() - self.__append_build_snippets() - - def __write_json_files(self): - self.__write_synth_json() - self.__write_impl_json() - - def __write_synth_json(self): - """Specify synthesis arguments in a json file. - Chevron will use to fill in the tcl template""" - synth = { - "part": self.part, - "verilog": self.verilog, - "system_verilog": self.system_verilog, - "vhdl": self.vhdl, - "vhdl_libs": list(self.vhdl_file_lib_map.items()), - "top": self.top, - "io": str(self.synth_output / "report_io.txt") if not self.ooc else False, - "synth_output": str(self.synth_output), - "flow_args": self.flow_args if self.flow_args else "", - } - synth_json = json.dumps(synth, indent=4) - - # check if the synth json file already exists and compare it to what we're about to write - json_equivalent = compare_json(self.synth_output / "synth.json", synth_json) + self._write_json_file() + self._append_build_snippets() - if not json_equivalent: - with open(self.synth_output / "synth.json", "w") as f: - f.write(synth_json) - - def __write_impl_json(self): - """Specify implementation arguments in json file. - Chevron will use json file to fill in the tcl template""" - impl = { - "part": self.part, - "xdc": str(self.synth_output / (self.top + ".xdc")) if not self.ooc else False, - "bit": str(self.impl_output / (self.top + ".bit")) if not self.ooc else False, - "impl_output": str(self.impl_output), - "synth_output": str(self.synth_output), - } - impl_json = json.dumps(impl, indent=4) - - # check if the impl json file already exists and compare it to what we're about to write - json_equivalent = compare_json(self.impl_output / "impl.json", impl_json) + def _json_write(self, old_path, new_string): + """Write the json file for the tool, if the new string + does not match the json already in existence.""" + json_equivalent = compare_json(old_path, new_string) if not json_equivalent: - with open(self.impl_output / "impl.json", "w") as f: - f.write(impl_json) - - def __append_build_snippets(self): - self.__append_synth_snippets() - self.__append_impl_snippets() - - def __append_synth_snippets(self): - """Create ninja snippets for vivado synthesis in build.ninja""" - with open(NINJA_SYNTH_TOOLS_PATH / "viv_synth.ninja.mustache") as f: - synth_ninja = chevron.render( - f, - { - "in_context": not self.ooc, - "synth_output": str(self.synth_output), - "synth_library": NINJA_SYNTH_TOOLS_PATH, - "top": self.top, - "verilog": self.verilog, - "system_verilog": self.system_verilog, - }, - ) - - with open(NINJA_BUILD_PATH, "a") as f: - f.write(synth_ninja) - - def __append_impl_snippets(self): - """Create ninja snippets for vivado implementation in build.ninja""" - with open(NINJA_IMPL_TOOLS_PATH / "viv_impl.ninja.mustache") as f: - impl_ninja = chevron.render( - f, - { - "in_context": not self.ooc, - "impl_output": str(self.impl_output), - "synth_output": str(self.synth_output), - "impl_library": NINJA_IMPL_TOOLS_PATH, - "top": self.top, - }, - ) - - with open(NINJA_BUILD_PATH, "a") as f: - f.write(impl_ninja) + with open(old_path, "w") as f: + f.write(new_string) + + def _write_json_file(self): + pass + + def _append_build_snippets(self): + pass + + def add_ninja_deps(self): + pass def _init_outputs(self): - self.outputs["synth_tcl"] = self.synth_output / "synth.tcl" - self.outputs["impl_tcl"] = self.impl_output / "impl.tcl" - self.outputs["synth_json"] = self.synth_output / "synth.json" - self.outputs["impl_json"] = self.impl_output / "impl.json" - self.outputs["synth_edf"] = self.synth_output / "viv_synth.edf" - self.outputs["synth_checkpoint"] = self.synth_output / "synth.dcp" - self.outputs["impl_verilog"] = self.impl_output / "viv_impl.v" - self.outputs["impl_edf"] = self.impl_output / "viv_impl.edf" - self.outputs["impl_checkpoint"] = self.impl_output / "impl.dcp" - self.outputs["utilization"] = self.impl_output / "utilization.txt" - self.outputs["impl_journal"] = self.impl_output / "vivado.jou" - self.outputs["impl_log"] = self.impl_output / "vivado.log" - self.outputs["synth_journal"] = self.synth_output / "vivado.jou" - self.outputs["synth_log"] = self.synth_output / "vivado.log" - - if not self.ooc: - self.outputs["io_report"] = self.synth_output / "report_io.txt" - self.outputs["synth_constraints"] = self.synth_output / (self.top + ".xdc") - self.outputs["bitstream"] = self.impl_output / (self.top + ".bit") - - def add_ninja_deps(self, deps): - """Add dependencies to the master ninja file that would cause it to rebuild if modified""" - self._add_ninja_deps_default(deps, __file__) - deps.append(NINJA_SYNTH_TOOLS_PATH / "viv_synth.ninja.mustache") - deps.append(NINJA_IMPL_TOOLS_PATH / "viv_impl.ninja.mustache") + pass diff --git a/bfasst/paths.py b/bfasst/paths.py index eb104e3ba..d4ee35f43 100644 --- a/bfasst/paths.py +++ b/bfasst/paths.py @@ -19,10 +19,10 @@ NINJA_UTILS_PATH = BFASST_PATH / "ninja_utils" NINJA_FLOWS_PATH = BFASST_PATH / "ninja_flows" -NINJA_SYNTH_TOOLS_PATH = NINJA_TOOLS_PATH / "synth" -NINJA_IMPL_TOOLS_PATH = NINJA_TOOLS_PATH / "impl" -VIVADO_RULES_PATH = NINJA_TOOLS_PATH / "vivado" / "vivado_rules.ninja.mustache" NINJA_VIVADO_TOOLS_PATH = NINJA_TOOLS_PATH / "vivado" +NINJA_VIVADO_SYNTH_TOOL_PATH = NINJA_VIVADO_TOOLS_PATH / "synth" +NINJA_VIVADO_IMPL_TOOL_PATH = NINJA_VIVADO_TOOLS_PATH / "impl" +VIVADO_RULES_PATH = NINJA_TOOLS_PATH / "vivado" / "vivado_rules.ninja.mustache" REV_BIT_TOOLS_PATH = NINJA_TOOLS_PATH / "rev_bit" NINJA_TRANSFORM_TOOLS_PATH = NINJA_TOOLS_PATH / "transform" diff --git a/test/flows/test_vivado_bit_analysis_flow.py b/test/flows/test_vivado_bit_analysis_flow.py index 807a902bb..214b5b7ff 100644 --- a/test/flows/test_vivado_bit_analysis_flow.py +++ b/test/flows/test_vivado_bit_analysis_flow.py @@ -10,6 +10,8 @@ from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.ninja_tools.transform.netlist_cleanup import NetlistCleanupTool from bfasst.ninja_tools.transform.netlist_phys_to_logical import NetlistPhysToLogicalTool +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.vivado.vivado import Vivado from bfasst.paths import ( DESIGNS_PATH, @@ -26,6 +28,10 @@ def setUpClass(cls): # overwrite the build file so it is not appended to incorrectly create_build_file() + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + Vivado.rules_appended_to_build = False + cls.flow = VivadoBitAnalysis(DESIGNS_PATH / "byu/alu") cls.flow.create_rule_snippets() cls.flow.create_build_snippets() @@ -55,7 +61,8 @@ def test_add_ninja_deps(self): expected = ["foo", "bar"] Xray(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) - Vivado(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoSynth(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoImpl(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) NetlistCleanupTool(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) NetlistPhysToLogicalTool(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) diff --git a/test/flows/test_vivado_conformal_flow.py b/test/flows/test_vivado_conformal_flow.py index 074b229c0..69efb4e00 100644 --- a/test/flows/test_vivado_conformal_flow.py +++ b/test/flows/test_vivado_conformal_flow.py @@ -6,9 +6,11 @@ import unittest from bfasst.ninja_flows.flow_utils import create_build_file from bfasst.ninja_flows.vivado_conformal import VivadoConformal -from bfasst.ninja_tools.vivado.vivado import Vivado +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.ninja_tools.compare.conformal.conformal import Conformal +from bfasst.ninja_tools.vivado.vivado import Vivado from bfasst.paths import ( DESIGNS_PATH, NINJA_BUILD_PATH, @@ -24,6 +26,10 @@ def setUpClass(cls) -> None: # overwrite the build file so it is not appended to incorrectly create_build_file() + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + Vivado.rules_appended_to_build = False + cls.flow = VivadoConformal(DESIGNS_PATH / "byu/alu") cls.flow.create_rule_snippets() cls.flow.create_build_snippets() @@ -46,11 +52,14 @@ def test_build_snippets_exist(self): self.assertEqual(build_statement_count, 8) def test_add_ninja_deps(self): + """Test that the flow adds the correct dependencies to the ninja build file + for reconfiguration""" observed = ["foo", "bar"] self.flow.add_ninja_deps(observed) expected = ["foo", "bar"] Xray(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) - Vivado(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoSynth(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoImpl(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) Conformal(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) expected.append(NINJA_FLOWS_PATH / "vivado_conformal.py") observed = sorted([str(s) for s in observed]) diff --git a/test/flows/test_vivado_flow.py b/test/flows/test_vivado_flow.py index 6d0374493..18ec7e3a7 100644 --- a/test/flows/test_vivado_flow.py +++ b/test/flows/test_vivado_flow.py @@ -9,6 +9,8 @@ from bfasst.ninja_flows.flow_utils import create_build_file from bfasst.ninja_flows.vivado import Vivado from bfasst.ninja_tools.vivado.vivado import Vivado as VivadoTool +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.paths import ( DESIGNS_PATH, NINJA_BUILD_PATH, @@ -25,6 +27,10 @@ def setUpClass(cls): # overwrite the build file so it is not appended to incorrectly create_build_file() + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + VivadoTool.rules_appended_to_build = False + cls.flow = Vivado(DESIGNS_PATH / "byu/alu") cls.flow.create_rule_snippets() cls.flow.create_build_snippets() @@ -42,37 +48,41 @@ def test_rule_snippets_exist(self): def test_json_exist(self): # test that the json files for synth and impl templates exist - self.assertTrue((self.flow.vivado_tool.synth_output / "synth.json").exists()) - self.assertTrue((self.flow.vivado_tool.impl_output / "impl.json").exists()) + self.assertTrue((self.flow.vivado_synth_tool.build_path / "synth.json").exists()) + self.assertTrue((self.flow.vivado_impl_tool.build_path / "impl.json").exists()) def test_tcl_json_accurate(self): """Test that the json files for synth and impl templates are accurate.""" synth_dict = { - "part": self.flow.vivado_tool.part, - "verilog": self.flow.vivado_tool.verilog, - "system_verilog": self.flow.vivado_tool.system_verilog, + "part": self.flow.vivado_synth_tool.part, + "verilog": self.flow.vivado_synth_tool.verilog, + "system_verilog": self.flow.vivado_synth_tool.system_verilog, "vhdl": [], "vhdl_libs": [], - "top": self.flow.vivado_tool.top, - "io": str(self.flow.vivado_tool.synth_output / "report_io.txt"), - "synth_output": str(self.flow.vivado_tool.synth_output), + "top": self.flow.vivado_synth_tool.top, + "io": str(self.flow.vivado_synth_tool.build_path / "report_io.txt"), + "synth_output": str(self.flow.vivado_synth_tool.build_path), "flow_args": "", } expected_synth_json = json.dumps(synth_dict, indent=4) self.assertTrue( - compare_json(self.flow.vivado_tool.synth_output / "synth.json", expected_synth_json) + compare_json(self.flow.vivado_synth_tool.build_path / "synth.json", expected_synth_json) ) impl_dict = { - "part": self.flow.vivado_tool.part, - "xdc": str(self.flow.vivado_tool.synth_output / (self.flow.vivado_tool.top + ".xdc")), - "bit": str(self.flow.vivado_tool.impl_output / (self.flow.vivado_tool.top + ".bit")), - "impl_output": str(self.flow.vivado_tool.impl_output), - "synth_output": str(self.flow.vivado_tool.synth_output), + "part": self.flow.vivado_synth_tool.part, + "xdc": str( + self.flow.vivado_synth_tool.build_path / (self.flow.vivado_synth_tool.top + ".xdc") + ), + "bit": str( + self.flow.vivado_impl_tool.build_path / (self.flow.vivado_synth_tool.top + ".bit") + ), + "impl_output": str(self.flow.vivado_impl_tool.build_path), + "synth_output": str(self.flow.vivado_synth_tool.build_path), } expected_impl_json = json.dumps(impl_dict, indent=4) self.assertTrue( - compare_json(self.flow.vivado_tool.impl_output / "impl.json", expected_impl_json) + compare_json(self.flow.vivado_impl_tool.build_path / "impl.json", expected_impl_json) ) def test_build_snippets_exist(self): @@ -90,7 +100,8 @@ def test_add_ninja_deps(self): "foo", "bar", ] - VivadoTool(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoSynth(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoImpl(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) expected.append(NINJA_FLOWS_PATH / "vivado.py") self.assertEqual(observed, expected) diff --git a/test/flows/test_vivado_ooc_flow.py b/test/flows/test_vivado_ooc_flow.py index 81cb3b2d5..402954465 100644 --- a/test/flows/test_vivado_ooc_flow.py +++ b/test/flows/test_vivado_ooc_flow.py @@ -2,6 +2,8 @@ import json import unittest from bfasst.ninja_flows.vivado_ooc import VivadoOoc +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.vivado.vivado import Vivado from bfasst.paths import ( DESIGNS_PATH, @@ -20,6 +22,10 @@ def setUpClass(cls): with open(NINJA_BUILD_PATH, "w") as f: f.write("") + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + Vivado.rules_appended_to_build = False + cls.flow = VivadoOoc(DESIGNS_PATH / "byu/alu") cls.flow.create_rule_snippets() cls.flow.create_build_snippets() @@ -38,31 +44,31 @@ def test_rule_snippets_exist(self): def test_tcl_json_accurate(self): """Test that the json file used to template the tcl file is accurate""" synth_dict = { - "part": self.flow.vivado_tool.part, - "verilog": self.flow.vivado_tool.verilog, - "system_verilog": self.flow.vivado_tool.system_verilog, + "part": self.flow.vivado_synth_tool.part, + "verilog": self.flow.vivado_synth_tool.verilog, + "system_verilog": self.flow.vivado_synth_tool.system_verilog, "vhdl": [], "vhdl_libs": [], - "top": self.flow.vivado_tool.top, + "top": self.flow.vivado_synth_tool.top, "io": False, - "synth_output": str(self.flow.vivado_tool.synth_output), + "synth_output": str(self.flow.vivado_synth_tool.build_path), "flow_args": "", } expected_synth_json = json.dumps(synth_dict, indent=4) self.assertTrue( - compare_json(self.flow.vivado_tool.synth_output / "synth.json", expected_synth_json) + compare_json(self.flow.vivado_synth_tool.build_path / "synth.json", expected_synth_json) ) impl_dict = { - "part": self.flow.vivado_tool.part, + "part": self.flow.vivado_synth_tool.part, "xdc": False, "bit": False, - "impl_output": str(self.flow.vivado_tool.impl_output), - "synth_output": str(self.flow.vivado_tool.synth_output), + "impl_output": str(self.flow.vivado_impl_tool.build_path), + "synth_output": str(self.flow.vivado_synth_tool.build_path), } expected_impl_json = json.dumps(impl_dict, indent=4) self.assertTrue( - compare_json(self.flow.vivado_tool.impl_output / "impl.json", expected_impl_json) + compare_json(self.flow.vivado_impl_tool.build_path / "impl.json", expected_impl_json) ) def test_build_snippets_exist(self): @@ -80,7 +86,8 @@ def test_add_ninja_deps(self): "foo", "bar", ] - Vivado(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoSynth(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoImpl(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) expected.append(NINJA_FLOWS_PATH / "vivado_ooc.py") expected.append(NINJA_FLOWS_PATH / "vivado.py") diff --git a/test/flows/test_vivado_phys_netlist.py b/test/flows/test_vivado_phys_netlist.py index 4daaec206..698f62fcc 100644 --- a/test/flows/test_vivado_phys_netlist.py +++ b/test/flows/test_vivado_phys_netlist.py @@ -8,6 +8,8 @@ from bfasst.ninja_flows.flow_utils import create_build_file from bfasst.ninja_flows.vivado_phys_netlist import VivadoPhysNetlist from bfasst.ninja_tools.transform.phys_netlist import PhysNetlist +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.vivado.vivado import Vivado from bfasst.paths import ( DESIGNS_PATH, @@ -24,6 +26,10 @@ def setUpClass(cls): # overwrite the build file so it is not appended to incorrectly create_build_file() + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + Vivado.rules_appended_to_build = False + cls.flow = VivadoPhysNetlist(DESIGNS_PATH / "byu/alu") cls.flow.create_rule_snippets() cls.flow.create_build_snippets() @@ -54,7 +60,8 @@ def test_add_ninja_deps(self): "foo", "bar", ] - Vivado(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoSynth(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoImpl(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) PhysNetlist(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) expected.append(NINJA_FLOWS_PATH / "vivado_phys_netlist.py") diff --git a/test/flows/test_vivado_phys_netlist_cmp_flow.py b/test/flows/test_vivado_phys_netlist_cmp_flow.py index 27f4ba8b9..9a719c8b6 100644 --- a/test/flows/test_vivado_phys_netlist_cmp_flow.py +++ b/test/flows/test_vivado_phys_netlist_cmp_flow.py @@ -10,6 +10,8 @@ from bfasst.ninja_tools.compare.structural.structural import Structural from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.ninja_tools.transform.phys_netlist import PhysNetlist +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.vivado.vivado import Vivado from bfasst.paths import ( DESIGNS_PATH, @@ -26,6 +28,10 @@ def setUpClass(cls): # overwrite the build file so it is not appended to incorrectly create_build_file() + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + Vivado.rules_appended_to_build = False + cls.flow = VivadoPhysNetlistCmp(DESIGNS_PATH / "byu/alu") cls.flow.create_rule_snippets() cls.flow.create_build_snippets() @@ -58,7 +64,8 @@ def test_add_ninja_deps(self): "foo", "bar", ] - Vivado(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoSynth(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoImpl(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) PhysNetlist(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) Xray(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) Structural(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) diff --git a/test/flows/test_vivado_phys_netlist_xrev_flow.py b/test/flows/test_vivado_phys_netlist_xrev_flow.py index 00fdbca1e..fb7f7edd7 100644 --- a/test/flows/test_vivado_phys_netlist_xrev_flow.py +++ b/test/flows/test_vivado_phys_netlist_xrev_flow.py @@ -9,6 +9,8 @@ from bfasst.ninja_flows.vivado_phys_netlist_xrev import VivadoPhysNetlistXrev from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.ninja_tools.transform.phys_netlist import PhysNetlist +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.vivado.vivado import Vivado from bfasst.paths import ( DESIGNS_PATH, @@ -25,6 +27,10 @@ def setUpClass(cls): # overwrite the build file so it is not appended to incorrectly create_build_file() + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + Vivado.rules_appended_to_build = False + cls.flow = VivadoPhysNetlistXrev(DESIGNS_PATH / "byu/alu") cls.flow.create_rule_snippets() cls.flow.create_build_snippets() @@ -56,7 +62,8 @@ def test_add_ninja_deps(self): "foo", "bar", ] - Vivado(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoSynth(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoImpl(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) PhysNetlist(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) Xray(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) expected.append(NINJA_FLOWS_PATH / "vivado_phys_netlist_xrev.py") diff --git a/test/flows/test_vivado_structural_error_injection_flow.py b/test/flows/test_vivado_structural_error_injection_flow.py index 37ff35588..4a1b671db 100644 --- a/test/flows/test_vivado_structural_error_injection_flow.py +++ b/test/flows/test_vivado_structural_error_injection_flow.py @@ -11,6 +11,8 @@ from bfasst.ninja_tools.rev_bit.xray import Xray from bfasst.ninja_tools.transform.error_injector import ErrorInjector from bfasst.ninja_tools.transform.phys_netlist import PhysNetlist +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.vivado.vivado import Vivado from bfasst.paths import ( DESIGNS_PATH, @@ -27,6 +29,10 @@ def setUpClass(cls): # overwrite the build file so it is not appended to incorrectly create_build_file() + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + Vivado.rules_appended_to_build = False + cls.flow = VivadoStructuralErrorInjection(DESIGNS_PATH / "byu/alu") cls.flow.create_rule_snippets() cls.flow.create_build_snippets() @@ -61,7 +67,8 @@ def test_add_ninja_deps(self): "bar", ] desing_path = DESIGNS_PATH / "byu/alu" - Vivado(desing_path).add_ninja_deps(expected) + VivadoSynth(desing_path).add_ninja_deps(expected) + VivadoImpl(desing_path).add_ninja_deps(expected) ErrorInjector(desing_path).add_ninja_deps(expected) PhysNetlist(desing_path).add_ninja_deps(expected) Xray(desing_path).add_ninja_deps(expected) diff --git a/test/flows/test_vivado_yosys_impl_flow.py b/test/flows/test_vivado_yosys_impl_flow.py index 57cb78116..eaab7e234 100644 --- a/test/flows/test_vivado_yosys_impl_flow.py +++ b/test/flows/test_vivado_yosys_impl_flow.py @@ -9,6 +9,8 @@ from bfasst.ninja_flows.vivado_yosys_impl import VivadoYosysImpl from bfasst.ninja_tools.compare.yosys.yosys import Yosys from bfasst.ninja_tools.rev_bit.xray import Xray +from bfasst.ninja_tools.vivado.synth.vivado_synth import VivadoSynth +from bfasst.ninja_tools.vivado.impl.vivado_impl import VivadoImpl from bfasst.ninja_tools.vivado.vivado import Vivado from bfasst.paths import DESIGNS_PATH, NINJA_BUILD_PATH, NINJA_FLOWS_PATH @@ -21,6 +23,10 @@ def setUpClass(cls) -> None: # overwrite the build file so it is not appended to incorrectly create_build_file() + # before all vivado based flows, make sure the Vivado parent class is + # allowed to create its rule snippets + Vivado.rules_appended_to_build = False + cls.design_shortname = DESIGNS_PATH / "byu/alu" cls.flow = VivadoYosysImpl(cls.design_shortname) cls.flow.create_rule_snippets() @@ -44,11 +50,14 @@ def test_build_snippets_exist(self): self.assertEqual(build_statement_count, 9) def test_add_ninja_deps(self): + """Test that the flow adds the correct dependencies to the ninja build file + for reconfiguration""" observed = ["foo", "bar"] self.flow.add_ninja_deps(observed) expected = ["foo", "bar"] Xray(self.design_shortname).add_ninja_deps(expected) - Vivado(self.design_shortname).add_ninja_deps(expected) + VivadoSynth(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) + VivadoImpl(DESIGNS_PATH / "byu/alu").add_ninja_deps(expected) Yosys(self.design_shortname).add_ninja_deps(expected) expected.append(NINJA_FLOWS_PATH / "vivado_yosys_impl.py") # observed.sort()