29#include "mlir/Analysis/TopologicalSortUtils.h"
30#include "mlir/IR/Builders.h"
31#include "mlir/IR/Operation.h"
32#include "mlir/IR/RegionKindInterface.h"
33#include "mlir/IR/Value.h"
34#include "mlir/IR/ValueRange.h"
35#include "mlir/IR/Visitors.h"
36#include "mlir/Support/LLVM.h"
37#include "llvm/ADT/APInt.h"
38#include "llvm/ADT/Bitset.h"
39#include "llvm/ADT/DenseMap.h"
40#include "llvm/ADT/MapVector.h"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/ScopeExit.h"
43#include "llvm/ADT/SetVector.h"
44#include "llvm/ADT/SmallVector.h"
45#include "llvm/ADT/iterator.h"
46#include "llvm/Support/Debug.h"
47#include "llvm/Support/ErrorHandling.h"
48#include "llvm/Support/LogicalResult.h"
55#define DEBUG_TYPE "synth-cut-rewriter"
63 return isa<aig::AndInverterOp>(op);
68 "Operation must be a supported logic operation for simulation");
72 if (
auto andOp = dyn_cast<aig::AndInverterOp>(op)) {
73 SmallVector<llvm::APInt, 2> inputs;
74 inputs.reserve(andOp.getInputs().size());
75 for (
auto input : andOp.getInputs()) {
76 auto it = eval.find(input);
78 llvm::report_fatal_error(
"Input value not found in evaluation map");
79 inputs.push_back(it->second);
82 eval[andOp.getResult()] = andOp.evaluate(inputs);
86 llvm::report_fatal_error(
87 "Unsupported operation for simulation. isSupportedLogicOp should "
88 "be used to check if the operation can be simulated.");
93 auto *op = value.getDefiningOp();
98 if (op->hasTrait<OpTrait::ConstantLike>()) {
109 ArrayRef<DelayType> newDelay,
double oldArea,
110 ArrayRef<DelayType> oldDelay) {
113 return newArea < oldArea || (newArea == oldArea && newDelay < oldDelay);
117 return newDelay < oldDelay || (newDelay == oldDelay && newArea < oldArea);
119 llvm_unreachable(
"Unknown mapping strategy");
125 auto isOperationReady = [](Value value, Operation *op) ->
bool {
129 isa<comb::ExtractOp, comb::ReplicateOp, comb::ConcatOp>(op));
134 return mlir::emitError(topOp->getLoc(),
135 "failed to sort operations topologically");
140template <
typename OpRange>
142 mlir::ValueRange values,
const OpRange &ops,
143 const llvm::SmallSetVector<mlir::Value, 4> &inputArgs) {
145 int64_t numInputs = inputArgs.size();
146 int64_t numOutputs = values.size();
151 return mlir::emitError(values.front().getLoc(),
152 "Truth table is too large");
153 return mlir::emitError(values.front().getLoc(),
154 "Multiple outputs are not supported yet");
160 uint32_t tableSize = 1 << numInputs;
162 DenseMap<Value, APInt> eval;
163 for (uint32_t i = 0; i < numInputs; ++i) {
166 uint32_t blockSize = 1 << i;
168 uint32_t patternWidth = 2 * blockSize;
169 APInt
pattern(patternWidth, 0);
170 assert(patternWidth <= tableSize &&
"Pattern width exceeds table size");
172 pattern = APInt::getHighBitsSet(patternWidth, blockSize);
176 eval[inputArgs[i]] = APInt::getSplat(tableSize,
pattern);
179 for (
auto *op : ops) {
180 if (op->getNumResults() == 0)
183 return op->emitError(
"Unsupported operation for truth table simulation");
196 llvm::SmallSetVector<Value, 4> inputs;
197 for (
auto arg : block->getArguments())
232 npnClass.emplace(std::move(canonicalForm));
237 SmallVectorImpl<Value> &permutedInputs)
const {
239 SmallVector<unsigned> idx;
240 npnClass.getInputPermutation(patternNPN, idx);
241 permutedInputs.reserve(idx.size());
242 for (
auto inputIndex : idx) {
243 assert(inputIndex <
inputs.size() &&
"Input index out of bounds");
244 permutedInputs.push_back(
inputs[inputIndex]);
249 os <<
"// === Cut Dump ===\n";
253 os <<
"Primary input cut: " << *
inputs.begin() <<
"\n";
258 for (
auto [idx, input] : llvm::enumerate(
inputs)) {
259 os <<
" Input " << idx <<
": " << input <<
"\n";
261 os <<
"\nOperations: \n";
269 os <<
"// === Cut End ===\n";
304 if (
auto *root = cut.
getRoot())
305 return llvm::any_of(op->getOperands(),
306 [&](Value v) { return v.getDefiningOp() == root; });
312 return cut.
inputs.size() == 1 &&
313 llvm::any_of(op->getOperands(),
314 [&](Value v) { return v == *cut.inputs.begin(); });
320 "The operation must be a child of the current root operation");
327 std::function<void(Operation *)> populateOperations = [&](Operation *op) {
333 for (
auto value : op->getOperands()) {
339 bool isInput =
inputs.contains(value);
340 bool isOtherInput = other.
inputs.contains(value);
342 if (isInput && isOtherInput)
345 auto *defOp = value.getDefiningOp();
347 assert(defOp &&
"Value must have a defining operation since block"
348 "arguments are treated as inputs");
357 populateOperations(defOp);
364 populateOperations(root);
368 for (
auto value : operation->getOperands()) {
370 newCut.
inputs.insert(value);
374 auto *defOp = value.getDefiningOp();
375 assert(defOp &&
"Value must have a defining operation");
380 newCut.
inputs.insert(value);
395 "The operation must be a child of the current root operation");
409 assert(
pattern &&
"Pattern must be set to get arrival time");
414 assert(
pattern &&
"Pattern must be set to get arrival time");
429 unsigned outputIndex)
const {
444 cuts.push_back(std::move(cut));
457 std::stable_sort(cuts.begin(), cuts.end(), [](
const Cut &a,
const Cut &b) {
458 return a.getInputSize() < b.getInputSize();
461 llvm::SmallVector<llvm::Bitset<64>, 4> inputBitMasks;
462 DenseMap<Value, unsigned> inputIndices;
463 auto getIndex = [&](Value v) ->
unsigned {
464 auto it = inputIndices.find(v);
465 if (it != inputIndices.end())
467 unsigned index = inputIndices.size();
468 if (LLVM_UNLIKELY(index >= 64))
469 llvm::report_fatal_error(
470 "Too many unique inputs across cuts. Max 64 supported. Consider "
471 "increasing the compile-time constant.");
472 inputIndices[v] = index;
476 for (
unsigned i = 0; i < cuts.size(); ++i) {
479 llvm::Bitset<64> inputsMask;
480 for (
auto input : cut.inputs.getArrayRef())
481 inputsMask.set(getIndex(input));
483 bool isUnique = llvm::all_of(
484 inputBitMasks, [&](
const llvm::Bitset<64> &existingCutInputMask) {
487 return (existingCutInputMask & inputsMask) != existingCutInputMask;
494 size_t uniqueCount = inputBitMasks.size();
495 if (i != uniqueCount)
496 cuts[uniqueCount] = std::move(cut);
497 inputBitMasks.push_back(inputsMask);
500 unsigned uniqueCount = inputBitMasks.size();
502 LLVM_DEBUG(llvm::dbgs() <<
"Original cuts: " << cuts.size()
503 <<
" Unique cuts: " << uniqueCount <<
"\n");
506 cuts.resize(uniqueCount);
511 llvm::function_ref<std::optional<MatchedPattern>(
const Cut &)> matchCut) {
519 for (
auto &cut :
cuts) {
522 "Cut input size exceeds maximum allowed size");
525 auto matched = matchCut(cut);
530 cut.setMatchedPattern(std::move(*matched));
543 auto *trivialCutsEnd =
544 std::stable_partition(
cuts.begin(),
cuts.end(),
545 [](
const Cut &cut) { return cut.isTrivialCut(); });
547 std::stable_sort(trivialCutsEnd,
cuts.end(),
548 [&options](
const Cut &a,
const Cut &b) ->
bool {
549 assert(!a.isTrivialCut() && !b.isTrivialCut() &&
550 "Trivial cuts should have been excluded");
551 const auto &aMatched = a.getMatchedPattern();
552 const auto &bMatched = b.getMatchedPattern();
555 if (aMatched && bMatched)
556 return compareDelayAndArea(
557 options.strategy, aMatched->getArea(),
558 aMatched->getArrivalTimes(), bMatched->getArea(),
559 bMatched->getArrivalTimes());
562 if (aMatched && !bMatched)
564 if (!aMatched && bMatched)
568 return a.getInputSize() < b.getInputSize();
577 for (
auto &cut :
cuts) {
588 llvm::dbgs() <<
"Finalized cut set with " <<
cuts.size() <<
" cuts and "
593 :
"no matched pattern")
605 SmallVectorImpl<NPNClass> &matchingNPNClasses)
const {
614 llvm::SmallVector<std::unique_ptr<CutRewritePattern>, 4>
patterns)
618 SmallVector<NPNClass, 2> npnClasses;
619 auto result =
pattern->useTruthTableMatcher(npnClasses);
621 for (
auto npnClass : npnClasses) {
624 npnClass.truthTable.numInputs}]
625 .push_back(std::make_pair(std::move(npnClass),
pattern.get()));
640 : options(options) {}
643 auto [cutSetPtr, inserted] =
644 cutSets.try_emplace(value, std::make_unique<CutSet>());
645 assert(inserted &&
"Cut set already exists for this value");
646 return cutSetPtr->second.get();
665 assert(logicOp->getNumResults() == 1 &&
666 "Logic operation must have a single result");
668 Value result = logicOp->getResult(0);
669 unsigned numOperands = logicOp->getNumOperands();
674 return logicOp->emitError(
"Cut enumeration supports at most 2 operands, "
677 if (!logicOp->getOpResult(0).getType().isInteger(1))
678 return logicOp->emitError()
679 <<
"Supported logic operations must have a single bit "
680 "result type but found: "
681 << logicOp->getResult(0).getType();
683 SmallVector<const CutSet *, 2> operandCutSets;
684 operandCutSets.reserve(numOperands);
686 for (
unsigned i = 0; i < numOperands; ++i) {
687 auto *operandCutSet =
getCutSet(logicOp->getOperand(i));
689 return logicOp->emitError(
"Failed to get cut set for operand ")
690 << i <<
": " << logicOp->getOperand(i);
691 operandCutSets.push_back(operandCutSet);
700 resultCutSet->addCut(primaryInputCut);
703 auto prune = llvm::make_scope_exit([&]() {
709 if (numOperands == 1) {
710 const auto &inputCutSet = operandCutSets[0];
713 for (
const Cut &inputCut : inputCutSet->getCuts()) {
714 Cut extendedCut = inputCut.
reRoot(logicOp);
719 resultCutSet->addCut(std::move(extendedCut));
725 assert(numOperands == 2 &&
"Expected binary operation");
727 const auto *lhsCutSet = operandCutSets[0];
728 const auto *rhsCutSet = operandCutSets[1];
731 for (
const Cut &lhsCut : lhsCutSet->getCuts()) {
732 for (
const Cut &rhsCut : rhsCutSet->getCuts()) {
738 resultCutSet->addCut(std::move(mergedCut));
747 llvm::function_ref<std::optional<MatchedPattern>(
const Cut &)> matchCut) {
748 LLVM_DEBUG(llvm::dbgs() <<
"Enumerating cuts for module: " << topOp->getName()
758 auto result = topOp->walk([&](Operation *op) {
759 if (failed(
visit(op)))
760 return mlir::WalkResult::interrupt();
761 return mlir::WalkResult::advance();
764 if (result.wasInterrupted())
767 LLVM_DEBUG(llvm::dbgs() <<
"Cut enumeration completed successfully\n");
773 auto *it =
cutSets.find(value);
776 auto cutSet = std::make_unique<CutSet>();
778 auto [newIt, inserted] =
cutSets.insert({value, std::move(cutSet)});
779 assert(inserted &&
"Cut set already exists for this value");
784 return it->second.get();
792 if (
auto *op = value.getDefiningOp()) {
795 if (
auto name = op->getAttrOfType<StringAttr>(
"sv.namehint"))
796 return name.getValue();
800 if (op->getNumResults() == 1) {
801 auto opName = op->getName();
802 auto count = opCounter[opName]++;
805 SmallString<16> nameStr;
806 nameStr += opName.getStringRef();
808 nameStr += std::to_string(count);
811 auto nameAttr = StringAttr::get(op->getContext(), nameStr);
812 op->setAttr(
"sv.namehint", nameAttr);
821 auto blockArg = cast<BlockArgument>(value);
823 dyn_cast<circt::hw::HWModuleOp>(blockArg.getOwner()->getParentOp());
828 return hwOp.getInputName(blockArg.getArgNumber());
832 DenseMap<OperationName, unsigned> opCounter;
833 for (
auto &[value, cutSetPtr] :
cutSets) {
834 auto &cutSet = *cutSetPtr;
836 << cutSet.getCuts().size() <<
" cuts:";
837 for (
const Cut &cut : cutSet.getCuts()) {
838 llvm::outs() <<
" {";
839 llvm::interleaveComma(cut.inputs, llvm::outs(), [&](Value input) {
840 llvm::outs() << getTestVariableName(input, opCounter);
842 auto &
pattern = cut.getMatchedPattern();
844 <<
"@t" << cut.getTruthTable().table.getZExtValue() <<
"d";
846 llvm::outs() << *std::max_element(
pattern->getArrivalTimes().begin(),
847 pattern->getArrivalTimes().end());
852 llvm::outs() <<
"\n";
854 llvm::outs() <<
"Cut enumeration completed successfully\n";
863 llvm::dbgs() <<
"Starting Cut Rewriter\n";
864 llvm::dbgs() <<
"Mode: "
877 if (
pattern->getNumOutputs() > 1) {
878 return mlir::emitError(
pattern->getLoc(),
879 "Cut rewriter does not support patterns with "
880 "multiple outputs yet");
907 LLVM_DEBUG(llvm::dbgs() <<
"Enumerating cuts...\n");
910 topOp, [&](
const Cut &cut) -> std::optional<MatchedPattern> {
916ArrayRef<std::pair<NPNClass, const CutRewritePattern *>>
918 if (
patterns.npnToPatternMap.empty())
922 auto it =
patterns.npnToPatternMap.find(
923 {npnClass.truthTable.table, npnClass.truthTable.numInputs});
924 if (it ==
patterns.npnToPatternMap.end())
926 return it->getSecond();
934 SmallVector<DelayType, 4> inputArrivalTimes;
935 SmallVector<DelayType, 1> bestArrivalTimes;
940 for (
auto input : cut.
inputs) {
941 assert(input.getType().isInteger(1));
946 inputArrivalTimes.push_back(0);
950 assert(cutSet &&
"Input must have a valid cut set");
954 auto *bestCut = cutSet->getBestMatchedCut();
958 const auto &matchedPattern = *bestCut->getMatchedPattern();
962 inputArrivalTimes.push_back(matchedPattern.getArrivalTime(
963 cast<mlir::OpResult>(input).getResultNumber()));
966 auto computeArrivalTimeAndPickBest =
968 llvm::function_ref<unsigned(
unsigned)> mapIndex) {
969 SmallVector<DelayType, 1> outputArrivalTimes;
971 for (
unsigned outputIndex = 0, outputSize = cut.
getOutputSize();
972 outputIndex < outputSize; ++outputIndex) {
975 for (
unsigned inputIndex = 0, inputSize = cut.
getInputSize();
976 inputIndex < inputSize; ++inputIndex) {
978 unsigned cutOriginalInput = mapIndex(inputIndex);
980 std::max(outputArrivalTime,
981 pattern->getDelay(cutOriginalInput, outputIndex) +
982 inputArrivalTimes[cutOriginalInput]);
985 outputArrivalTimes.push_back(outputArrivalTime);
991 outputArrivalTimes, bestPattern->
getArea(),
994 llvm::dbgs() <<
"== Matched Pattern ==============\n";
995 llvm::dbgs() <<
"Matching cut: \n";
996 cut.
dump(llvm::dbgs());
997 llvm::dbgs() <<
"Found better pattern: "
999 llvm::dbgs() <<
" with area: " <<
pattern->getArea();
1000 llvm::dbgs() <<
" and input arrival times: ";
1001 for (
unsigned i = 0; i < inputArrivalTimes.size(); ++i) {
1002 llvm::dbgs() <<
" " << inputArrivalTimes[i];
1004 llvm::dbgs() <<
" and arrival times: ";
1006 for (
auto arrivalTime : outputArrivalTimes) {
1007 llvm::dbgs() <<
" " << arrivalTime;
1009 llvm::dbgs() <<
"\n";
1010 llvm::dbgs() <<
"== Matched Pattern End ==============\n";
1013 bestArrivalTimes = std::move(outputArrivalTimes);
1020 "Pattern input size must match cut input size");
1026 SmallVector<unsigned> inputMapping;
1028 computeArrivalTimeAndPickBest(
pattern,
1029 [&](
unsigned i) {
return inputMapping[i]; });
1034 computeArrivalTimeAndPickBest(
pattern, [&](
unsigned i) {
return i; });
1043 LLVM_DEBUG(llvm::dbgs() <<
"Performing cut-based rewriting...\n");
1047 PatternRewriter rewriter(top->getContext());
1048 for (
auto &[value, cutSet] : llvm::reverse(cutVector)) {
1049 if (value.use_empty()) {
1050 if (
auto *op = value.getDefiningOp())
1057 LLVM_DEBUG(llvm::dbgs() <<
"Skipping inputs: " << value <<
"\n");
1061 LLVM_DEBUG(llvm::dbgs() <<
"Cut set for value: " << value <<
"\n");
1062 auto *bestCut = cutSet->getBestMatchedCut();
1066 return emitError(value.getLoc(),
"No matching cut found for value: ")
1070 rewriter.setInsertionPoint(bestCut->getRoot());
1071 const auto &matchedPattern = bestCut->getMatchedPattern();
1072 auto result = matchedPattern->getPattern()->rewrite(rewriter, *bestCut);
1076 rewriter.replaceOp(bestCut->getRoot(), *result);
1079 auto array = rewriter.getI64ArrayAttr(matchedPattern->getArrivalTimes());
1080 (*result)->setAttr(
"test.arrival_times", array);
assert(baseType &&"element must be base type")
static bool isAlwaysCutInput(Value value)
static bool isSupportedLogicOp(mlir::Operation *op)
static Cut getAsTrivialCut(mlir::Value value)
static FailureOr< BinaryTruthTable > computeTruthTable(mlir::ValueRange values, const OpRange &ops, const llvm::SmallSetVector< mlir::Value, 4 > &inputArgs)
Get the truth table for an op.
static StringRef getTestVariableName(Value value, DenseMap< OperationName, unsigned > &opCounter)
Generate a human-readable name for a value used in test output.
static bool compareDelayAndArea(OptimizationStrategy strategy, double newArea, ArrayRef< DelayType > newDelay, double oldArea, ArrayRef< DelayType > oldDelay)
static void removeDuplicateAndNonMinimalCuts(SmallVectorImpl< Cut > &cuts)
static bool isCutDerivedFromOperand(const Cut &cut, Operation *op)
static void simulateLogicOp(Operation *op, DenseMap< Value, llvm::APInt > &eval)
RewritePatternSet pattern
LogicalResult visit(Operation *op)
Visit a single operation and generate cuts for it.
const CutRewriterOptions & options
Configuration options for cut enumeration.
llvm::MapVector< Value, std::unique_ptr< CutSet > > cutSets
Maps values to their associated cut sets.
LogicalResult enumerateCuts(Operation *topOp, llvm::function_ref< std::optional< MatchedPattern >(const Cut &)> matchCut=[](const Cut &) { return std::nullopt;})
Enumerate cuts for all nodes in the given module.
CutEnumerator(const CutRewriterOptions &options)
Constructor for cut enumerator.
void clear()
Clear all cut sets and reset the enumerator.
llvm::function_ref< std::optional< MatchedPattern >(const Cut &)> matchCut
Function to match cuts against available patterns.
LogicalResult visitLogicOp(Operation *logicOp)
Visit a combinational logic operation and generate cuts.
llvm::MapVector< Value, std::unique_ptr< CutSet > > takeVector()
Move ownership of all cut sets to caller.
CutSet * createNewCutSet(Value value)
Create a new cut set for a value.
const CutSet * getCutSet(Value value)
Get the cut set for a specific value.
llvm::SmallVector< std::unique_ptr< CutRewritePattern >, 4 > patterns
Owned collection of all rewriting patterns.
DenseMap< std::pair< APInt, unsigned >, SmallVector< std::pair< NPNClass, const CutRewritePattern * > > > npnToPatternMap
Fast lookup table mapping NPN canonical forms to matching patterns.
SmallVector< const CutRewritePattern *, 4 > nonTruthTablePatterns
Patterns that use custom matching logic instead of truth tables.
CutRewritePatternSet(llvm::SmallVector< std::unique_ptr< CutRewritePattern >, 4 > patterns)
Constructor that takes ownership of the provided patterns.
const CutRewriterOptions & options
Configuration options.
ArrayRef< std::pair< NPNClass, const CutRewritePattern * > > getMatchingPatternsFromTruthTable(const Cut &cut) const
Find patterns that match a cut's truth table.
std::optional< MatchedPattern > patternMatchCut(const Cut &cut)
Match a cut against available patterns and compute arrival time.
LogicalResult enumerateCuts(Operation *topOp)
Enumerate cuts for all nodes in the given module.
LogicalResult run(Operation *topOp)
Execute the complete cut-based rewriting algorithm.
CutEnumerator cutEnumerator
LogicalResult runBottomUpRewrite(Operation *topOp)
Perform the actual circuit rewriting using selected patterns.
Manages a collection of cuts for a single logic node using priority cuts algorithm.
Cut * getBestMatchedCut() const
Get the cut associated with the best matched pattern.
llvm::SmallVector< Cut, 4 > cuts
Collection of cuts for this node.
void addCut(Cut cut)
Add a new cut to this set.
unsigned size() const
Get the number of cuts in this set.
void finalize(const CutRewriterOptions &options, llvm::function_ref< std::optional< MatchedPattern >(const Cut &)> matchCut)
Finalize the cut set by removing duplicates and selecting the best pattern.
bool isFrozen
Whether cut set is finalized.
ArrayRef< Cut > getCuts() const
Get read-only access to all cuts in this set.
Represents a cut in the combinational logic network.
std::optional< NPNClass > npnClass
Cached NPN canonical form for this cut.
const std::optional< MatchedPattern > & getMatchedPattern() const
Get the matched pattern for this cut.
llvm::SmallSetVector< mlir::Operation *, 4 > operations
Operations contained within this cut.
unsigned getOutputSize() const
Get the number of outputs from root operation.
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.
llvm::SmallSetVector< mlir::Value, 4 > inputs
External inputs to this cut (cut boundary).
void dump(llvm::raw_ostream &os) const
const BinaryTruthTable & getTruthTable() const
Get the truth table for this cut.
std::optional< BinaryTruthTable > truthTable
Cached truth table for this cut.
Cut mergeWith(const Cut &other, Operation *root) const
Merge this cut with another cut to form a new cut.
unsigned getInputSize() const
Get the number of inputs to this cut.
bool isTrivialCut() const
Check if this cut represents a trivial cut.
Cut reRoot(Operation *root) const
Represents a cut that has been successfully matched to a rewriting pattern.
DelayType getArrivalTime(unsigned outputIndex) const
Get the arrival time of signals through this pattern.
DelayType getDelay(unsigned inputIndex, unsigned outputIndex) const
Get the delay between specific input and output pins.
ArrayRef< DelayType > getArrivalTimes() const
const CutRewritePattern * pattern
The matched library pattern.
double getArea() const
Get the area cost of using this pattern.
const CutRewritePattern * getPattern() const
Get the library pattern that was matched.
SmallVector< DelayType, 1 > arrivalTimes
Arrival times of outputs from this pattern.
OptimizationStrategy
Optimization strategy.
@ OptimizationStrategyArea
Optimize for minimal area.
@ OptimizationStrategyTiming
Optimize for minimal critical path delay.
FailureOr< BinaryTruthTable > getTruthTable(ValueRange values, Block *block)
LogicalResult topologicallySortGraphRegionBlocks(mlir::Operation *op, llvm::function_ref< bool(mlir::Value, mlir::Operation *)> isOperandReady)
This function performs a topological sort on the operations within each block of graph regions in the...
static constexpr unsigned maxTruthTableInputs
Maximum number of inputs supported for truth table generation.
LogicalResult topologicallySortLogicNetwork(mlir::Operation *op)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Represents a boolean function as a truth table.
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.
void getInputPermutation(const NPNClass &targetNPN, llvm::SmallVectorImpl< unsigned > &permutation) const
Get input permutation from this NPN class to another equivalent NPN class.
Utility that tracks operations that have potentially become unused and allows them to be cleaned up a...
void eraseNow(Operation *op)
Erase an operation immediately, and remove it from the set of ops to be removed later.
Base class for cut rewriting patterns used in combinational logic optimization.
virtual DelayType getDelay(unsigned inputIndex, unsigned outputIndex) const =0
Get the delay between specific input and output.
virtual bool useTruthTableMatcher(SmallVectorImpl< NPNClass > &matchingNPNClasses) const
Specify truth tables that this pattern can match.
virtual double getArea() const =0
Get the area cost of this pattern.
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 allowNoMatch
Fail if there is a root operation that has no matching pattern.
bool attachDebugTiming
Put arrival times to rewritten operations.
OptimizationStrategy strategy
Optimization strategy (area vs. timing).
bool testPriorityCuts
Run priority cuts enumeration and dump the cut sets.