Skip to content

Commit f25eebe

Browse files
authored
[Conversion] Add ConvertToLLVM pass combining Comb and HW to LLVM lowering (#9105)
This commit introduces a new unified ConvertToLLVM pass that combines both HW and Comb conversion patterns to provide complete lowering from hardware description to LLVM IR. The pass operates on func.func operations and translates Comb and HW operations to LLVM dialect. - Only converts operations inside func.func, leaving HW/SV dialects untouched - Provides complete lowering path for hardware descriptions to LLVM IR - Includes comprehensive test coverage for all Comb operations - Refactors CombToLLVM.cpp to focus on pattern definitions
1 parent 2b863b6 commit f25eebe

File tree

9 files changed

+388
-2
lines changed

9 files changed

+388
-2
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===- ConvertToLLVM.h - ConvertToLLVM pass entry point ---------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This header file defines prototypes that expose the ConvertToLLVM pass
10+
// constructors.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef CIRCT_CONVERSION_CONVERTTOLLVM_H
15+
#define CIRCT_CONVERSION_CONVERTTOLLVM_H
16+
17+
#include "circt/Support/LLVM.h"
18+
#include <memory>
19+
20+
namespace circt {
21+
22+
#define GEN_PASS_DECL_CONVERTTOLLVM
23+
#include "circt/Conversion/Passes.h.inc"
24+
25+
} // namespace circt
26+
27+
#endif // CIRCT_CONVERSION_CONVERTTOLLVM_H

include/circt/Conversion/Passes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "circt/Conversion/CombToSMT.h"
2525
#include "circt/Conversion/CombToSynth.h"
2626
#include "circt/Conversion/ConvertToArcs.h"
27+
#include "circt/Conversion/ConvertToLLVM.h"
2728
#include "circt/Conversion/DCToHW.h"
2829
#include "circt/Conversion/DatapathToComb.h"
2930
#include "circt/Conversion/DatapathToSMT.h"
@@ -56,6 +57,10 @@
5657

5758
namespace circt {
5859

60+
// Generate pass declarations.
61+
#define GEN_PASS_DECL_CONVERTTOLLVM
62+
#include "circt/Conversion/Passes.h.inc"
63+
5964
// Generate the code for registering conversion passes.
6065
#define GEN_PASS_REGISTRATION
6166
#include "circt/Conversion/Passes.h.inc"

include/circt/Conversion/Passes.td

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,23 @@ def ConvertHWToLLVM : Pass<"convert-hw-to-llvm", "mlir::ModuleOp"> {
513513
let dependentDialects = ["mlir::LLVM::LLVMDialect"];
514514
}
515515

516+
//===----------------------------------------------------------------------===//
517+
// ConvertToLLVM
518+
//===----------------------------------------------------------------------===//
519+
520+
def ConvertToLLVM : Pass<"convert-to-llvm", "mlir::ModuleOp"> {
521+
let summary = "Convert Comb and HW to LLVM";
522+
let description = [{
523+
This pass translates Comb and HW operations inside func.func to LLVM IR.
524+
It combines both HW and Comb conversion patterns to provide a complete
525+
lowering from hardware description to LLVM IR.
526+
}];
527+
let dependentDialects = [
528+
"mlir::LLVM::LLVMDialect",
529+
"mlir::arith::ArithDialect"
530+
];
531+
}
532+
516533
//===----------------------------------------------------------------------===//
517534
// HWArithToHW
518535
//===----------------------------------------------------------------------===//

lib/CAPI/Conversion/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_circt_public_c_api_library(CIRCTCAPIConversion
1414
CIRCTCombToLLVM
1515
CIRCTCombToSMT
1616
CIRCTConvertToArcs
17+
CIRCTConvertToLLVM
1718
CIRCTDatapathToComb
1819
CIRCTDatapathToSMT
1920
CIRCTDCToHW

lib/Conversion/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_subdirectory(CombToLLVM)
99
add_subdirectory(CombToSMT)
1010
add_subdirectory(CombToSynth)
1111
add_subdirectory(ConvertToArcs)
12+
add_subdirectory(ConvertToLLVM)
1213
add_subdirectory(DatapathToComb)
1314
add_subdirectory(DatapathToSMT)
1415
add_subdirectory(DCToHW)

lib/Conversion/CombToLLVM/CombToLLVM.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
//===- CombToLLVM.cpp - Comb to LLVM Conversion Pass ----------------------===//
1+
//===- CombToLLVM.cpp - Comb to LLVM Conversion Patterns ------------------===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// This is the main Comb to LLVM Conversion Pass Implementation.
9+
// This file implements Comb to LLVM conversion patterns.
1010
//
1111
//===----------------------------------------------------------------------===//
1212

@@ -23,7 +23,13 @@ using namespace mlir;
2323
using namespace circt;
2424

2525
namespace {
26+
27+
//===----------------------------------------------------------------------===//
28+
// Comb Operation Conversion Patterns
29+
//===----------------------------------------------------------------------===//
30+
2631
/// Convert a comb::ParityOp to the LLVM dialect.
32+
/// This is the only Comb operation that doesn't have a Comb-to-Arith pattern.
2733
struct CombParityOpConversion : public ConvertToLLVMPattern {
2834
explicit CombParityOpConversion(MLIRContext *ctx,
2935
LLVMTypeConverter &typeConverter)
@@ -43,9 +49,17 @@ struct CombParityOpConversion : public ConvertToLLVMPattern {
4349
return success();
4450
}
4551
};
52+
4653
} // namespace
4754

55+
//===----------------------------------------------------------------------===//
56+
// Pattern Population Functions
57+
//===----------------------------------------------------------------------===//
58+
4859
void circt::populateCombToLLVMConversionPatterns(LLVMTypeConverter &converter,
4960
RewritePatternSet &patterns) {
61+
// Only add patterns for operations that don't have Comb-to-Arith patterns
62+
// Most Comb operations are handled by the Comb-to-Arith + Arith-to-LLVM
63+
// pipeline
5064
patterns.add<CombParityOpConversion>(patterns.getContext(), converter);
5165
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
add_circt_conversion_library(CIRCTConvertToLLVM
2+
ConvertToLLVM.cpp
3+
4+
DEPENDS
5+
CIRCTConversionPassIncGen
6+
7+
LINK_COMPONENTS
8+
Core
9+
10+
LINK_LIBS PUBLIC
11+
CIRCTComb
12+
CIRCTCombToArith
13+
CIRCTCombToLLVM
14+
CIRCTHW
15+
CIRCTHWToLLVM
16+
CIRCTSupport
17+
MLIRArithToLLVM
18+
MLIRControlFlowToLLVM
19+
MLIRFuncToLLVM
20+
MLIRIndexToLLVM
21+
MLIRLLVMCommonConversion
22+
MLIRSCFToControlFlow
23+
MLIRTransforms
24+
)
25+
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//===- ConvertToLLVM.cpp - ConvertToLLVM Pass ----------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file implements the ConvertToLLVM pass.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "circt/Conversion/ConvertToLLVM.h"
14+
#include "circt/Conversion/CombToArith.h"
15+
#include "circt/Conversion/CombToLLVM.h"
16+
#include "circt/Conversion/HWToLLVM.h"
17+
#include "circt/Dialect/Comb/CombOps.h"
18+
#include "circt/Dialect/SV/SVOps.h"
19+
#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
20+
#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
21+
#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
22+
#include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h"
23+
#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
24+
#include "mlir/Conversion/LLVMCommon/Pattern.h"
25+
#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
26+
#include "mlir/Dialect/Arith/IR/Arith.h"
27+
#include "mlir/Dialect/Func/IR/FuncOps.h"
28+
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
29+
#include "mlir/Pass/Pass.h"
30+
#include "mlir/Transforms/DialectConversion.h"
31+
32+
using namespace mlir;
33+
using namespace circt;
34+
35+
namespace circt {
36+
#define GEN_PASS_DEF_CONVERTTOLLVM
37+
#include "circt/Conversion/Passes.h.inc"
38+
39+
namespace impl {
40+
41+
//===----------------------------------------------------------------------===//
42+
// Pass Implementation
43+
//===----------------------------------------------------------------------===//
44+
45+
struct ConvertToLLVMPass : public ConvertToLLVMBase<ConvertToLLVMPass> {
46+
void runOnOperation() override;
47+
48+
private:
49+
void convertFuncOp(func::FuncOp funcOp);
50+
};
51+
52+
void ConvertToLLVMPass::runOnOperation() {
53+
// Iterate over all func.func operations in the module and convert them
54+
for (auto funcOp :
55+
llvm::make_early_inc_range(getOperation().getOps<func::FuncOp>())) {
56+
convertFuncOp(funcOp);
57+
}
58+
}
59+
60+
void ConvertToLLVMPass::convertFuncOp(func::FuncOp funcOp) {
61+
MLIRContext *context = &getContext();
62+
RewritePatternSet patterns(context);
63+
auto converter = mlir::LLVMTypeConverter(context);
64+
65+
// Add HW to LLVM type conversions
66+
populateHWToLLVMTypeConversions(converter);
67+
68+
LLVMConversionTarget target(*context);
69+
target.addIllegalDialect<comb::CombDialect>();
70+
target.addIllegalDialect<arith::ArithDialect>();
71+
72+
// Mark HW and SV dialects as legal - we only convert operations inside
73+
// func.func
74+
target.addLegalDialect<hw::HWDialect>();
75+
target.addLegalDialect<sv::SVDialect>();
76+
77+
// Setup the conversion patterns in the correct order:
78+
// 1. SCF to ControlFlow (for structured control flow)
79+
populateSCFToControlFlowConversionPatterns(patterns);
80+
81+
// 2. Func to LLVM (for function operations)
82+
populateFuncToLLVMConversionPatterns(converter, patterns);
83+
84+
// 3. ControlFlow to LLVM (for control flow operations)
85+
cf::populateControlFlowToLLVMConversionPatterns(converter, patterns);
86+
87+
// 4. Comb to Arith (for most combinational operations)
88+
populateCombToArithConversionPatterns(converter, patterns);
89+
90+
// 5. Arith to LLVM (for arithmetic operations)
91+
arith::populateArithToLLVMConversionPatterns(converter, patterns);
92+
93+
// 6. Index to LLVM (for index operations)
94+
index::populateIndexToLLVMConversionPatterns(converter, patterns);
95+
96+
// 7. Any function op interface type conversion
97+
populateAnyFunctionOpInterfaceTypeConversionPattern(patterns, converter);
98+
99+
// 8. Comb to LLVM (for operations without Comb-to-Arith patterns, like
100+
// parity)
101+
populateCombToLLVMConversionPatterns(converter, patterns);
102+
103+
// Apply the partial conversion only to this func.func operation
104+
if (failed(applyPartialConversion(funcOp, target, std::move(patterns))))
105+
signalPassFailure();
106+
}
107+
108+
} // namespace impl
109+
} // namespace circt

0 commit comments

Comments
 (0)