15 #include "mlir/IR/Value.h"
16 #include "llvm/ADT/Any.h"
17 #include "llvm/Support/Debug.h"
19 using namespace circt;
25 static std::vector<mlir::Value>
toVector(mlir::ValueRange range) {
26 return std::vector<mlir::Value>(range.begin(), range.end());
31 ArrayRef<mlir::Value> outs,
32 llvm::DenseMap<mlir::Value, llvm::Any> &valueMap) {
34 if (valueMap.count(in) == 0)
38 if (valueMap.count(out) > 0)
45 static std::vector<llvm::Any>
47 llvm::DenseMap<mlir::Value, llvm::Any> &valueMap) {
48 std::vector<llvm::Any> ins;
49 for (
auto &value : values) {
50 assert(valueMap[value].has_value());
51 ins.push_back(valueMap[value]);
52 valueMap.erase(value);
59 ArrayRef<mlir::Value> outs,
60 llvm::DenseMap<mlir::Value, llvm::Any> &valueMap) {
61 assert(values.size() == outs.size());
62 for (
unsigned long i = 0; i < outs.size(); ++i)
63 valueMap[outs[i]] = values[i];
67 static void updateTime(ArrayRef<mlir::Value> ins, ArrayRef<mlir::Value> outs,
68 llvm::DenseMap<mlir::Value, double> &timeMap,
72 time = std::max(time, timeMap[in]);
74 for (
auto &out : outs)
79 llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
80 llvm::DenseMap<mlir::Value, double> &timeMap,
81 std::vector<mlir::Value> &scheduleList,
83 auto ins =
toVector(op->getOperands());
84 auto outs =
toVector(op->getResults());
88 std::vector<llvm::Any> out(outs.size());
89 auto generalOp = dyn_cast<GeneralOpInterface>(op);
91 op->emitOpError(
"Undefined execution for the current op");
92 generalOp.execute(in, out);
104 bool ForkOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
105 llvm::DenseMap<unsigned, unsigned> & ,
106 llvm::DenseMap<mlir::Value, double> &timeMap,
107 std::vector<std::vector<llvm::Any>> & ,
108 std::vector<mlir::Value> &scheduleList) {
109 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList, 1);
112 bool MergeOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
113 llvm::DenseMap<unsigned, unsigned> & ,
114 llvm::DenseMap<mlir::Value, double> &timeMap,
115 std::vector<std::vector<llvm::Any>> & ,
116 std::vector<mlir::Value> &scheduleList) {
118 for (mlir::Value in : getOperands()) {
119 if (valueMap.count(in) == 1) {
121 emitOpError(
"More than one valid input to Merge!");
122 auto t = valueMap[in];
123 valueMap[getResult()] = t;
124 timeMap[getResult()] = timeMap[in];
131 emitOpError(
"No valid input to Merge!");
132 scheduleList.push_back(getResult());
135 bool MuxOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
136 llvm::DenseMap<unsigned, unsigned> & ,
137 llvm::DenseMap<mlir::Value, double> &timeMap,
138 std::vector<std::vector<llvm::Any>> & ,
139 std::vector<mlir::Value> &scheduleList) {
140 mlir::Value control = getSelectOperand();
141 if (valueMap.count(control) == 0)
143 auto controlValue = valueMap[control];
144 auto controlTime = timeMap[control];
145 auto opIdx = llvm::any_cast<APInt>(controlValue).getZExtValue();
146 assert(opIdx < getDataOperands().size() &&
147 "Trying to select a non-existing mux operand");
149 mlir::Value in = getDataOperands()[opIdx];
150 if (valueMap.count(in) == 0)
152 auto inValue = valueMap[in];
153 auto inTime = timeMap[in];
154 double time = std::max(controlTime, inTime);
155 valueMap[getResult()] = inValue;
156 timeMap[getResult()] = time;
159 valueMap.erase(control);
161 scheduleList.push_back(getResult());
164 bool ControlMergeOp::tryExecute(
165 llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
166 llvm::DenseMap<unsigned, unsigned> & ,
167 llvm::DenseMap<mlir::Value, double> &timeMap,
168 std::vector<std::vector<llvm::Any>> & ,
169 std::vector<mlir::Value> &scheduleList) {
171 for (
auto in : llvm::enumerate(getOperands())) {
172 if (valueMap.count(in.value()) == 1) {
174 emitOpError(
"More than one valid input to CMerge!");
175 valueMap[getResult()] = valueMap[in.value()];
176 timeMap[getResult()] = timeMap[in.value()];
178 valueMap[getIndex()] = APInt(
INDEX_WIDTH, in.index());
179 timeMap[getIndex()] = timeMap[in.value()];
182 valueMap.erase(in.value());
188 emitOpError(
"No valid input to CMerge!");
189 scheduleList =
toVector(getResults());
193 void BranchOp::execute(std::vector<llvm::Any> &ins,
194 std::vector<llvm::Any> &outs) {
198 bool BranchOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
199 llvm::DenseMap<unsigned, unsigned> & ,
200 llvm::DenseMap<mlir::Value, double> &timeMap,
201 std::vector<std::vector<llvm::Any>> & ,
202 std::vector<mlir::Value> &scheduleList) {
203 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList, 0);
206 bool ConditionalBranchOp::tryExecute(
207 llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
208 llvm::DenseMap<unsigned, unsigned> & ,
209 llvm::DenseMap<mlir::Value, double> &timeMap,
210 std::vector<std::vector<llvm::Any>> & ,
211 std::vector<mlir::Value> &scheduleList) {
212 mlir::Value control = getConditionOperand();
213 if (valueMap.count(control) == 0)
215 auto controlValue = valueMap[control];
216 auto controlTime = timeMap[control];
217 mlir::Value in = getDataOperand();
218 if (valueMap.count(in) == 0)
220 auto inValue = valueMap[in];
221 auto inTime = timeMap[in];
222 mlir::Value out = llvm::any_cast<APInt>(controlValue) != 0 ? getTrueResult()
224 double time = std::max(controlTime, inTime);
225 valueMap[out] = inValue;
227 scheduleList.push_back(out);
230 valueMap.erase(control);
235 bool SinkOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
236 llvm::DenseMap<unsigned, unsigned> & ,
237 llvm::DenseMap<mlir::Value, double> & ,
238 std::vector<std::vector<llvm::Any>> & ,
239 std::vector<mlir::Value> & ) {
240 valueMap.erase(getOperand());
244 void BufferOp::execute(std::vector<llvm::Any> &ins,
245 std::vector<llvm::Any> &outs) {
249 bool BufferOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
250 llvm::DenseMap<unsigned, unsigned> & ,
251 llvm::DenseMap<mlir::Value, double> &timeMap,
252 std::vector<std::vector<llvm::Any>> & ,
253 std::vector<mlir::Value> &scheduleList) {
254 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList,
258 void ConstantOp::execute(std::vector<llvm::Any> & ,
259 std::vector<llvm::Any> &outs) {
260 auto attr = (*this)->getAttrOfType<mlir::IntegerAttr>(
"value");
261 outs[0] = attr.getValue();
264 bool ConstantOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
265 llvm::DenseMap<unsigned, unsigned> & ,
266 llvm::DenseMap<mlir::Value, double> &timeMap,
267 std::vector<std::vector<llvm::Any>> & ,
268 std::vector<mlir::Value> &scheduleList) {
269 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList, 0);
272 template <
typename TMemOp>
275 llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
276 llvm::DenseMap<unsigned, unsigned> &memoryMap,
277 llvm::DenseMap<mlir::Value, double> &timeMap,
278 std::vector<std::vector<llvm::Any>> &store,
279 std::vector<mlir::Value> &scheduleList) {
280 bool notReady =
false;
281 for (
unsigned i = 0; i < op.getStCount(); i++) {
282 mlir::Value data = op->getOperand(opIndex++);
283 mlir::Value address = op->getOperand(opIndex++);
284 mlir::Value nonceOut = op->getResult(op.getLdCount() + i);
285 if ((!valueMap.count(data) || !valueMap.count(address))) {
289 auto addressValue = valueMap[address];
290 auto addressTime = timeMap[address];
291 auto dataValue = valueMap[data];
292 auto dataTime = timeMap[data];
294 assert(buffer < store.size());
295 auto &ref = store[buffer];
296 unsigned offset = llvm::any_cast<APInt>(addressValue).getZExtValue();
297 assert(offset < ref.size());
298 ref[offset] = dataValue;
301 APInt apnonearg(1, 0);
302 valueMap[nonceOut] = apnonearg;
303 double time = std::max(addressTime, dataTime);
304 timeMap[nonceOut] = time;
305 scheduleList.push_back(nonceOut);
307 valueMap.erase(data);
308 valueMap.erase(address);
311 for (
unsigned i = 0; i < op.getLdCount(); i++) {
312 mlir::Value address = op->getOperand(opIndex++);
313 mlir::Value dataOut = op->getResult(i);
314 mlir::Value nonceOut = op->getResult(op.getLdCount() + op.getStCount() + i);
315 if (!valueMap.count(address)) {
319 auto addressValue = valueMap[address];
320 auto addressTime = timeMap[address];
321 assert(buffer < store.size());
322 auto &ref = store[buffer];
323 unsigned offset = llvm::any_cast<APInt>(addressValue).getZExtValue();
324 assert(offset < ref.size());
326 valueMap[dataOut] = ref[offset];
327 timeMap[dataOut] = addressTime;
329 APInt apnonearg(1, 0);
330 valueMap[nonceOut] = apnonearg;
331 timeMap[nonceOut] = addressTime;
332 scheduleList.push_back(dataOut);
333 scheduleList.push_back(nonceOut);
335 valueMap.erase(address);
337 return (notReady) ? false :
true;
340 bool MemoryOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
341 llvm::DenseMap<unsigned, unsigned> &memoryMap,
342 llvm::DenseMap<mlir::Value, double> &timeMap,
343 std::vector<std::vector<llvm::Any>> &store,
344 std::vector<mlir::Value> &scheduleList) {
345 unsigned buffer = memoryMap[getId()];
347 store, scheduleList);
350 bool LoadOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
351 llvm::DenseMap<unsigned, unsigned> & ,
352 llvm::DenseMap<mlir::Value, double> &timeMap,
353 std::vector<std::vector<llvm::Any>> & ,
354 std::vector<mlir::Value> &scheduleList) {
355 mlir::Value address = getOperand(0);
356 mlir::Value data = getOperand(1);
357 mlir::Value nonce = getOperand(2);
358 mlir::Value addressOut = getResult(1);
359 mlir::Value dataOut = getResult(0);
360 if ((valueMap.count(address) && !valueMap.count(nonce)) ||
361 (!valueMap.count(address) && valueMap.count(nonce)) ||
362 (!valueMap.count(address) && !valueMap.count(nonce) &&
363 !valueMap.count(data)))
365 if (valueMap.count(address) && valueMap.count(nonce)) {
366 auto addressValue = valueMap[address];
367 auto addressTime = timeMap[address];
368 auto nonceValue = valueMap[nonce];
369 auto nonceTime = timeMap[nonce];
370 valueMap[addressOut] = addressValue;
371 double time = std::max(addressTime, nonceTime);
372 timeMap[addressOut] = time;
373 scheduleList.push_back(addressOut);
375 valueMap.erase(address);
376 valueMap.erase(nonce);
377 }
else if (valueMap.count(data)) {
378 auto dataValue = valueMap[
data];
379 auto dataTime = timeMap[
data];
380 valueMap[dataOut] = dataValue;
381 timeMap[dataOut] = dataTime;
382 scheduleList.push_back(dataOut);
384 valueMap.erase(data);
386 llvm_unreachable(
"why?");
391 bool ExternalMemoryOp::tryExecute(
392 llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
393 llvm::DenseMap<unsigned, unsigned> &memoryMap,
394 llvm::DenseMap<mlir::Value, double> &timeMap,
395 std::vector<std::vector<llvm::Any>> &store,
396 std::vector<mlir::Value> &scheduleList) {
397 unsigned buffer = llvm::any_cast<unsigned>(valueMap[getMemref()]);
399 store, scheduleList);
402 bool StoreOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
403 llvm::DenseMap<unsigned, unsigned> & ,
404 llvm::DenseMap<mlir::Value, double> &timeMap,
405 std::vector<std::vector<llvm::Any>> & ,
406 std::vector<mlir::Value> &scheduleList) {
407 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList, 1);
410 void JoinOp::execute(std::vector<llvm::Any> &ins,
411 std::vector<llvm::Any> &outs) {
415 bool JoinOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
416 llvm::DenseMap<unsigned, unsigned> & ,
417 llvm::DenseMap<mlir::Value, double> &timeMap,
418 std::vector<std::vector<llvm::Any>> & ,
419 std::vector<mlir::Value> &scheduleList) {
420 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList, 1);
423 void SyncOp::execute(std::vector<llvm::Any> &ins,
424 std::vector<llvm::Any> &outs) {
428 bool SyncOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
429 llvm::DenseMap<unsigned, unsigned> & ,
430 llvm::DenseMap<mlir::Value, double> &timeMap,
431 std::vector<std::vector<llvm::Any>> & ,
432 std::vector<mlir::Value> &scheduleList) {
433 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList, 1);
436 void StoreOp::execute(std::vector<llvm::Any> &ins,
437 std::vector<llvm::Any> &outs) {
443 void ForkOp::execute(std::vector<llvm::Any> &ins,
444 std::vector<llvm::Any> &outs) {
445 for (
auto &out : outs)
449 bool UnpackOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
450 llvm::DenseMap<unsigned, unsigned> & ,
451 llvm::DenseMap<mlir::Value, double> &timeMap,
452 std::vector<std::vector<llvm::Any>> & ,
453 std::vector<mlir::Value> &scheduleList) {
454 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList, 1);
457 void UnpackOp::execute(std::vector<llvm::Any> &ins,
458 std::vector<llvm::Any> &outs) {
459 auto ins0Vec = llvm::any_cast<std::vector<llvm::Any>>(ins[0]);
460 assert(ins0Vec.size() == getNumResults() &&
461 "expected that the number of tuple elements matches the number of "
463 for (
auto [in, out] : llvm::zip(ins0Vec, outs))
467 bool PackOp::tryExecute(llvm::DenseMap<mlir::Value, llvm::Any> &valueMap,
468 llvm::DenseMap<unsigned, unsigned> & ,
469 llvm::DenseMap<mlir::Value, double> &timeMap,
470 std::vector<std::vector<llvm::Any>> & ,
471 std::vector<mlir::Value> &scheduleList) {
472 return tryToExecute(getOperation(), valueMap, timeMap, scheduleList, 1);
475 void PackOp::execute(std::vector<llvm::Any> &ins,
476 std::vector<llvm::Any> &outs) {
477 assert(ins.size() == getNumOperands() &&
478 "expected that the number inputs match the number of tuple elements");
assert(baseType &&"element must be base type")
static void storeValues(std::vector< llvm::Any > &values, ArrayRef< mlir::Value > outs, llvm::DenseMap< mlir::Value, llvm::Any > &valueMap)
static void updateTime(ArrayRef< mlir::Value > ins, ArrayRef< mlir::Value > outs, llvm::DenseMap< mlir::Value, double > &timeMap, double latency)
static std::vector< llvm::Any > fetchValues(ArrayRef< mlir::Value > values, llvm::DenseMap< mlir::Value, llvm::Any > &valueMap)
static bool tryToExecute(Operation *op, llvm::DenseMap< mlir::Value, llvm::Any > &valueMap, llvm::DenseMap< mlir::Value, double > &timeMap, std::vector< mlir::Value > &scheduleList, double latency)
static constexpr int INDEX_WIDTH
static std::vector< mlir::Value > toVector(mlir::ValueRange range)
static bool isReadyToExecute(ArrayRef< mlir::Value > ins, ArrayRef< mlir::Value > outs, llvm::DenseMap< mlir::Value, llvm::Any > &valueMap)
static bool executeMemoryOperation(TMemOp op, unsigned buffer, int opIndex, llvm::DenseMap< mlir::Value, llvm::Any > &valueMap, llvm::DenseMap< unsigned, unsigned > &memoryMap, llvm::DenseMap< mlir::Value, double > &timeMap, std::vector< std::vector< llvm::Any >> &store, std::vector< mlir::Value > &scheduleList)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.