From c8c19f6adae89da82f0000cf2a0d54f48d3657f5 Mon Sep 17 00:00:00 2001 From: hailong Date: Fri, 28 Jun 2024 18:16:44 +0800 Subject: [PATCH] [Moore] Add AssignedVarOp and MergeAssignments pass. --- include/circt/Dialect/Moore/MooreOps.td | 14 +++- include/circt/Dialect/Moore/MoorePasses.h | 1 + include/circt/Dialect/Moore/MoorePasses.td | 10 +++ lib/Dialect/Moore/MooreOps.cpp | 8 +++ lib/Dialect/Moore/Transforms/CMakeLists.txt | 1 + .../Moore/Transforms/MergeAssignments.cpp | 68 +++++++++++++++++++ test/Dialect/Moore/merge-assignments.mlir | 21 ++++++ tools/circt-verilog/circt-verilog.cpp | 1 + 8 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 lib/Dialect/Moore/Transforms/MergeAssignments.cpp create mode 100644 test/Dialect/Moore/merge-assignments.mlir diff --git a/include/circt/Dialect/Moore/MooreOps.td b/include/circt/Dialect/Moore/MooreOps.td index e7103eb6a1ef..e71074e8b4de 100644 --- a/include/circt/Dialect/Moore/MooreOps.td +++ b/include/circt/Dialect/Moore/MooreOps.td @@ -249,11 +249,23 @@ def NetOp : MooreOp<"net", [ ); let results = (outs Res:$result); let assemblyFormat = [{ - ``custom($name) $kind ($assignment^)? attr-dict + `` custom($name) $kind ($assignment^)? attr-dict `:` type($result) }]; } +def AssignedVarOp : MooreOp<"assigned_variable", [ + DeclareOpInterfaceMethods, + TypesMatchWith<"input value and variable types match", + "result", "input", "cast($_self).getNestedType()"> +]> { + let arguments = (ins StrAttr:$name, UnpackedType:$input); + let results = (outs Res:$result); + let assemblyFormat = [{ + `` custom($name) $input attr-dict `:` type($result) + }]; +} + def ReadOp : MooreOp<"read", [ DeclareOpInterfaceMethods, TypesMatchWith<"input and result types match", diff --git a/include/circt/Dialect/Moore/MoorePasses.h b/include/circt/Dialect/Moore/MoorePasses.h index c03353ea9bdd..7f75187c369d 100644 --- a/include/circt/Dialect/Moore/MoorePasses.h +++ b/include/circt/Dialect/Moore/MoorePasses.h @@ -22,6 +22,7 @@ namespace moore { #define GEN_PASS_DECL #include "circt/Dialect/Moore/MoorePasses.h.inc" +std::unique_ptr createMergeAssignmentsPass(); std::unique_ptr createSimplifyProceduresPass(); std::unique_ptr createLowerConcatRefPass(); diff --git a/include/circt/Dialect/Moore/MoorePasses.td b/include/circt/Dialect/Moore/MoorePasses.td index 2adfb950303d..de09156a47ee 100644 --- a/include/circt/Dialect/Moore/MoorePasses.td +++ b/include/circt/Dialect/Moore/MoorePasses.td @@ -15,6 +15,16 @@ include "mlir/Pass/PassBase.td" +def MergeAssignments : Pass<"moore-merge-assignments", "moore::SVModuleOp"> { + let summary = "Merge declarations and assignments"; + let description = [{ + Find easy uses of declaration and assignment and merge them into + assigned_variable. That allows the MooreToCore lowering to look for + assigned_variable to create an hw.wire. + }]; + let constructor = "circt::moore::createMergeAssignmentsPass()"; +} + def SimplifyProcedures : Pass<"moore-simplify-procedures", "moore::SVModuleOp"> { let summary = "Simplify procedures"; let description = [{ diff --git a/lib/Dialect/Moore/MooreOps.cpp b/lib/Dialect/Moore/MooreOps.cpp index 50c4755d72dd..ed765a45db3f 100644 --- a/lib/Dialect/Moore/MooreOps.cpp +++ b/lib/Dialect/Moore/MooreOps.cpp @@ -273,6 +273,14 @@ void NetOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) { setNameFn(getResult(), getName()); } +//===----------------------------------------------------------------------===// +// AssignedVarOp +//===----------------------------------------------------------------------===// + +void AssignedVarOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) { + setNameFn(getResult(), getName()); +} + //===----------------------------------------------------------------------===// // ConstantOp //===----------------------------------------------------------------------===// diff --git a/lib/Dialect/Moore/Transforms/CMakeLists.txt b/lib/Dialect/Moore/Transforms/CMakeLists.txt index 1c69117d9e45..2500669b4776 100644 --- a/lib/Dialect/Moore/Transforms/CMakeLists.txt +++ b/lib/Dialect/Moore/Transforms/CMakeLists.txt @@ -1,5 +1,6 @@ add_circt_dialect_library(CIRCTMooreTransforms LowerConcatRef.cpp +MergeAssignments.cpp SimplifyProcedures.cpp diff --git a/lib/Dialect/Moore/Transforms/MergeAssignments.cpp b/lib/Dialect/Moore/Transforms/MergeAssignments.cpp new file mode 100644 index 000000000000..639510b1b263 --- /dev/null +++ b/lib/Dialect/Moore/Transforms/MergeAssignments.cpp @@ -0,0 +1,68 @@ +//===- MergeAssignments.cpp - Merge declaration and assignment ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the MergeAssignments pass. +// Find easy uses of declaration and assignments and merge them into +// assigned_variable. Easy use represents the declaration doesn't be performed +// bit slice. Like bit [127:0] b; assign b = 128'b0; +// +//===----------------------------------------------------------------------===// + +#include "circt/Dialect/Moore/MooreOps.h" +#include "circt/Dialect/Moore/MoorePasses.h" +#include "mlir/IR/Dialect.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/TypeSwitch.h" + +namespace circt { +namespace moore { +#define GEN_PASS_DEF_MERGEASSIGNMENTS +#include "circt/Dialect/Moore/MoorePasses.h.inc" +} // namespace moore +} // namespace circt + +using namespace circt; +using namespace moore; + +namespace { +struct MergeAssignmentsPass + : public circt::moore::impl::MergeAssignmentsBase { + void runOnOperation() override; +}; +} // namespace + +std::unique_ptr circt::moore::createMergeAssignmentsPass() { + return std::make_unique(); +} + +// Only collect the easy declaration and its value at module level. +static void collectAssignmets(SVModuleOp moduleOp, + llvm::MapVector &assignments) { + moduleOp->walk([&](ContinuousAssignOp op) { + if (auto varOp = op.getDst().getDefiningOp()) + assignments[varOp] = op.getSrc(); + }); +} + +void MergeAssignmentsPass::runOnOperation() { + OpBuilder builder(&getContext()); + + // Use to collect the easy declaration and its value. + llvm::MapVector assignments; + + collectAssignmets(getOperation(), assignments); + for (auto assignment : assignments) { + auto varName = + assignment.first.getDefiningOp()->getAttrOfType("name"); + + builder.setInsertionPointAfterValue(assignment.first); + builder.create(assignment.first.getLoc(), + assignment.first.getType(), varName, + assignment.second); + } +} diff --git a/test/Dialect/Moore/merge-assignments.mlir b/test/Dialect/Moore/merge-assignments.mlir new file mode 100644 index 000000000000..8bc1ffb8250a --- /dev/null +++ b/test/Dialect/Moore/merge-assignments.mlir @@ -0,0 +1,21 @@ +// RUN: circt-opt --moore-merge-assignments %s | FileCheck %s + +// CHECK-LABEL: moore.module @Foo() +moore.module @Foo() { + // CHECK: %a = moore.variable : + // CHECK: %a_0 = moore.assigned_variable name "a" %0 : + %a = moore.variable : + + // CHECK: %b = moore.variable : + // CHECK: %b_1 = moore.assigned_variable name "b" %2 : + %b = moore.variable : + + %0 = moore.constant 32 : i32 + moore.assign %a, %0 : i32 + %1 = moore.constant 32 : i32 + %2 = moore.conversion %1 : !moore.i32 -> !moore.l32 + moore.assign %b, %2 : l32 + moore.output + +} + diff --git a/tools/circt-verilog/circt-verilog.cpp b/tools/circt-verilog/circt-verilog.cpp index d439179d7617..4b9fcf92315a 100644 --- a/tools/circt-verilog/circt-verilog.cpp +++ b/tools/circt-verilog/circt-verilog.cpp @@ -224,6 +224,7 @@ static LogicalResult populateMooreTransforms(mlir::PassManager &pm) { modulePM.addPass(moore::createLowerConcatRefPass()); modulePM.addPass(moore::createSimplifyProceduresPass()); pm.addPass(mlir::createMem2Reg()); + modulePM.addPass(moore::createMergeAssignmentsPass()); // TODO: like dedup pass. return success();