From d1d1187c10e0945b9d6fcccf34870b2e4e378d6e Mon Sep 17 00:00:00 2001 From: John Demme Date: Fri, 18 Nov 2022 15:58:37 -0800 Subject: [PATCH] [PyCDE][Mostly NFC] Refactor the way passes are run Only functional change is removing support for running the design partition pass. --- frontends/PyCDE/src/pycde/system.py | 62 +++++++++++++------ frontends/PyCDE/test/design_partition.py | 76 ------------------------ 2 files changed, 43 insertions(+), 95 deletions(-) delete mode 100644 frontends/PyCDE/test/design_partition.py diff --git a/frontends/PyCDE/src/pycde/system.py b/frontends/PyCDE/src/pycde/system.py index cf1d3178fc75..b79431b789ed 100644 --- a/frontends/PyCDE/src/pycde/system.py +++ b/frontends/PyCDE/src/pycde/system.py @@ -155,19 +155,6 @@ def __exit__(self, exc_type, exc_value, traceback): def body(self): return self.mod.body - def _passes(self, partition): - tops = ",".join( - [self._op_cache.get_pyproxy_symbol(m) for m in self.top_modules]) - verilog_file = self.name + ".sv" - tcl_file = self.name + ".tcl" - self.files.add(self._output_directory / verilog_file) - self.files.add(self._output_directory / tcl_file) - partition_str = "msft-partition," if partition else "" - return self.PASSES.format(tops=tops, - partition=partition_str, - verilog_file=verilog_file, - tcl_file=tcl_file).strip() - def print(self, *argv, **kwargs): self.mod.operation.print(*argv, **kwargs) @@ -213,20 +200,57 @@ def get_instance(self, self) return self._instance_roots[key] - def run_passes(self, partition=False): + PASS_PHASES = [ + # First, run all the passes with callbacks into pycde. + "builtin.module(esi-connect-services)", + lambda sys: sys.generate(), + # After all of the pycde code has been executed, we have all the types + # defined so we can go through and output the typedefs delcarations. + lambda sys: types.declare_types(sys.mod), + "builtin.module(lower-hwarith-to-hw, msft-lower-constructs, msft-lower-instances)", + "builtin.module(esi-emit-collateral{{tops={tops} schema-file=schema.capnp}})", + "builtin.module(lower-msft-to-hw{{verilog-file={verilog_file}}})", + "builtin.module(hw.module(lower-seq-hlmem))", + # "cse", + "builtin.module(lower-esi-to-physical, lower-esi-ports, lower-esi-to-hw)", + "builtin.module(convert-fsm-to-sv)", + "builtin.module(lower-seq-to-sv)", + "builtin.module(cse)", + "builtin.module(hw.module(prettify-verilog), hw.module(hw-cleanup))", + "builtin.module(msft-export-tcl{{tops={tops} tcl-file={tcl_file}}})" + ] + + def run_passes(self, debug=False): if self.passed: return if len(self._generate_queue) > 0: print("WARNING: running lowering passes on partially generated design!", file=sys.stderr) - # By now, we have all the types defined so we can go through and output the - # typedefs delcarations. - types.declare_types(self.mod) + tops = ",".join( + [self._op_cache.get_pyproxy_symbol(m) for m in self.top_modules]) + verilog_file = self.name + ".sv" + tcl_file = self.name + ".tcl" + self.files.add(self._output_directory / verilog_file) + self.files.add(self._output_directory / tcl_file) - pm = mlir.passmanager.PassManager.parse(self._passes(partition)) self._op_cache.release_ops() - pm.run(self.mod) + for idx, phase in enumerate(self.PASS_PHASES): + try: + if isinstance(phase, str): + passes = phase.format(tops=tops, + verilog_file=verilog_file, + tcl_file=tcl_file).strip() + pm = mlir.passmanager.PassManager.parse(passes) + pm.run(self.mod) + else: + phase(self) + except RuntimeError as err: + sys.stderr.write(f"Exception while executing phase {phase}.\n") + raise err + self._op_cache.release_ops() + if debug: + open(f"after_phase_{idx}.mlir", "w").write(str(self.mod)) self.passed = True def emit_outputs(self): diff --git a/frontends/PyCDE/test/design_partition.py b/frontends/PyCDE/test/design_partition.py deleted file mode 100644 index c29257425339..000000000000 --- a/frontends/PyCDE/test/design_partition.py +++ /dev/null @@ -1,76 +0,0 @@ -# RUN: rm -rf %t -# RUN: %PYTHON% %s %t 2>&1 | FileCheck %s - -import pycde -from pycde import (Input, Output, module, externmodule, generator, types) -from pycde.module import DesignPartition -import sys - - -@module -class TopLevel: - x = Input(types.i32) - y = Output(types.i32) - - @generator - def construct(mod): - TopLevel.part1 = DesignPartition("part1") - Plus("Plus1", a=mod.x, b=mod.x, partition=TopLevel.part1) - mod.y = PlusPipeline(a=mod.x).y - - -@externmodule -class Plus: - a = Input(types.i32) - b = Input(types.i32) - y = Output(types.i32) - - def __init__(self, name: str = None) -> None: - if name is not None: - self.instance_name = name - - -@module -class PlusPipeline: - a = Input(types.i32) - y = Output(types.i32) - - @generator - def construct(mod): - p1 = Plus(a=mod.a, b=mod.a) - p2 = Plus(a=p1.y, b=mod.a, partition=TopLevel.part1) - p3 = Plus(a=p2.y, b=mod.a) - mod.y = p3.y - - -s = pycde.System([TopLevel], - name="DesignPartitionTest", - output_directory=sys.argv[1]) - -print("Generating...") -s.generate() - -inst = s.get_instance(TopLevel) -inst.walk(lambda i: print(i)) - -s.cleanup() -s.print() -s.run_passes(partition=True) -s.emit_outputs() -print("************") -print("** Post pass/emit") -s.print() - -# CHECK-LABEL: msft.module @TopLevel -# CHECK: msft.partition @part1, "part1" -# CHECK: %Plus1.y = msft.instance @Plus1 @Plus(%x, %x) {targetDesignPartition = @TopLevel::@part1} : (i32, i32) -> i32 -# CHECK: %PlusPipeline.y = msft.instance @PlusPipeline @PlusPipeline(%x) : (i32) -> i32 -# CHECK: msft.output %PlusPipeline.y : i32 - -# CHECK-LABEL: ** Post pass/emit -# CHECK-LABEL: hw.module @part1 -# CHECK: hw.instance "Plus1" sym @Plus1 @Plus -# CHECK: hw.instance "PlusPipeline.Plus_1" sym @PlusPipeline.Plus_1 @Plus -# CHECK-LABEL: hw.module @TopLevel -# CHECK: hw.instance "part1" sym @part1 @part1 -# CHECK: hw.instance "PlusPipeline" sym @PlusPipeline @PlusPipeline