23#include "mlir/IR/Builders.h"
24#include "mlir/IR/Threading.h"
25#include "mlir/Support/WalkResult.h"
26#include "llvm/ADT/APInt.h"
27#include "llvm/ADT/SmallVector.h"
28#include "llvm/Support/Debug.h"
32#define GEN_PASS_DEF_TECHMAPPER
33#include "circt/Dialect/Synth/Transforms/SynthPasses.h.inc"
40#define DEBUG_TYPE "synth-tech-mapper"
48 auto inputTypes =
module.getInputTypes();
49 auto outputTypes =
module.getOutputTypes();
51 unsigned numInputs = inputTypes.size();
52 unsigned numOutputs = outputTypes.size();
54 return module->emitError(
55 "Modules with multiple outputs are not supported yet");
58 for (
auto type : inputTypes) {
59 if (!type.isInteger(1))
60 return module->emitError(
"All input ports must be single bit");
62 for (
auto type : outputTypes) {
63 if (!type.isInteger(1))
64 return module->emitError(
"All output ports must be single bit");
68 return module->emitError("Too many inputs for truth table generation");
70 SmallVector<Value> results;
71 results.reserve(numOutputs);
73 auto *bodyBlock =
module.getBodyBlock();
74 assert(bodyBlock &&
"Module must have a body block");
76 for (
auto result : bodyBlock->getTerminator()->getOperands())
77 results.push_back(result);
80 FailureOr<BinaryTruthTable> truthTable =
getTruthTable(results, bodyBlock);
81 if (failed(truthTable))
95 llvm::dbgs() <<
"Created Tech Library Pattern for module: "
96 <<
module.getModuleName() << "\n"
97 << "NPN Class: " << this->npnClass.truthTable.table << "\n"
98 << "Inputs: " << this->npnClass.inputPermutation.size()
100 << "Input Negation: " << this->npnClass.inputNegation << "\n"
101 << "Output Negation: " << this->npnClass.outputNegation
107 auto moduleCp =
module;
108 return moduleCp.getModuleName();
113 const Cut &cut)
const override {
122 SmallVectorImpl<NPNClass> &matchingNPNClasses)
const override {
123 matchingNPNClasses.push_back(
npnClass);
128 llvm::FailureOr<Operation *>
rewrite(mlir::OpBuilder &builder,
130 const Cut &cut)
const override {
132 SmallVector<Value> inputs;
137 hw::InstanceOp::create(builder, cut.
getRoot()->getLoc(), module,
138 "mapped", ArrayRef<Value>(inputs));
139 return instanceOp.getOperation();
151 auto module = this->module;
152 return module.getLoc();
163struct TechMapperPass :
public impl::TechMapperBase<TechMapperPass> {
164 using TechMapperBase<TechMapperPass>::TechMapperBase;
166 void runOnOperation()
override {
167 auto module = getOperation();
169 SmallVector<std::unique_ptr<CutRewritePattern>> libraryPatterns;
171 unsigned maxInputSize = 0;
177 SmallVector<hw::HWModuleOp> nonLibraryModules;
178 for (
auto hwModule :
module.getOps<hw::HWModuleOp>()) {
180 hwModule->getAttrOfType<DictionaryAttr>("hw.techlib.info");
185 nonLibraryModules.push_back(hwModule);
190 auto areaAttr = techInfo.getAs<FloatAttr>(
"area");
191 auto delayAttr = techInfo.getAs<ArrayAttr>(
"delay");
192 if (!areaAttr || !delayAttr) {
193 mlir::emitError(hwModule.getLoc())
194 <<
"Library module " << hwModule.getModuleName()
195 <<
" must have 'area'(float) and 'delay' (2d array to represent "
196 "input-output pair delay) attributes";
201 double area = areaAttr.getValue().convertToDouble();
203 SmallVector<DelayType> delay;
204 for (
auto delayValue : delayAttr) {
205 auto delayArray = cast<ArrayAttr>(delayValue);
206 for (
auto delayElement : delayArray) {
211 cast<mlir::IntegerAttr>(delayElement).getValue().getZExtValue());
216 if (failed(npnClass)) {
222 std::unique_ptr<TechLibraryPattern>
pattern =
223 std::make_unique<TechLibraryPattern>(hwModule, area, std::move(delay),
224 std::move(*npnClass));
227 maxInputSize = std::max(maxInputSize,
pattern->getNumInputs());
230 libraryPatterns.push_back(std::move(
pattern));
233 if (libraryPatterns.empty())
234 return markAllAnalysesPreserved();
242 auto result = mlir::failableParallelForEach(
243 module.getContext(), nonLibraryModules, [&](
hw::HWModuleOp hwModule) {
244 LLVM_DEBUG(llvm::dbgs() <<
"Processing non-library module: "
245 << hwModule.getName() <<
"\n");
246 CutRewriter rewriter(options, patternSet);
247 return rewriter.run(hwModule);
assert(baseType &&"element must be base type")
RewritePatternSet pattern
static llvm::FailureOr< NPNClass > getNPNClassFromModule(hw::HWModuleOp module)
Cut enumeration engine for combinational logic networks.
Manages a collection of rewriting patterns for combinational logic optimization.
Represents a cut in the combinational logic network.
void getPermutatedInputs(const NPNClass &patternNPN, SmallVectorImpl< Value > &permutedInputs) const
Get the permutated inputs for this cut based on the given pattern NPN.
const NPNClass & getNPNClass() const
Get the NPN canonical form for this cut.
mlir::Operation * getRoot() const
Get the root operation of this cut.
FailureOr< BinaryTruthTable > getTruthTable(ValueRange values, Block *block)
static constexpr unsigned maxTruthTableInputs
Maximum number of inputs supported for truth table generation.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Simple technology library encoded as a HWModuleOp.
TechLibraryPattern(hw::HWModuleOp module, double area, SmallVector< DelayType > delay, NPNClass npnClass)
StringRef getPatternName() const override
Get the name of this pattern. Used for debugging.
hw::HWModuleOp NPNClass npnClass
std::optional< MatchResult > match(CutEnumerator &enumerator, const Cut &cut) const override
Match the cut set against this library primitive.
llvm::FailureOr< Operation * > rewrite(mlir::OpBuilder &builder, CutEnumerator &enumerator, const Cut &cut) const override
Rewrite the cut set using this library primitive.
const SmallVector< DelayType > delay
bool useTruthTableMatcher(SmallVectorImpl< NPNClass > &matchingNPNClasses) const override
Enable truth table matching for this pattern.
unsigned getNumOutputs() const override
Get the number of outputs this pattern produces.
unsigned getNumInputs() const
LocationAttr getLoc() const override
Get location for this pattern(optional).
Represents the canonical form of a boolean function under NPN equivalence.
static NPNClass computeNPNCanonicalForm(const BinaryTruthTable &tt)
Compute the canonical NPN form for a given truth table.
bool equivalentOtherThanPermutation(const NPNClass &other) const
Equality comparison for NPN classes.
Base class for cut rewriting patterns used in combinational logic optimization.
mlir::MLIRContext * getContext() const
Configuration options for the cut-based rewriting algorithm.
unsigned maxCutInputSize
Maximum number of inputs allowed for any cut.
unsigned maxCutSizePerRoot
Maximum number of cuts to maintain per logic node.
bool attachDebugTiming
Put arrival times to rewritten operations.
OptimizationStrategy strategy
Optimization strategy (area vs. timing).
Result of matching a cut against a pattern.