CIRCT 23.0.0git
Loading...
Searching...
No Matches
SynthOps.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 defines the operations of the Synth dialect.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef CIRCT_DIALECT_SYNTH_SYNTHOPS_H
14#define CIRCT_DIALECT_SYNTH_SYNTHOPS_H
15
18#include "circt/Support/LLVM.h"
19#include "mlir/IR/Attributes.h"
20#include "mlir/IR/Builders.h"
21#include "mlir/IR/BuiltinOps.h"
22#include "mlir/IR/BuiltinTypes.h"
23#include "mlir/IR/Dialect.h"
24#include "mlir/IR/Operation.h"
25#include "mlir/Interfaces/InferTypeOpInterface.h"
26#include "mlir/Interfaces/SideEffectInterfaces.h"
27#include "mlir/Rewrite/PatternApplicator.h"
28
29#define GET_OP_CLASSES
30#include "circt/Dialect/Synth/Synth.h.inc"
31
32#include "llvm/ADT/PriorityQueue.h"
33
34namespace circt {
35namespace synth {
37 mlir::RewritePatternSet &patterns);
39 mlir::RewritePatternSet &patterns);
40bool isLogicNetworkOp(mlir::Operation *op);
41
42/// This function performs a topological sort on the operations within each
43/// block of graph regions in the given operation. It uses MLIR's topological
44/// sort utility as a wrapper, ensuring that operations are ordered such that
45/// all operands are defined before their uses. The `isOperandReady` callback
46/// allows customization of when an operand is considered ready for sorting.
48 mlir::Operation *op,
49 llvm::function_ref<bool(mlir::Value, mlir::Operation *)> isOperandReady);
50
51//===----------------------------------------------------------------------===//
52// Delay-Aware Tree Building Utilities
53//===----------------------------------------------------------------------===//
54
55/// Helper class for delay-aware tree building.
56/// Stores a value along with its arrival time and inversion flag.
58 /// The value and an optional inversion flag packed together.
59 /// The inversion flag is used for AndInverterOp lowering.
60 llvm::PointerIntPair<mlir::Value, 1, bool> value;
61
62 /// The arrival time (delay) of this value in the circuit.
63 int64_t arrivalTime;
64
65 /// Value numbering for deterministic ordering when arrival times are equal.
66 /// This ensures consistent results across runs when multiple values have
67 /// the same delay.
68 size_t valueNumbering = 0;
69
70public:
71 ValueWithArrivalTime(mlir::Value value, int64_t arrivalTime, bool invert,
72 size_t valueNumbering = 0)
75
76 mlir::Value getValue() const { return value.getPointer(); }
77 bool isInverted() const { return value.getInt(); }
78 int64_t getArrivalTime() const { return arrivalTime; }
79
81 value.setInt(!value.getInt());
82 return *this;
83 }
84
85 /// Comparison operator for priority queue. Values with earlier arrival times
86 /// have higher priority. When arrival times are equal, use value numbering
87 /// for determinism.
88 bool operator>(const ValueWithArrivalTime &other) const {
89 return std::tie(arrivalTime, valueNumbering) >
90 std::tie(other.arrivalTime, other.valueNumbering);
91 }
92};
93
94/// Build a balanced binary tree using a priority queue to greedily pair
95/// elements with earliest arrival times. This minimizes the critical path
96/// delay.
97///
98/// Template parameters:
99/// T - The element type (must have operator> defined)
100///
101/// The algorithm uses a min-heap to repeatedly combine the two elements with
102/// the earliest arrival times, which is optimal for minimizing maximum delay.
103template <typename T>
104T buildBalancedTreeWithArrivalTimes(llvm::ArrayRef<T> elements,
105 llvm::function_ref<T(T, T)> combine) {
106 assert(!elements.empty() && "Cannot build tree from empty elements");
107
108 if (elements.size() == 1)
109 return elements[0];
110 if (elements.size() == 2)
111 return combine(elements[0], elements[1]);
112
113 // Min-heap priority queue ordered by operator>
114 llvm::PriorityQueue<T, std::vector<T>, std::greater<T>> pq(elements.begin(),
115 elements.end());
116
117 // Greedily pair the two earliest-arriving elements
118 while (pq.size() > 1) {
119 T e1 = pq.top();
120 pq.pop();
121 T e2 = pq.top();
122 pq.pop();
123
124 // Combine the two elements
125 T combined = combine(e1, e2);
126 pq.push(combined);
127 }
128
129 return pq.top();
130}
131
132/// Evaluate the Boolean function `x ^ (z | (x & y))`.
133template <typename T>
134T evaluateDotLogic(const T &x, const T &y, const T &z) {
135 return x ^ (z | (x & y));
136}
137
138template <typename T>
139T evaluateMajorityLogic(const T &a, const T &b, const T &c) {
140 return (a & b) | (a & c) | (b & c);
141}
142
143inline llvm::APInt invertBooleanLogic(llvm::APInt value) {
144 value.flipAllBits();
145 return value;
146}
147
148inline llvm::KnownBits invertBooleanLogic(llvm::KnownBits value) {
149 std::swap(value.Zero, value.One);
150 return value;
151}
152
153template <typename T>
154T evaluateOneHotLogic(const T &a, const T &b, const T &c) {
155 auto allSet = a & b & c;
156 return (a ^ b ^ c) & invertBooleanLogic(allSet);
157}
158
159template <typename T>
160T evaluateMuxLogic(const T &a, const T &b, const T &c) {
161 return (a & b) | (invertBooleanLogic(a) & c);
162}
163
164} // namespace synth
165} // namespace circt
166
167#endif // CIRCT_DIALECT_SYNTH_SYNTHOPS_H
assert(baseType &&"element must be base type")
Helper class for delay-aware tree building.
Definition SynthOps.h:57
ValueWithArrivalTime(mlir::Value value, int64_t arrivalTime, bool invert, size_t valueNumbering=0)
Definition SynthOps.h:71
mlir::Value getValue() const
Definition SynthOps.h:76
ValueWithArrivalTime & flipInversion()
Definition SynthOps.h:80
size_t valueNumbering
Value numbering for deterministic ordering when arrival times are equal.
Definition SynthOps.h:68
int64_t arrivalTime
The arrival time (delay) of this value in the circuit.
Definition SynthOps.h:63
llvm::PointerIntPair< mlir::Value, 1, bool > value
The value and an optional inversion flag packed together.
Definition SynthOps.h:60
bool operator>(const ValueWithArrivalTime &other) const
Comparison operator for priority queue.
Definition SynthOps.h:88
llvm::APInt invertBooleanLogic(llvm::APInt value)
Definition SynthOps.h:143
void populateVariadicXorInverterLoweringPatterns(mlir::RewritePatternSet &patterns)
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...
Definition SynthOps.cpp:662
T buildBalancedTreeWithArrivalTimes(llvm::ArrayRef< T > elements, llvm::function_ref< T(T, T)> combine)
Build a balanced binary tree using a priority queue to greedily pair elements with earliest arrival t...
Definition SynthOps.h:104
T evaluateDotLogic(const T &x, const T &y, const T &z)
Evaluate the Boolean function x ^ (z | (x & y)).
Definition SynthOps.h:134
T evaluateMajorityLogic(const T &a, const T &b, const T &c)
Definition SynthOps.h:139
T evaluateMuxLogic(const T &a, const T &b, const T &c)
Definition SynthOps.h:160
bool isLogicNetworkOp(mlir::Operation *op)
T evaluateOneHotLogic(const T &a, const T &b, const T &c)
Definition SynthOps.h:154
void populateVariadicAndInverterLoweringPatterns(mlir::RewritePatternSet &patterns)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition synth.py:1