12 #include <llvm/ADT/SmallPtrSet.h>
18 circt::firrtl::FModuleOp
24 throw std::logic_error(node->
DebugString() +
" has more than 1 output");
30 auto body = module.getBodyBlock();
32 ::llvm::SmallVector<mlir::Value> inBundles;
35 for (
size_t i = 0; i < node->
ninputs(); i++)
41 inBundles.push_back(bundle);
47 auto outData =
GetSubfield(body, outBundle,
"data");
49 if (rvsdg::is<llvm::IntegerAddOperation>(node))
51 auto input0 =
GetSubfield(body, inBundles[0],
"data");
52 auto input1 =
GetSubfield(body, inBundles[1],
"data");
53 auto op =
AddAddOp(body, input0, input1);
58 else if (rvsdg::is<llvm::IntegerSubOperation>(node))
60 auto input0 =
GetSubfield(body, inBundles[0],
"data");
61 auto input1 =
GetSubfield(body, inBundles[1],
"data");
62 auto op =
AddSubOp(body, input0, input1);
67 else if (rvsdg::is<llvm::IntegerAndOperation>(node))
69 auto input0 =
GetSubfield(body, inBundles[0],
"data");
70 auto input1 =
GetSubfield(body, inBundles[1],
"data");
71 auto op =
AddAndOp(body, input0, input1);
75 else if (rvsdg::is<llvm::IntegerXorOperation>(node))
77 auto input0 =
GetSubfield(body, inBundles[0],
"data");
78 auto input1 =
GetSubfield(body, inBundles[1],
"data");
79 auto op =
AddXorOp(body, input0, input1);
83 else if (rvsdg::is<llvm::IntegerOrOperation>(node))
85 auto input0 =
GetSubfield(body, inBundles[0],
"data");
86 auto input1 =
GetSubfield(body, inBundles[1],
"data");
87 auto op =
AddOrOp(body, input0, input1);
93 auto input0 =
GetSubfield(body, inBundles[0],
"data");
94 auto input1 =
GetSubfield(body, inBundles[1],
"data");
95 auto op =
AddMulOp(body, input0, input1);
100 else if (rvsdg::is<llvm::IntegerSDivOperation>(node))
102 auto input0 =
GetSubfield(body, inBundles[0],
"data");
103 auto input1 =
GetSubfield(body, inBundles[1],
"data");
106 auto divOp =
AddDivOp(body, sIntOp0, sIntOp1);
111 else if (rvsdg::is<llvm::IntegerLShrOperation>(node))
113 auto input0 =
GetSubfield(body, inBundles[0],
"data");
114 auto input1 =
GetSubfield(body, inBundles[1],
"data");
115 auto op =
AddDShrOp(body, input0, input1);
119 else if (rvsdg::is<llvm::IntegerAShrOperation>(node))
121 auto input0 =
GetSubfield(body, inBundles[0],
"data");
122 auto input1 =
GetSubfield(body, inBundles[1],
"data");
124 auto shrOp =
AddDShrOp(body, sIntOp0, input1);
127 Connect(body, outData, uIntOp);
129 else if (rvsdg::is<llvm::IntegerShlOperation>(node))
131 auto input0 =
GetSubfield(body, inBundles[0],
"data");
132 auto input1 =
GetSubfield(body, inBundles[1],
"data");
133 auto bitsOp =
AddBitsOp(body, input1, 7, 0);
134 auto op =
AddDShlOp(body, input0, bitsOp);
136 auto slice =
AddBitsOp(body, op, outSize - 1, 0);
140 else if (rvsdg::is<llvm::IntegerSRemOperation>(node))
142 auto input0 =
GetSubfield(body, inBundles[0],
"data");
143 auto input1 =
GetSubfield(body, inBundles[1],
"data");
146 auto remOp =
AddRemOp(body, sIntOp0, sIntOp1);
148 Connect(body, outData, uIntOp);
150 else if (rvsdg::is<llvm::IntegerEqOperation>(node))
152 auto input0 =
GetSubfield(body, inBundles[0],
"data");
153 auto input1 =
GetSubfield(body, inBundles[1],
"data");
154 auto op =
AddEqOp(body, input0, input1);
158 else if (rvsdg::is<llvm::IntegerNeOperation>(node))
160 auto input0 =
GetSubfield(body, inBundles[0],
"data");
161 auto input1 =
GetSubfield(body, inBundles[1],
"data");
162 auto op =
AddNeqOp(body, input0, input1);
166 else if (rvsdg::is<llvm::IntegerSgtOperation>(node))
168 auto input0 =
GetSubfield(body, inBundles[0],
"data");
169 auto input1 =
GetSubfield(body, inBundles[1],
"data");
172 auto op =
AddGtOp(body, sIntOp0, sIntOp1);
176 else if (rvsdg::is<llvm::IntegerUltOperation>(node))
178 auto input0 =
GetSubfield(body, inBundles[0],
"data");
179 auto input1 =
GetSubfield(body, inBundles[1],
"data");
180 auto op =
AddLtOp(body, input0, input1);
184 else if (rvsdg::is<llvm::IntegerUleOperation>(node))
186 auto input0 =
GetSubfield(body, inBundles[0],
"data");
187 auto input1 =
GetSubfield(body, inBundles[1],
"data");
188 auto op =
AddLeqOp(body, input0, input1);
192 else if (rvsdg::is<llvm::IntegerUgtOperation>(node))
194 auto input0 =
GetSubfield(body, inBundles[0],
"data");
195 auto input1 =
GetSubfield(body, inBundles[1],
"data");
196 auto op =
AddGtOp(body, input0, input1);
200 else if (rvsdg::is<llvm::IntegerSgeOperation>(node))
202 auto input0 =
GetSubfield(body, inBundles[0],
"data");
203 auto input1 =
GetSubfield(body, inBundles[1],
"data");
206 auto op =
AddGeqOp(body, sIntOp0, sIntOp1);
210 else if (rvsdg::is<llvm::IntegerUgeOperation>(node))
212 auto input0 =
GetSubfield(body, inBundles[0],
"data");
213 auto input1 =
GetSubfield(body, inBundles[1],
"data");
214 auto op =
AddGeqOp(body, input0, input1);
218 else if (rvsdg::is<llvm::IntegerSleOperation>(node))
220 auto input0 =
GetSubfield(body, inBundles[0],
"data");
221 auto input1 =
GetSubfield(body, inBundles[1],
"data");
224 auto op =
AddLeqOp(body, sIntOp0, sIntOp1);
228 else if (rvsdg::is<llvm::IntegerSltOperation>(node))
230 auto input0 =
GetSubfield(body, inBundles[0],
"data");
231 auto input1 =
GetSubfield(body, inBundles[1],
"data");
234 auto op =
AddLtOp(body, sInt0, sInt1);
239 auto input0 =
GetSubfield(body, inBundles[0],
"data");
240 Connect(body, outData, input0);
242 else if (rvsdg::is<const llvm::TruncOperation>(node->
GetOperation()))
244 auto inData =
GetSubfield(body, inBundles[0],
"data");
250 auto inData =
GetSubfield(body, inBundles[0],
"data");
251 Connect(body, outData, inData);
255 auto inData =
GetSubfield(body, inBundles[0],
"data");
256 Connect(body, outData, inData);
260 auto input0 =
GetSubfield(body, inBundles[0],
"data");
262 auto padOp =
AddPadOp(body, sintOp, op->ndstbits());
264 Connect(body, outData, uintOp);
268 auto & value = op->Representation();
269 auto size = value.nbits();
271 auto constant =
GetConstant(body, size, value.to_uint());
272 Connect(body, outData, constant);
277 auto value = op->value().alternative();
278 auto size = ceil(log2(op->value().nalternatives()));
280 Connect(body, outData, constant);
284 auto input0 =
GetSubfield(body, inBundles[0],
"data");
285 Connect(body, outData, input0);
289 auto input0 =
GetSubfield(body, inBundles[0],
"data");
290 Connect(body, outData, input0);
294 auto inData =
GetSubfield(body, inBundles[0],
"data");
295 auto outData =
GetSubfield(body, outBundle,
"data");
300 if (inSize == outSize)
302 Connect(body, outData, inData);
311 auto size = op->nbits();
312 mlir::Value result =
GetConstant(body, size, op->default_alternative());
313 for (
auto it = op->begin(); it != op->end(); it++)
317 result =
AddMuxOp(body, comparison, value, result);
319 if ((
unsigned long)outSize != size)
321 result =
AddBitsOp(body, result, outSize - 1, 0);
323 Connect(body, outData, result);
329 auto input0 =
GetSubfield(body, inBundles[0],
"data");
330 mlir::Value result =
AddCvtOp(body, input0);
334 for (
size_t i = 1; i < node->
ninputs(); i++)
336 int bits =
JlmSize(pointeeType);
340 pointeeType =
nullptr;
342 else if (
auto arrayType =
dynamic_cast<const llvm::ArrayType *
>(pointeeType))
344 pointeeType = &arrayType->element_type();
346 else if (
auto vectorType =
dynamic_cast<const llvm::VectorType *
>(pointeeType))
348 pointeeType = vectorType->
Type().get();
352 throw std::logic_error(pointeeType->
debug_string() +
" pointer not implemented!");
355 auto input =
GetSubfield(body, inBundles[i],
"data");
357 int bytes = bits / 8;
359 auto cvtOp =
AddCvtOp(body, constantOp);
360 auto offset =
AddMulOp(body, asSInt, cvtOp);
361 result =
AddAddOp(body, result, offset);
369 auto input0 =
GetSubfield(body, inBundles[0],
"data");
370 auto input1 =
GetSubfield(body, inBundles[1],
"data");
372 auto vec =
Builder_->create<circt::firrtl::WireOp>(
374 circt::firrtl::FVectorType::get(
GetFirrtlType(vt->Type().get()), vt->size()),
376 auto elementBits =
JlmSize(vt->Type().get());
377 body->push_back(vec);
378 for (
size_t i = 0; i < vt->size(); ++i)
380 auto subindexOp =
Builder_->create<circt::firrtl::SubindexOp>(
384 body->push_back(subindexOp);
388 AddBitsOp(body, input0, elementBits * (i + 1) - 1, elementBits * i));
390 auto subaccessOp =
Builder_->create<circt::firrtl::SubaccessOp>(
394 body->push_back(subaccessOp);
395 Connect(body, outData, subaccessOp);
404 auto select =
GetSubfield(body, inBundles[0],
"data");
406 for (
size_t i = 1; i < node->
ninputs(); i++)
408 auto data =
GetSubfield(body, inBundles[i],
"data");
410 auto eqOp =
AddEqOp(body, select, constant);
411 auto whenOp =
AddWhenOp(body, eqOp,
false);
412 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
413 Connect(thenBody, outData, data);
418 throw std::logic_error(
"Simple node " + node->
DebugString() +
" not implemented!");
423 mlir::Value prevAnd = oneBitValue;
424 for (
size_t i = 0; i < node->
ninputs(); i++)
426 auto bundle = inBundles[i];
430 auto outValid =
GetSubfield(body, outBundle,
"valid");
431 Connect(body, outValid, prevAnd);
434 auto outReady =
GetSubfield(body, outBundle,
"ready");
435 auto andReady =
AddAndOp(body, outReady, prevAnd);
437 for (
size_t i = 0; i < node->
ninputs(); i++)
439 auto bundle = inBundles[i];
441 Connect(body, ready, andReady);
447 circt::firrtl::FModuleOp
452 auto body = module.getBodyBlock();
456 auto constant =
Builder_->create<circt::firrtl::ConstantOp>(
459 ::llvm::APInt(1, 1));
460 body->push_back(constant);
467 Connect(body, ready, constant);
472 circt::firrtl::FModuleOp
477 auto body = module.getBodyBlock();
483 auto predReady =
GetSubfield(body, predBundle,
"ready");
484 auto predValid =
GetSubfield(body, predBundle,
"valid");
485 auto predData =
GetSubfield(body, predBundle,
"data");
488 auto inReady =
GetSubfield(body, inBundle,
"ready");
489 auto inValid =
GetSubfield(body, inBundle,
"valid");
494 auto outReady =
GetSubfield(body, outBundle,
"ready");
495 auto outValid =
GetSubfield(body, outBundle,
"valid");
496 auto outData =
GetSubfield(body, outBundle,
"data");
498 auto dataReg =
Builder_->create<circt::firrtl::RegOp>(
502 Builder_->getStringAttr(
"data_reg"));
503 body->push_back(dataReg);
514 Connect(body, outData, dataReg.getResult());
516 auto dataPassThroughBody =
517 AddWhenOp(body, dataPassThrough,
false).getThenBodyBuilder().getBlock();
518 Connect(dataPassThroughBody, outData, inData);
520 auto inFire =
AddAndOp(body, inReady, inValid);
521 auto inFireBody =
AddWhenOp(body, inFire,
false).getThenBodyBuilder().getBlock();
522 Connect(inFireBody, dataReg.getResult(), inData);
527 circt::firrtl::FModuleOp
534 auto body = module.getBodyBlock();
538 auto inReady =
GetSubfield(body, inBundle,
"ready");
539 auto inValid =
GetSubfield(body, inBundle,
"valid");
550 Connect(body, inReady, oneBitValue);
551 for (
size_t i = 0; i < node->
noutputs(); ++i)
557 Connect(body, portValid, inValid);
558 Connect(body, portData, inData);
565 ::llvm::SmallVector<circt::firrtl::RegResetOp> firedRegs;
566 ::llvm::SmallVector<circt::firrtl::AndPrimOp> whenConditions;
569 mlir::Value allFired = inValid;
570 for (
size_t i = 0; i < node->
noutputs(); ++i)
572 std::string validName(
"out");
573 validName.append(std::to_string(i));
574 validName.append(
"_fired_reg");
575 auto firedReg =
Builder_->create<circt::firrtl::RegResetOp>(
581 Builder_->getStringAttr(validName));
582 body->push_back(firedReg);
583 firedRegs.push_back(firedReg);
591 auto notFiredReg =
AddNotOp(body, firedReg.getResult());
592 auto andOp =
AddAndOp(body, inValid, notFiredReg.getResult());
593 Connect(body, portValid, andOp);
594 Connect(body, portData, inData);
596 auto orOp =
AddOrOp(body, portReady, firedReg.getResult());
597 allFired =
AddAndOp(body, allFired, orOp);
600 whenConditions.push_back(
AddAndOp(body, portReady, portValid));
602 allFired =
AddNodeOp(body, allFired,
"all_fired").getResult();
603 Connect(body, inReady, allFired);
606 auto condition =
AddNotOp(body, allFired);
607 auto whenOp =
AddWhenOp(body, condition,
true);
610 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
612 for (
size_t i = 0; i < node->
noutputs(); i++)
614 auto nestedWhen =
AddWhenOp(thenBody, whenConditions[i],
false);
615 auto nestedBody = nestedWhen.getThenBodyBuilder().getBlock();
616 Connect(nestedBody, firedRegs[i].getResult(), oneBitValue);
619 auto elseBody = whenOp.getElseBodyBuilder().getBlock();
620 for (
size_t i = 0; i < node->
noutputs(); i++)
622 Connect(elseBody, firedRegs[i].getResult(), zeroBitValue);
629 circt::firrtl::FModuleOp
634 auto body = module.getBodyBlock();
641 ::llvm::SmallVector<circt::firrtl::RegResetOp> firedRegs;
642 ::llvm::SmallVector<circt::firrtl::AndPrimOp> whenConditions;
645 mlir::Value allInsValid = oneBitValue;
646 for (
size_t i = 0; i < node->
ninputs(); ++i)
650 auto inValid =
GetSubfield(body, inBundle,
"valid");
652 allInsValid =
AddAndOp(body, allInsValid, inValid);
654 allInsValid =
AddNodeOp(body, allInsValid,
"all_ins_valid").getResult();
655 mlir::Value allFired = oneBitValue;
656 for (
size_t i = 0; i < node->
noutputs(); ++i)
658 std::string validName(
"out");
659 validName.append(std::to_string(i));
660 validName.append(
"_fired_reg");
661 auto firedReg =
Builder_->create<circt::firrtl::RegResetOp>(
667 Builder_->getStringAttr(validName));
668 body->push_back(firedReg);
669 firedRegs.push_back(firedReg);
679 auto notFiredReg =
AddNotOp(body, firedReg.getResult());
680 auto andOp =
AddAndOp(body, allInsValid, notFiredReg);
681 Connect(body, outValid, andOp);
682 Connect(body, outData, inData);
684 auto orOp =
AddOrOp(body,
AddAndOp(body, outValid, outReady), firedReg.getResult());
685 allFired =
AddAndOp(body, allFired, orOp);
688 whenConditions.push_back(
AddAndOp(body, outReady, outValid));
690 allFired =
AddNodeOp(body, allFired,
"all_fired").getResult();
691 for (
size_t i = 0; i < node->
ninputs(); ++i)
695 Connect(body, inReady, allFired);
699 auto condition =
AddNotOp(body, allFired);
700 auto whenOp =
AddWhenOp(body, condition,
true);
703 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
705 for (
size_t i = 0; i < node->
noutputs(); i++)
707 auto nestedWhen =
AddWhenOp(thenBody, whenConditions[i],
false);
708 auto nestedBody = nestedWhen.getThenBodyBuilder().getBlock();
709 Connect(nestedBody, firedRegs[i].getResult(), oneBitValue);
712 auto elseBody = whenOp.getElseBodyBuilder().getBlock();
713 for (
size_t i = 0; i < node->
noutputs(); i++)
715 Connect(elseBody, firedRegs[i].getResult(), zeroBitValue);
721 circt::firrtl::FModuleOp
726 auto body = module.getBodyBlock();
731 for (
size_t i = 0; i < node->
noutputs(); ++i)
734 auto outValid =
GetSubfield(body, outBundle,
"valid");
735 auto outData =
GetSubfield(body, outBundle,
"data");
736 Connect(body, outValid, zeroBitValue);
739 for (
size_t j = 0; j < node->
ninputs(); ++j)
741 mlir::BlockArgument memRes =
GetInPort(module, j);
742 auto memResValid =
GetSubfield(body, memRes,
"valid");
743 auto memResReady =
GetSubfield(body, memRes,
"ready");
744 auto memResBundle =
GetSubfield(body, memRes,
"data");
745 auto memResId =
GetSubfield(body, memResBundle,
"id");
746 auto memResData =
GetSubfield(body, memResBundle,
"data");
748 memResData->getResult(0).getType().cast<circt::firrtl::IntType>().getWidth().value();
750 auto elseBody = body;
751 for (
size_t i = 0; i < node->
noutputs(); ++i)
755 auto outValid =
GetSubfield(elseBody, outBundle,
"valid");
756 auto outReady =
GetSubfield(elseBody, outBundle,
"ready");
757 auto outData =
GetSubfield(elseBody, outBundle,
"data");
760 auto whenOp =
AddWhenOp(elseBody, condition,
true);
761 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
762 Connect(thenBody, outValid, oneBitValue);
763 Connect(thenBody, memResReady, outReady);
768 if (nbits == portWidth)
770 Connect(thenBody, outData, memResData);
777 elseBody = whenOp.getElseBodyBuilder().getBlock();
781 Connect(elseBody, memResReady, oneBitValue);
784 for (
size_t i = 0; i < j; ++i)
786 mlir::BlockArgument memRes2 =
GetInPort(module, i);
787 auto memResValid2 =
GetSubfield(body, memRes2,
"valid");
788 auto memResBundle2 =
GetSubfield(body, memRes2,
"data");
789 auto memResId2 =
GetSubfield(body, memResBundle2,
"id");
790 auto id_assert =
Builder_->create<circt::firrtl::AssertOp>(
797 AddAndOp(body, memResValid, memResValid2),
798 AddEqOp(body, memResId, memResId2))),
800 "overlapping reponse id",
802 "response_id_assert_" + std::to_string(j) +
"_" + std::to_string(i));
803 body->push_back(id_assert);
810 circt::firrtl::FModuleOp
815 auto body = module.getBodyBlock();
819 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadAddrReadys;
820 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadAddrValids;
821 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadAddrDatas;
822 ::llvm::SmallVector<mlir::Value> loadIds;
824 auto storeTypes = op->GetStoreTypes();
825 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeAddrReadys;
826 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeAddrValids;
827 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeAddrDatas;
828 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeDataReadys;
829 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeDataValids;
830 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeDataDatas;
831 ::llvm::SmallVector<mlir::Value> storeIds;
835 for (
size_t i = 0; i < op->get_nloads(); ++i)
838 loadAddrReadys.push_back(
GetSubfield(body, bundle,
"ready"));
839 loadAddrValids.push_back(
GetSubfield(body, bundle,
"valid"));
840 loadAddrDatas.push_back(
GetSubfield(body, bundle,
"data"));
844 for (
size_t i = op->get_nloads(); i < node->
ninputs(); ++i)
848 storeAddrReadys.push_back(
GetSubfield(body, addrBundle,
"ready"));
849 storeAddrValids.push_back(
GetSubfield(body, addrBundle,
"valid"));
850 storeAddrDatas.push_back(
GetSubfield(body, addrBundle,
"data"));
853 storeDataReadys.push_back(
GetSubfield(body, dataBundle,
"ready"));
854 storeDataValids.push_back(
GetSubfield(body, dataBundle,
"valid"));
855 storeDataDatas.push_back(
GetSubfield(body, dataBundle,
"data"));
862 ::llvm::SmallVector<mlir::Value> loadGranted(loadTypes->size(), zeroBitValue);
863 ::llvm::SmallVector<mlir::Value> storeGranted(storeTypes->size(), zeroBitValue);
864 for (
size_t j = 0; j < node->
noutputs(); ++j)
866 auto reqType = util::assertedCast<const BundleType>(node->
output(j)->
Type().get());
867 auto hasWrite = reqType->elements_.size() == 5;
868 mlir::BlockArgument memReq =
GetOutPort(module, j);
869 mlir::Value memReqData;
870 mlir::Value memReqWrite;
871 auto memReqReady =
GetSubfield(body, memReq,
"ready");
872 auto memReqValid =
GetSubfield(body, memReq,
"valid");
873 auto memReqBundle =
GetSubfield(body, memReq,
"data");
874 auto memReqAddr =
GetSubfield(body, memReqBundle,
"addr");
875 auto memReqSize =
GetSubfield(body, memReqBundle,
"size");
876 auto memReqId =
GetSubfield(body, memReqBundle,
"id");
879 memReqData =
GetSubfield(body, memReqBundle,
"data");
880 memReqWrite =
GetSubfield(body, memReqBundle,
"write");
883 Connect(body, memReqValid, zeroBitValue);
885 mlir::Value previousGranted = zeroBitValue;
886 for (
size_t i = 0; i < loadTypes->size(); ++i)
890 Connect(body, loadAddrReadys[i], zeroBitValue);
892 auto canGrant =
AddNotOp(body,
AddOrOp(body, previousGranted, loadGranted[i]));
893 auto grant =
AddAndOp(body, canGrant, loadAddrValids[i]);
894 auto whenOp =
AddWhenOp(body, grant,
false);
895 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
896 Connect(thenBody, loadAddrReadys[i], memReqReady);
897 Connect(thenBody, memReqValid, loadAddrValids[i]);
898 Connect(thenBody, memReqAddr, loadAddrDatas[i]);
899 Connect(thenBody, memReqId, loadIds[i]);
901 auto loadType = loadTypes->at(i).get();
902 int bitWidth =
JlmSize(loadType);
903 int log2Bytes = log2(bitWidth / 8);
907 Connect(thenBody, memReqWrite, zeroBitValue);
910 previousGranted =
AddOrOp(body, previousGranted, grant);
911 loadGranted[i] =
AddOrOp(body, loadGranted[i], grant);
914 for (
size_t i = 0; hasWrite && i < storeTypes->size(); ++i)
918 Connect(body, storeAddrReadys[i], zeroBitValue);
919 Connect(body, storeDataReadys[i], zeroBitValue);
921 auto notOp =
AddNotOp(body,
AddOrOp(body, previousGranted, storeGranted[i]));
922 auto grant =
AddAndOp(body, notOp, storeAddrValids[i]);
923 grant =
AddAndOp(body, grant, storeDataValids[i]);
924 auto whenOp =
AddWhenOp(body, grant,
false);
925 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
926 Connect(thenBody, storeAddrReadys[i], memReqReady);
927 Connect(thenBody, storeDataReadys[i], memReqReady);
928 Connect(thenBody, memReqValid, storeAddrValids[i]);
929 Connect(thenBody, memReqAddr, storeAddrDatas[i]);
930 Connect(thenBody, memReqData, storeDataDatas[i]);
934 Connect(thenBody, memReqId, storeIds[i]);
936 auto storeType = storeTypes->at(i).get();
937 int bitWidth =
JlmSize(storeType);
938 int log2Bytes = log2(bitWidth / 8);
940 Connect(thenBody, memReqWrite, oneBitValue);
942 previousGranted =
AddOrOp(body, previousGranted, grant);
943 storeGranted[i] =
AddOrOp(body, storeGranted[i], grant);
950 circt::firrtl::FModuleOp
953 JLM_ASSERT(rvsdg::is<LoadOperation>(node) || rvsdg::is<LocalLoadOperation>(node));
957 auto body = module.getBodyBlock();
960 auto inBundleAddr =
GetInPort(module, 0);
961 auto inReadyAddr =
GetSubfield(body, inBundleAddr,
"ready");
962 auto inValidAddr =
GetSubfield(body, inBundleAddr,
"valid");
963 auto inDataAddr =
GetSubfield(body, inBundleAddr,
"data");
965 ::llvm::SmallVector<circt::firrtl::SubfieldOp> inReadyStates;
966 ::llvm::SmallVector<circt::firrtl::SubfieldOp> inValidStates;
967 ::llvm::SmallVector<circt::firrtl::SubfieldOp> inDataStates;
968 for (
size_t i = 1; i < node->
ninputs() - 1; ++i)
971 inReadyStates.push_back(
GetSubfield(body, bundle,
"ready"));
972 inValidStates.push_back(
GetSubfield(body, bundle,
"valid"));
973 inDataStates.push_back(
GetSubfield(body, bundle,
"data"));
977 auto inReadyMemData =
GetSubfield(body, inBundleMemData,
"ready");
978 auto inValidMemData =
GetSubfield(body, inBundleMemData,
"valid");
979 auto inDataMemData =
GetSubfield(body, inBundleMemData,
"data");
983 auto outReadyData =
GetSubfield(body, outBundleData,
"ready");
984 auto outValidData =
GetSubfield(body, outBundleData,
"valid");
985 auto outDataData =
GetSubfield(body, outBundleData,
"data");
987 ::llvm::SmallVector<circt::firrtl::SubfieldOp> outReadyStates;
988 ::llvm::SmallVector<circt::firrtl::SubfieldOp> outValidStates;
989 ::llvm::SmallVector<circt::firrtl::SubfieldOp> outDataStates;
990 for (
size_t i = 1; i < node->
noutputs() - 1; ++i)
993 outReadyStates.push_back(
GetSubfield(body, bundle,
"ready"));
994 outValidStates.push_back(
GetSubfield(body, bundle,
"valid"));
995 outDataStates.push_back(
GetSubfield(body, bundle,
"data"));
999 auto outReadyMemAddr =
GetSubfield(body, outBundleMemAddr,
"ready");
1000 auto outValidMemAddr =
GetSubfield(body, outBundleMemAddr,
"valid");
1001 auto outDataMemAddr =
GetSubfield(body, outBundleMemAddr,
"data");
1009 ::llvm::SmallVector<circt::firrtl::RegResetOp> oValidRegs;
1010 ::llvm::SmallVector<circt::firrtl::RegResetOp> oDataRegs;
1011 for (
size_t i = 0; i < node->
noutputs() - 1; i++)
1013 std::string validName(
"o");
1014 validName.append(std::to_string(i));
1015 validName.append(
"_valid_reg");
1016 auto validReg =
Builder_->create<circt::firrtl::RegResetOp>(
1022 Builder_->getStringAttr(validName));
1023 body->push_back(validReg);
1024 oValidRegs.push_back(validReg);
1027 std::string dataName(
"o");
1028 dataName.append(std::to_string(i));
1029 dataName.append(
"_data_reg");
1030 auto dataReg =
Builder_->create<circt::firrtl::RegResetOp>(
1036 Builder_->getStringAttr(dataName));
1037 body->push_back(dataReg);
1038 oDataRegs.push_back(dataReg);
1040 auto sentReg =
Builder_->create<circt::firrtl::RegResetOp>(
1046 Builder_->getStringAttr(
"sent_reg"));
1047 body->push_back(sentReg);
1051 mlir::Value canRequest =
AddNotOp(body, sentReg.getResult());
1052 canRequest =
AddAndOp(body, canRequest, inValidAddr);
1053 for (
auto vld : inValidStates)
1055 canRequest =
AddAndOp(body, canRequest, vld);
1059 canRequest =
AddAndOp(body, canRequest,
AddNotOp(body, oValidRegs[0].getResult()));
1060 for (
size_t i = 1; i < oValidRegs.size(); i++)
1064 canRequest =
AddAndOp(body, canRequest,
AddNotOp(body, oValidRegs[i].getResult()));
1068 Connect(body, outValidMemAddr, canRequest);
1069 Connect(body, outDataMemAddr, inDataAddr);
1071 Connect(body, outValidData, oValidRegs[0].getResult());
1072 Connect(body, outDataData, oDataRegs[0].getResult());
1074 for (
size_t i = 1; i < node->
noutputs() - 1; ++i)
1076 Connect(body, outValidStates[i - 1], oValidRegs[i].getResult());
1077 Connect(body, outDataStates[i - 1], oDataRegs[i].getResult());
1078 auto andOp2 =
AddAndOp(body, outReadyStates[i - 1], outValidStates[i - 1]);
1081 AddWhenOp(body, andOp2,
false).getThenBodyBuilder().getBlock(),
1082 oValidRegs[i].getResult(),
1087 auto whenResFireOp =
AddWhenOp(body,
AddAndOp(body, sentReg.getResult(), inValidMemData),
false);
1088 auto whenResFireBody = whenResFireOp.getThenBodyBuilder().getBlock();
1089 Connect(whenResFireBody, sentReg.getResult(), zeroBitValue);
1090 Connect(whenResFireBody, oDataRegs[0].getResult(), inDataMemData);
1091 Connect(whenResFireBody, oValidRegs[0].getResult(), oneBitValue);
1092 Connect(whenResFireBody, outDataData, inDataMemData);
1093 Connect(whenResFireBody, outValidData, oneBitValue);
1096 auto whenReqFireOp =
AddWhenOp(body, outReadyMemAddr,
false);
1097 auto whenReqFireBody = whenReqFireOp.getThenBodyBuilder().getBlock();
1098 Connect(whenReqFireBody, sentReg.getResult(), oneBitValue);
1099 for (
size_t i = 1; i < node->
noutputs() - 1; ++i)
1101 Connect(whenReqFireBody, oValidRegs[i].getResult(), oneBitValue);
1102 Connect(whenReqFireBody, oDataRegs[i].getResult(), inDataStates[i - 1]);
1106 Connect(body, inReadyAddr, outReadyMemAddr);
1107 for (
size_t i = 1; i < node->
ninputs() - 1; ++i)
1109 Connect(body, inReadyStates[i - 1], outReadyMemAddr);
1111 Connect(body, inReadyMemData, sentReg.getResult());
1113 auto andOp =
AddAndOp(body, outReadyData, outValidData);
1116 AddWhenOp(body, andOp,
false).getThenBodyBuilder().getBlock(),
1117 oValidRegs[0].getResult(),
1123 circt::firrtl::FModuleOp
1126 JLM_ASSERT(rvsdg::is<DecoupledLoadOperation>(node));
1130 auto body = module.getBodyBlock();
1133 auto inBundleAddr =
GetInPort(module, 0);
1134 auto inReadyAddr =
GetSubfield(body, inBundleAddr,
"ready");
1135 auto inValidAddr =
GetSubfield(body, inBundleAddr,
"valid");
1136 auto inDataAddr =
GetSubfield(body, inBundleAddr,
"data");
1139 auto inReadyMemData =
GetSubfield(body, inBundleMemData,
"ready");
1140 auto inValidMemData =
GetSubfield(body, inBundleMemData,
"valid");
1141 auto inDataMemData =
GetSubfield(body, inBundleMemData,
"data");
1145 auto outReadyData =
GetSubfield(body, outBundleData,
"ready");
1146 auto outValidData =
GetSubfield(body, outBundleData,
"valid");
1147 auto outDataData =
GetSubfield(body, outBundleData,
"data");
1150 auto outReadyMemAddr =
GetSubfield(body, outBundleMemAddr,
"ready");
1151 auto outValidMemAddr =
GetSubfield(body, outBundleMemAddr,
"valid");
1152 auto outDataMemAddr =
GetSubfield(body, outBundleMemAddr,
"data");
1155 Connect(body, outValidMemAddr, inValidAddr);
1156 Connect(body, outDataMemAddr, inDataAddr);
1159 Connect(body, inReadyAddr, outReadyMemAddr);
1160 Connect(body, inReadyMemData, outReadyData);
1162 Connect(body, outValidData, inValidMemData);
1163 Connect(body, outDataData, inDataMemData);
1164 AddAndOp(body, outReadyData, outValidData);
1169 circt::firrtl::FModuleOp
1172 auto lmem_op = util::assertedCast<const LocalMemoryOperation>(&node->
GetOperation());
1173 auto res_node = rvsdg::TryGetOwnerNode<rvsdg::Node>(*node->
output(0)->
Users().
begin());
1174 JLM_ASSERT(rvsdg::is<LocalMemoryResponseOperation>(res_node));
1175 auto req_node = rvsdg::TryGetOwnerNode<rvsdg::Node>(*node->
output(1)->
Users().
begin());
1176 JLM_ASSERT(rvsdg::is<LocalMemoryRequestOperation>(req_node));
1180 ::llvm::SmallVector<circt::firrtl::PortInfo> ports;
1186 for (
size_t i = 1; i < req_node->ninputs(); ++i)
1188 std::string name(
"i");
1189 name.append(std::to_string(i - 1));
1192 circt::firrtl::Direction::In,
1196 for (
size_t i = 0; i < res_node->noutputs(); ++i)
1198 std::string name(
"o");
1199 name.append(std::to_string(i));
1202 circt::firrtl::Direction::Out,
1209 mlir::StringAttr name =
Builder_->getStringAttr(nodeName);
1211 auto module =
Builder_->create<circt::firrtl::FModuleOp>(
1214 circt::firrtl::ConventionAttr::get(
1216 circt::firrtl::Convention::Internal),
1219 auto body = module.getBodyBlock();
1221 size_t loads = rvsdg::TryGetOwnerNode<rvsdg::Node>(*node->
output(0)->
Users().
begin())->noutputs();
1224 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadAddrReadys;
1225 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadAddrValids;
1226 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadAddrDatas;
1228 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeAddrReadys;
1229 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeAddrValids;
1230 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeAddrDatas;
1231 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeDataReadys;
1232 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeDataValids;
1233 ::llvm::SmallVector<circt::firrtl::SubfieldOp> storeDataDatas;
1236 for (
size_t i = 1; i < req_node->ninputs(); ++i)
1243 loadAddrReadys.push_back(
GetSubfield(body, bundle,
"ready"));
1244 loadAddrValids.push_back(
GetSubfield(body, bundle,
"valid"));
1245 loadAddrDatas.push_back(
GetSubfield(body, bundle,
"data"));
1250 auto addrBundle =
GetInPort(module, i - 1);
1251 storeAddrReadys.push_back(
GetSubfield(body, addrBundle,
"ready"));
1252 storeAddrValids.push_back(
GetSubfield(body, addrBundle,
"valid"));
1253 storeAddrDatas.push_back(
GetSubfield(body, addrBundle,
"data"));
1255 auto dataBundle =
GetInPort(module, i - 1);
1256 storeDataReadys.push_back(
GetSubfield(body, dataBundle,
"ready"));
1257 storeDataValids.push_back(
GetSubfield(body, dataBundle,
"valid"));
1258 storeDataDatas.push_back(
GetSubfield(body, dataBundle,
"data"));
1262 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadDataReadys;
1263 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadDataValids;
1264 ::llvm::SmallVector<circt::firrtl::SubfieldOp> loadDataDatas;
1265 for (
size_t i = 0; i < res_node->noutputs(); ++i)
1268 loadDataReadys.push_back(
GetSubfield(body, bundle,
"ready"));
1269 loadDataValids.push_back(
GetSubfield(body, bundle,
"valid"));
1270 loadDataDatas.push_back(
GetSubfield(body, bundle,
"data"));
1279 auto arraytype = std::dynamic_pointer_cast<const llvm::ArrayType>(lmem_op->result(0));
1280 size_t depth = arraytype->nelements();
1282 ::llvm::SmallVector<mlir::Type> memTypes;
1283 ::llvm::SmallVector<mlir::Attribute> memNames;
1284 memTypes.push_back(circt::firrtl::MemOp::getTypeForPort(
1287 circt::firrtl::MemOp::PortKind::ReadWrite));
1288 memNames.push_back(
Builder_->getStringAttr(
"rw0"));
1293 auto memory =
Builder_->create<circt::firrtl::MemOp>(
1299 circt::firrtl::RUWAttr::New,
1302 body->push_back(memory);
1303 auto rw0 = memory.getPortNamed(
"rw0");
1314 int addrwidth = ceil(log2(depth));
1318 for (
size_t i = 0; i < storeDataReadys.size(); ++i)
1320 Connect(body, storeDataReadys[i], zeroBitValue);
1321 Connect(body, storeAddrReadys[i], zeroBitValue);
1323 ::llvm::SmallVector<circt::firrtl::RegResetOp> loadValidRegs;
1324 for (
size_t i = 0; i < loadAddrReadys.size(); ++i)
1326 auto validReg =
Builder_->create<circt::firrtl::RegResetOp>(
1332 Builder_->getStringAttr(
"load_valid_" + std::to_string(i)));
1333 body->push_back(validReg);
1334 loadValidRegs.push_back(validReg);
1335 Connect(body, validReg.getResult(), zeroBitValue);
1336 Connect(body, loadDataValids[i], validReg.getResult());
1337 Connect(body, loadDataDatas[i], rw0_rdata);
1338 Connect(body, loadAddrReadys[i], zeroBitValue);
1341 mlir::Block * elsewhen = body;
1342 for (
size_t i = 0; i < storeDataReadys.size(); ++i)
1344 auto whenReqFireOp =
1345 AddWhenOp(elsewhen,
AddAndOp(elsewhen, storeAddrValids[i], storeDataValids[i]),
true);
1346 auto whenReqFireBody = whenReqFireOp.getThenBodyBuilder().getBlock();
1347 Connect(whenReqFireBody, storeDataReadys[i], oneBitValue);
1348 Connect(whenReqFireBody, storeAddrReadys[i], oneBitValue);
1349 Connect(whenReqFireBody, rw0_wmode, oneBitValue);
1350 Connect(whenReqFireBody, rw0_wdata, storeDataDatas[i]);
1354 AddBitsOp(whenReqFireBody, storeAddrDatas[i], addrwidth - 1, 0));
1355 elsewhen = whenReqFireOp.getElseBodyBuilder().getBlock();
1357 for (
size_t i = 0; i < loadAddrReadys.size(); ++i)
1359 auto whenReqFireOp =
AddWhenOp(elsewhen, loadAddrValids[i],
true);
1360 auto whenReqFireBody = whenReqFireOp.getThenBodyBuilder().getBlock();
1361 Connect(whenReqFireBody, loadAddrReadys[i], oneBitValue);
1362 Connect(whenReqFireBody, rw0_wmode, zeroBitValue);
1366 AddBitsOp(whenReqFireBody, loadAddrDatas[i], addrwidth - 1, 0));
1367 Connect(whenReqFireBody, loadValidRegs[i].getResult(), oneBitValue);
1368 elsewhen = whenReqFireOp.getElseBodyBuilder().getBlock();
1370 Connect(elsewhen, rw0_wmode, zeroBitValue);
1376 circt::firrtl::FModuleOp
1379 JLM_ASSERT(rvsdg::is<StoreOperation>(node) || rvsdg::is<LocalStoreOperation>(node));
1383 auto body = module.getBodyBlock();
1386 auto inBundleAddr =
GetInPort(module, 0);
1387 auto inReadyAddr =
GetSubfield(body, inBundleAddr,
"ready");
1388 auto inValidAddr =
GetSubfield(body, inBundleAddr,
"valid");
1389 auto inDataAddr =
GetSubfield(body, inBundleAddr,
"data");
1391 auto inBundleData =
GetInPort(module, 1);
1392 auto inReadyData =
GetSubfield(body, inBundleData,
"ready");
1393 auto inValidData =
GetSubfield(body, inBundleData,
"valid");
1394 auto inDataData =
GetSubfield(body, inBundleData,
"data");
1396 ::llvm::SmallVector<circt::firrtl::SubfieldOp> inReadyStates;
1397 ::llvm::SmallVector<circt::firrtl::SubfieldOp> inValidStates;
1398 ::llvm::SmallVector<circt::firrtl::SubfieldOp> inDataStates;
1399 for (
size_t i = 2; i < node->
ninputs() - 1; ++i)
1402 inReadyStates.push_back(
GetSubfield(body, bundle,
"ready"));
1403 inValidStates.push_back(
GetSubfield(body, bundle,
"valid"));
1404 inDataStates.push_back(
GetSubfield(body, bundle,
"data"));
1408 auto inReadyResp =
GetSubfield(body, inBundleResp,
"ready");
1409 auto inValidResp =
GetSubfield(body, inBundleResp,
"valid");
1411 ::llvm::SmallVector<circt::firrtl::SubfieldOp> outReadyStates;
1412 ::llvm::SmallVector<circt::firrtl::SubfieldOp> outValidStates;
1413 ::llvm::SmallVector<circt::firrtl::SubfieldOp> outDataStates;
1414 for (
size_t i = 0; i < node->
noutputs() - 2; ++i)
1417 outReadyStates.push_back(
GetSubfield(body, bundle,
"ready"));
1418 outValidStates.push_back(
GetSubfield(body, bundle,
"valid"));
1419 outDataStates.push_back(
GetSubfield(body, bundle,
"data"));
1423 auto outReadyMemAddr =
GetSubfield(body, outBundleMemAddr,
"ready");
1424 auto outValidMemAddr =
GetSubfield(body, outBundleMemAddr,
"valid");
1425 auto outDataMemAddr =
GetSubfield(body, outBundleMemAddr,
"data");
1429 auto outValidMemData =
GetSubfield(body, outBundleMemData,
"valid");
1430 auto outDataMemData =
GetSubfield(body, outBundleMemData,
"data");
1434 mlir::Value canRequest = inValidAddr;
1435 canRequest =
AddAndOp(body, canRequest, inValidData);
1436 for (
auto vld : inValidStates)
1438 canRequest =
AddAndOp(body, canRequest, vld);
1451 Connect(body, outValidMemAddr, canRequest);
1452 Connect(body, outDataMemAddr, inDataAddr);
1453 Connect(body, outValidMemData, canRequest);
1454 Connect(body, outDataMemData, inDataData);
1456 mlir::Value outStatesReady = oneBitValue;
1457 for (
size_t i = 0; i < node->
noutputs() - 2; ++i)
1459 Connect(body, outValidStates[i], inValidResp);
1461 outStatesReady =
AddAndOp(body, outReadyStates[i], outStatesReady);
1463 Connect(body, inReadyResp, outStatesReady);
1466 Connect(body, inReadyAddr, outReadyMemAddr);
1468 Connect(body, inReadyData, outReadyMemAddr);
1469 for (
size_t i = 2; i < node->
ninputs() - 1; ++i)
1471 Connect(body, inReadyStates[i - 2], outReadyMemAddr);
1476 circt::firrtl::FModuleOp
1481 auto body = module.getBodyBlock();
1489 auto inReady0 =
GetSubfield(body, inBundle0,
"ready");
1490 auto inValid0 =
GetSubfield(body, inBundle0,
"valid");
1491 auto inData0 =
GetSubfield(body, inBundle0,
"data");
1494 auto inReady1 =
GetSubfield(body, inBundle1,
"ready");
1495 auto inValid1 =
GetSubfield(body, inBundle1,
"valid");
1496 auto inData1 =
GetSubfield(body, inBundle1,
"data");
1501 mlir::BlockArgument inBundle2 = NULL;
1502 circt::firrtl::SubfieldOp inReady2 = NULL;
1503 circt::firrtl::SubfieldOp inValid2 = NULL;
1504 circt::firrtl::SubfieldOp inData2 = NULL;
1515 auto outReady0 =
GetSubfield(body, outBundle0,
"ready");
1516 auto outValid0 =
GetSubfield(body, outBundle0,
"valid");
1517 auto outData0 =
GetSubfield(body, outBundle0,
"data");
1520 mlir::BlockArgument memReq =
GetPort(module,
"mem_req");
1521 mlir::BlockArgument memRes =
GetPort(module,
"mem_res");
1523 auto memReqReady =
GetSubfield(body, memReq,
"ready");
1524 auto memReqValid =
GetSubfield(body, memReq,
"valid");
1525 auto memReqAddr =
GetSubfield(body, memReq,
"addr");
1526 auto memReqData =
GetSubfield(body, memReq,
"data");
1527 auto memReqWrite =
GetSubfield(body, memReq,
"write");
1528 auto memReqWidth =
GetSubfield(body, memReq,
"width");
1530 auto memResValid =
GetSubfield(body, memRes,
"valid");
1531 auto memResData =
GetSubfield(body, memRes,
"data");
1539 ::llvm::SmallVector<circt::firrtl::RegResetOp> oValidRegs;
1540 ::llvm::SmallVector<circt::firrtl::RegResetOp> oDataRegs;
1541 for (
size_t i = 0; i < node->
noutputs(); i++)
1543 std::string validName(
"o");
1544 validName.append(std::to_string(i));
1545 validName.append(
"_valid_reg");
1546 auto validReg =
Builder_->create<circt::firrtl::RegResetOp>(
1552 Builder_->getStringAttr(validName));
1553 body->push_back(validReg);
1554 oValidRegs.push_back(validReg);
1557 std::string dataName(
"o");
1558 dataName.append(std::to_string(i));
1559 dataName.append(
"_data_reg");
1560 auto dataReg =
Builder_->create<circt::firrtl::RegResetOp>(
1566 Builder_->getStringAttr(dataName));
1567 body->push_back(dataReg);
1568 oDataRegs.push_back(dataReg);
1570 auto sentReg =
Builder_->create<circt::firrtl::RegResetOp>(
1576 Builder_->getStringAttr(
"sent_reg"));
1577 body->push_back(sentReg);
1579 mlir::Value canRequest =
AddNotOp(body, sentReg.getResult());
1580 canRequest =
AddAndOp(body, canRequest, inValid0);
1581 canRequest =
AddAndOp(body, canRequest, inValid1);
1584 canRequest =
AddAndOp(body, canRequest, inValid2);
1586 for (
size_t i = 0; i < node->
noutputs(); i++)
1588 canRequest =
AddAndOp(body, canRequest,
AddNotOp(body, oValidRegs[i].getResult()));
1592 Connect(body, memReqValid, canRequest);
1593 Connect(body, memReqAddr, inData0);
1598 Connect(body, memReqWrite, oneBitValue);
1599 Connect(body, memReqData, inData1);
1600 bitWidth = std::dynamic_pointer_cast<const rvsdg::BitType>(node->
input(1)->
Type())->nbits();
1604 Connect(body, memReqWrite, zeroBitValue);
1606 Connect(body, memReqData, invalid);
1607 if (
auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(node->
output(0)->
Type()))
1609 bitWidth = bitType->nbits();
1611 else if (rvsdg::is<llvm::PointerType>(node->
output(0)->
Type()))
1617 throw util::Error(
"unknown width for mem request");
1621 int log2Bytes = log2(bitWidth / 8);
1625 auto whenReqFireOp =
AddWhenOp(body, memReqReady,
false);
1626 auto whenReqFireBody = whenReqFireOp.getThenBodyBuilder().getBlock();
1627 Connect(whenReqFireBody, sentReg.getResult(), oneBitValue);
1630 Connect(whenReqFireBody, oValidRegs[0].getResult(), oneBitValue);
1631 Connect(whenReqFireBody, oDataRegs[0].getResult(), inData2);
1635 Connect(whenReqFireBody, oValidRegs[1].getResult(), oneBitValue);
1636 Connect(whenReqFireBody, oDataRegs[1].getResult(), inData1);
1640 auto whenResFireOp =
AddWhenOp(body,
AddAndOp(body, sentReg.getResult(), memResValid),
false);
1641 auto whenResFireBody = whenResFireOp.getThenBodyBuilder().getBlock();
1642 Connect(whenResFireBody, sentReg.getResult(), zeroBitValue);
1645 Connect(whenResFireBody, oValidRegs[0].getResult(), oneBitValue);
1648 auto bitsOp =
AddBitsOp(whenResFireBody, memResData, bitWidth - 1, 0);
1649 Connect(whenResFireBody, oDataRegs[0].getResult(), bitsOp);
1653 Connect(whenResFireBody, oDataRegs[0].getResult(), memResData);
1658 Connect(body, inReady0, memReqReady);
1659 Connect(body, inReady1, memReqReady);
1662 Connect(body, inReady2, memReqReady);
1665 Connect(body, outValid0, oValidRegs[0].getResult());
1666 Connect(body, outData0, oDataRegs[0].getResult());
1667 auto andOp =
AddAndOp(body, outReady0, outValid0);
1670 AddWhenOp(body, andOp,
false).getThenBodyBuilder().getBlock(),
1671 oValidRegs[0].getResult(),
1676 auto outReady1 =
GetSubfield(body, outBundle1,
"ready");
1677 auto outValid1 =
GetSubfield(body, outBundle1,
"valid");
1678 auto outData1 =
GetSubfield(body, outBundle1,
"data");
1680 Connect(body, outValid1, oValidRegs[1].getResult());
1681 Connect(body, outData1, oDataRegs[1].getResult());
1682 auto andOp =
AddAndOp(body, outReady1, outValid1);
1685 AddWhenOp(body, andOp,
false).getThenBodyBuilder().getBlock(),
1686 oValidRegs[1].getResult(),
1693 circt::firrtl::FModuleOp
1698 auto body = module.getBodyBlock();
1702 auto inReady0 =
GetSubfield(body, inBundle0,
"ready");
1703 auto inValid0 =
GetSubfield(body, inBundle0,
"valid");
1706 auto inReady1 =
GetSubfield(body, inBundle1,
"ready");
1707 auto inValid1 =
GetSubfield(body, inBundle1,
"valid");
1708 auto inData1 =
GetSubfield(body, inBundle1,
"data");
1711 auto outReady =
GetSubfield(body, outBundle,
"ready");
1712 auto outValid =
GetSubfield(body, outBundle,
"valid");
1713 auto outData =
GetSubfield(body, outBundle,
"data");
1715 auto andOp0 =
AddAndOp(body, outReady, inValid1);
1716 auto andOp1 =
AddAndOp(body, outReady, inValid0);
1717 auto andOp2 =
AddAndOp(body, inValid0, inValid1);
1719 Connect(body, inReady0, andOp0);
1720 Connect(body, inReady1, andOp1);
1721 Connect(body, outValid, andOp2);
1722 Connect(body, outData, inData1);
1727 circt::firrtl::FModuleOp
1732 auto body = module.getBodyBlock();
1739 auto inReady =
GetSubfield(body, inBundle,
"ready");
1740 auto inValid =
GetSubfield(body, inBundle,
"valid");
1741 auto inData =
GetSubfield(body, inBundle,
"data");
1744 Connect(body, outBundle, inBundle);
1747 auto formatString =
"print node " + std::to_string(pn->id()) +
": %x\n";
1748 auto name =
"print_node_" + std::to_string(pn->id());
1749 auto printValue =
AddPadOp(body, inData, 64);
1750 ::llvm::SmallVector<mlir::Value>
operands;
1752 body->push_back(
Builder_->create<circt::firrtl::PrintFOp>(
1762 circt::firrtl::FModuleOp
1767 auto body = module.getBodyBlock();
1774 std::string validName(
"buf_valid_reg");
1775 auto validReg =
Builder_->create<circt::firrtl::RegResetOp>(
1781 Builder_->getStringAttr(validName));
1782 body->push_back(validReg);
1784 std::string dataName(
"buf_data_reg");
1785 auto dataReg =
Builder_->create<circt::firrtl::RegResetOp>(
1791 Builder_->getStringAttr(dataName));
1792 body->push_back(dataReg);
1795 auto inReady =
GetSubfield(body, inBundle,
"ready");
1796 auto inValid =
GetSubfield(body, inBundle,
"valid");
1797 auto inData =
GetSubfield(body, inBundle,
"data");
1800 auto outReady =
GetSubfield(body, outBundle,
"ready");
1801 auto outValid =
GetSubfield(body, outBundle,
"valid");
1802 auto outData =
GetSubfield(body, outBundle,
"data");
1804 auto orOp =
AddOrOp(body, validReg.getResult(), inValid);
1805 Connect(body, outValid, orOp);
1806 auto muxOp =
AddMuxOp(body, validReg.getResult(), dataReg.getResult(), inData);
1807 Connect(body, outData, muxOp);
1808 auto notOp =
AddNotOp(body, validReg.getResult());
1809 Connect(body, inReady, notOp);
1812 auto condition =
AddAndOp(body, inValid, inReady);
1813 auto whenOp =
AddWhenOp(body, condition,
false);
1814 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
1815 Connect(thenBody, validReg.getResult(), oneBitValue);
1816 Connect(thenBody, dataReg.getResult(), inData);
1819 condition =
AddAndOp(body, outValid, outReady);
1820 whenOp =
AddWhenOp(body, condition,
false);
1821 thenBody = whenOp.getThenBodyBuilder().getBlock();
1822 Connect(thenBody, validReg.getResult(), zeroBitValue);
1827 circt::firrtl::FModuleOp
1832 auto body = module.getBodyBlock();
1844 ::llvm::SmallVector<circt::firrtl::RegResetOp> validRegs;
1845 ::llvm::SmallVector<circt::firrtl::RegResetOp> dataRegs;
1846 for (
size_t i = 0; i <= capacity; i++)
1848 std::string validName(
"buf");
1849 validName.append(std::to_string(i));
1850 validName.append(
"_valid_reg");
1851 auto validReg =
Builder_->create<circt::firrtl::RegResetOp>(
1857 Builder_->getStringAttr(validName));
1858 body->push_back(validReg);
1859 validRegs.push_back(validReg);
1861 std::string dataName(
"buf");
1862 dataName.append(std::to_string(i));
1863 dataName.append(
"_data_reg");
1864 auto dataReg =
Builder_->create<circt::firrtl::RegResetOp>(
1870 Builder_->getStringAttr(dataName));
1871 body->push_back(dataReg);
1872 dataRegs.push_back(dataReg);
1878 Connect(body, validRegs[capacity].getResult(), zeroBitValue);
1879 Connect(body, dataRegs[capacity].getResult(), zeroValue);
1882 ::llvm::SmallVector<circt::firrtl::WireOp> shiftWires;
1883 ::llvm::SmallVector<circt::firrtl::WireOp> consumedWires;
1884 for (
size_t i = 0; i <= capacity; i++)
1886 std::string shiftName(
"shift_out");
1887 shiftName.append(std::to_string(i));
1888 shiftWires.push_back(
AddWireOp(body, shiftName, 1));
1889 std::string consumedName(
"in_consumed");
1890 consumedName.append(std::to_string(i));
1891 consumedWires.push_back(
AddWireOp(body, consumedName, 1));
1895 auto inReady =
GetSubfield(body, inBundle,
"ready");
1896 auto inValid =
GetSubfield(body, inBundle,
"valid");
1897 auto inData =
GetSubfield(body, inBundle,
"data");
1900 auto outReady =
GetSubfield(body, outBundle,
"ready");
1901 auto outValid =
GetSubfield(body, outBundle,
"valid");
1902 auto outData =
GetSubfield(body, outBundle,
"data");
1905 Connect(body, outValid, validRegs[0].getResult());
1906 Connect(body, outData, dataRegs[0].getResult());
1907 auto andOp =
AddAndOp(body, outReady, outValid);
1908 Connect(body, shiftWires[0].getResult(), andOp);
1909 if (op->IsPassThrough())
1911 auto notOp =
AddNotOp(body, validRegs[0].getResult());
1912 andOp =
AddAndOp(body, notOp, outReady);
1913 Connect(body, consumedWires[0].getResult(), andOp);
1914 auto whenOp =
AddWhenOp(body, notOp,
false);
1915 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
1916 Connect(thenBody, outData, inData);
1917 Connect(thenBody, outValid, inValid);
1921 Connect(body, consumedWires[0].getResult(), zeroBitValue);
1925 auto notOp =
AddNotOp(body, validRegs[capacity - 1].getResult());
1926 Connect(body, inReady, notOp);
1928 andOp =
AddAndOp(body, inReady, inValid);
1929 for (
size_t i = 0; i < capacity; ++i)
1931 Connect(body, consumedWires[i + 1].getResult(), consumedWires[i].getResult());
1932 Connect(body, shiftWires[i + 1].getResult(), zeroBitValue);
1935 auto whenOp =
AddWhenOp(body, shiftWires[i].getResult(),
false);
1936 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
1937 Connect(thenBody, validRegs[i].getResult(), zeroBitValue);
1940 auto notOp =
AddNotOp(body, validRegs[i].getResult());
1941 auto condition =
AddOrOp(body, shiftWires[i].getResult(), notOp);
1942 whenOp =
AddWhenOp(body, condition,
false);
1943 thenBody = whenOp.getThenBodyBuilder().getBlock();
1945 notOp =
AddNotOp(thenBody, consumedWires[i].getResult());
1946 auto elseCondition =
AddAndOp(thenBody, andOp, notOp);
1949 whenOp =
AddWhenOp(thenBody, validRegs[i + 1].getResult(),
true);
1950 thenBody = whenOp.getThenBodyBuilder().getBlock();
1951 Connect(thenBody, validRegs[i].getResult(), oneBitValue);
1952 Connect(thenBody, dataRegs[i].getResult(), dataRegs[i + 1].getResult());
1953 Connect(thenBody, shiftWires[i + 1].getResult(), oneBitValue);
1956 auto elseBody = whenOp.getElseBodyBuilder().getBlock();
1957 auto nestedWhen =
AddWhenOp(elseBody, elseCondition,
false);
1958 thenBody = nestedWhen.getThenBodyBuilder().getBlock();
1959 Connect(thenBody, consumedWires[i + 1].getResult(), oneBitValue);
1960 Connect(thenBody, validRegs[i].getResult(), oneBitValue);
1961 Connect(thenBody, dataRegs[i].getResult(), inData);
1967 circt::firrtl::FModuleOp
1972 auto body = module.getBodyBlock();
1984 ::llvm::SmallVector<circt::firrtl::RegResetOp> validRegs;
1985 ::llvm::SmallVector<circt::firrtl::RegResetOp> dataRegs;
1986 for (
size_t i = 0; i <= capacity; i++)
1988 std::string validName(
"buf");
1989 validName.append(std::to_string(i));
1990 validName.append(
"_valid_reg");
1991 auto validReg =
Builder_->create<circt::firrtl::RegResetOp>(
1997 Builder_->getStringAttr(validName));
1998 body->push_back(validReg);
1999 validRegs.push_back(validReg);
2001 std::string dataName(
"buf");
2002 dataName.append(std::to_string(i));
2003 dataName.append(
"_data_reg");
2004 auto dataReg =
Builder_->create<circt::firrtl::RegResetOp>(
2010 Builder_->getStringAttr(dataName));
2011 body->push_back(dataReg);
2012 dataRegs.push_back(dataReg);
2018 Connect(body, validRegs[capacity].getResult(), zeroBitValue);
2019 Connect(body, dataRegs[capacity].getResult(), zeroValue);
2022 ::llvm::SmallVector<circt::firrtl::WireOp> shiftWires;
2023 ::llvm::SmallVector<circt::firrtl::WireOp> consumedWires;
2024 for (
size_t i = 0; i <= capacity; i++)
2026 std::string shiftName(
"shift_out");
2027 shiftName.append(std::to_string(i));
2028 shiftWires.push_back(
AddWireOp(body, shiftName, 1));
2029 std::string consumedName(
"in_consumed");
2030 consumedName.append(std::to_string(i));
2031 consumedWires.push_back(
AddWireOp(body, consumedName, 1));
2034 auto checkBundle =
GetInPort(module, 0);
2035 auto checkReady =
GetSubfield(body, checkBundle,
"ready");
2036 auto checkValid =
GetSubfield(body, checkBundle,
"valid");
2037 auto checkData =
GetSubfield(body, checkBundle,
"data");
2040 auto enqReady =
GetSubfield(body, enqBundle,
"ready");
2041 auto enqValid =
GetSubfield(body, enqBundle,
"valid");
2042 auto enqData =
GetSubfield(body, enqBundle,
"data");
2045 auto deqReady =
GetSubfield(body, deqBundle,
"ready");
2046 auto deqValid =
GetSubfield(body, deqBundle,
"valid");
2049 auto outReady =
GetSubfield(body, outBundle,
"ready");
2050 auto outValid =
GetSubfield(body, outBundle,
"valid");
2051 auto outData =
GetSubfield(body, outBundle,
"data");
2054 auto addr_in_queue_wire =
AddWireOp(body,
"addr_in_queue", 1);
2055 auto addr_out_valid =
AddAndOp(body, checkValid,
AddNotOp(body, addr_in_queue_wire.getResult()));
2056 Connect(body, outValid, addr_out_valid);
2057 Connect(body, outData, checkData);
2059 auto andOp =
AddAndOp(body, deqReady, deqValid);
2061 Connect(body, deqReady, validRegs[0].getResult());
2063 Connect(body, shiftWires[0].getResult(), andOp);
2073 Connect(body, consumedWires[0].getResult(), zeroBitValue);
2077 auto notOp =
AddNotOp(body, validRegs[capacity - 1].getResult());
2078 Connect(body, enqReady, notOp);
2080 andOp =
AddAndOp(body, enqReady, enqValid);
2081 mlir::Value addr_in_queue = zeroBitValue;
2082 for (
size_t i = 0; i < capacity; ++i)
2084 Connect(body, consumedWires[i + 1].getResult(), consumedWires[i].getResult());
2085 Connect(body, shiftWires[i + 1].getResult(), zeroBitValue);
2088 auto whenOp =
AddWhenOp(body, shiftWires[i].getResult(),
false);
2089 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
2090 Connect(thenBody, validRegs[i].getResult(), zeroBitValue);
2093 auto notOp =
AddNotOp(body, validRegs[i].getResult());
2094 auto condition =
AddOrOp(body, shiftWires[i].getResult(), notOp);
2095 whenOp =
AddWhenOp(body, condition,
false);
2096 thenBody = whenOp.getThenBodyBuilder().getBlock();
2098 notOp =
AddNotOp(thenBody, consumedWires[i].getResult());
2099 auto elseCondition =
AddAndOp(thenBody, andOp, notOp);
2102 whenOp =
AddWhenOp(thenBody, validRegs[i + 1].getResult(),
true);
2103 thenBody = whenOp.getThenBodyBuilder().getBlock();
2104 Connect(thenBody, validRegs[i].getResult(), oneBitValue);
2105 Connect(thenBody, dataRegs[i].getResult(), dataRegs[i + 1].getResult());
2106 Connect(thenBody, shiftWires[i + 1].getResult(), oneBitValue);
2109 auto elseBody = whenOp.getElseBodyBuilder().getBlock();
2110 auto nestedWhen =
AddWhenOp(elseBody, elseCondition,
false);
2111 thenBody = nestedWhen.getThenBodyBuilder().getBlock();
2112 Connect(thenBody, consumedWires[i + 1].getResult(), oneBitValue);
2113 Connect(thenBody, validRegs[i].getResult(), oneBitValue);
2114 Connect(thenBody, dataRegs[i].getResult(), enqData);
2121 validRegs[i].getResult(),
2122 AddEqOp(body, dataRegs[i].getResult(), checkData)));
2124 if (op->combinatorial)
2130 Connect(body, addr_in_queue_wire.getResult(), addr_in_queue);
2135 circt::firrtl::FModuleOp
2140 auto body = module.getBodyBlock();
2144 auto inputs = node->
ninputs();
2146 auto outReady =
GetSubfield(body, outBundle,
"ready");
2148 auto outValid =
GetSubfield(body, outBundle,
"valid");
2149 Connect(body, outValid, zeroBitValue);
2152 auto outData =
GetSubfield(body, outBundle,
"data");
2153 Connect(body, outData, invalid);
2156 auto inReady0 =
GetSubfield(body, inBundle0,
"ready");
2157 auto inValid0 =
GetSubfield(body, inBundle0,
"valid");
2158 auto inData0 =
GetSubfield(body, inBundle0,
"data");
2167 auto ctr_max =
GetConstant(body, ctr_bits, (1 << ctr_bits) - 1);
2169 ::llvm::SmallVector<mlir::Value> discard_queueds;
2170 ::llvm::SmallVector<circt::firrtl::WireOp> discardWires;
2171 mlir::Value any_discard_full =
GetConstant(body, 1, 0);
2174 for (
size_t i = 1; i < inputs; i++)
2177 auto inReady =
GetSubfield(body, inBundle,
"ready");
2178 auto inValid =
GetSubfield(body, inBundle,
"valid");
2180 std::string regName(
"i");
2181 regName.append(std::to_string(i));
2182 regName.append(
"_discard_ctr");
2183 auto discard_ctr_reg =
Builder_->create<circt::firrtl::RegResetOp>(
2190 body->push_back(discard_ctr_reg);
2192 std::string wireName(
"i");
2193 wireName.append(std::to_string(i));
2194 wireName.append(
"_discard");
2195 auto discard_wire =
AddWireOp(body, wireName, 1);
2196 discardWires.push_back(discard_wire);
2197 Connect(body, discard_wire.getResult(), zeroBitValue);
2198 auto discard_queued =
AddNeqOp(body, discard_ctr_reg.getResult(), ctr_zero);
2199 discard_queueds.push_back(discard_queued);
2200 auto discard_full =
AddEqOp(body, discard_ctr_reg.getResult(), ctr_max);
2201 any_discard_full =
AddOrOp(body, any_discard_full, discard_full);
2202 auto fire =
AddAndOp(body, inReady, inValid);
2203 Connect(body, inReady,
AddOrOp(body, discard_queued, discard_wire.getResult()));
2208 AddAndOp(body, discard_queued, fire),
2209 AddNotOp(body, discard_wire.getResult())),
2213 &whenOp.getThenBlock(),
2214 discard_ctr_reg.getResult(),
2216 &whenOp.getThenBlock(),
2217 AddSubOp(&whenOp.getThenBlock(), discard_ctr_reg.getResult(), ctr_one),
2220 &whenOp.getElseBlock(),
2222 &whenOp.getElseBlock(),
2223 discard_wire.getResult(),
2224 AddNotOp(&whenOp.getElseBlock(), fire)),
2228 &elseWhenOp.getThenBlock(),
2229 discard_ctr_reg.getResult(),
2231 &elseWhenOp.getThenBlock(),
2232 AddAddOp(&elseWhenOp.getThenBlock(), discard_ctr_reg.getResult(), ctr_one),
2236 auto out_fire =
AddAndOp(body, outReady, outValid);
2237 Connect(body, inReady0, out_fire);
2242 for (
size_t i = 1; i < inputs; i++)
2245 auto inReady =
GetSubfield(matchBlock, inBundle,
"ready");
2246 auto inValid =
GetSubfield(matchBlock, inBundle,
"valid");
2247 auto inData =
GetSubfield(matchBlock, inBundle,
"data");
2254 AddNotOp(matchBlock, discard_queueds[i - 1])),
2257 Connect(whenBlock, outValid, inValid);
2258 Connect(whenBlock, outData, inData);
2259 Connect(whenBlock, inReady, outReady);
2260 for (
size_t j = 1; j < inputs; j++)
2266 Connect(whenBlock, discardWires[j - 1].getResult(), out_fire);
2273 circt::firrtl::FModuleOp
2278 auto body = module.getBodyBlock();
2280 auto inputs = node->
ninputs();
2282 auto outReady =
GetSubfield(body, outBundle,
"ready");
2284 auto outValid =
GetSubfield(body, outBundle,
"valid");
2286 Connect(body, outValid, zeroBitValue);
2289 auto outData =
GetSubfield(body, outBundle,
"data");
2290 Connect(body, outData, invalid);
2293 auto inReady0 =
GetSubfield(body, inBundle0,
"ready");
2294 auto inValid0 =
GetSubfield(body, inBundle0,
"valid");
2295 Connect(body, inReady0, zeroBitValue);
2296 auto inData0 =
GetSubfield(body, inBundle0,
"data");
2299 for (
size_t i = 1; i < inputs; i++)
2302 auto inReady =
GetSubfield(body, inBundle,
"ready");
2303 auto inValid =
GetSubfield(body, inBundle,
"valid");
2304 auto inData =
GetSubfield(body, inBundle,
"data");
2305 Connect(body, inReady, zeroBitValue);
2307 auto eqOp =
AddEqOp(body, inData0, constant);
2308 auto andOp =
AddAndOp(body, inValid0, eqOp);
2309 auto whenOp =
AddWhenOp(body, andOp,
false);
2310 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
2311 Connect(thenBody, outValid, inValid);
2312 Connect(thenBody, outData, inData);
2313 Connect(thenBody, inReady, outReady);
2314 auto whenAnd =
AddAndOp(thenBody, outReady, inValid);
2315 Connect(thenBody, inReady0, whenAnd);
2320 circt::firrtl::FModuleOp
2325 auto body = module.getBodyBlock();
2330 auto inReady0 =
GetSubfield(body, inBundle0,
"ready");
2331 auto inValid0 =
GetSubfield(body, inBundle0,
"valid");
2332 auto inData0 =
GetSubfield(body, inBundle0,
"data");
2335 auto inReady1 =
GetSubfield(body, inBundle1,
"ready");
2336 auto inValid1 =
GetSubfield(body, inBundle1,
"valid");
2337 auto inData1 =
GetSubfield(body, inBundle1,
"data");
2339 Connect(body, inReady0, zeroBitValue);
2340 Connect(body, inReady1, zeroBitValue);
2343 for (
size_t i = 0; i < node->
noutputs(); i++)
2346 auto outReady =
GetSubfield(body, outBundle,
"ready");
2347 auto outValid =
GetSubfield(body, outBundle,
"valid");
2348 auto outData =
GetSubfield(body, outBundle,
"data");
2349 Connect(body, outValid, zeroBitValue);
2350 Connect(body, outData, invalid);
2353 auto eqOp =
AddEqOp(body, inData0, constant);
2354 auto condition =
AddAndOp(body, inValid0, eqOp);
2355 auto whenOp =
AddWhenOp(body, condition,
false);
2356 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
2357 Connect(thenBody, inReady1, outReady);
2358 auto andOp =
AddAndOp(thenBody, outReady, inValid1);
2359 Connect(thenBody, inReady0, andOp);
2360 Connect(thenBody, outValid, inValid1);
2361 Connect(thenBody, outData, inData1);
2367 circt::firrtl::FModuleLike
2378 else if (rvsdg::is<LoopConstantBufferOperation>(node))
2403 if (rvsdg::is<LocalStoreOperation>(node))
2412 else if (rvsdg::is<MemoryResponseOperation>(node))
2416 else if (rvsdg::is<MemoryRequestOperation>(node))
2420 else if (jlm::rvsdg::is<const PredicateBufferOperation>(node->
GetOperation()))
2433 else if (rvsdg::is<TriggerOperation>(node))
2437 else if (rvsdg::is<StateGateOperation>(node))
2460 bool is_float =
false;
2461 for (
size_t i = 0; i < node->
ninputs(); ++i)
2463 is_float = is_float || rvsdg::is<const llvm::FloatingPointType>(node->
input(i)->
Type());
2465 for (
size_t i = 0; i < node->
noutputs(); ++i)
2467 is_float = is_float || rvsdg::is<const llvm::FloatingPointType>(node->
output(i)->
Type());
2476 circt::firrtl::FModuleOp
2481 auto body = module.getBodyBlock();
2486 Builder_->create<circt::firrtl::InstanceOp>(
Builder_->getUnknownLoc(), srModule,
"sr");
2487 body->push_back(instance);
2494 JLM_ASSERT(instance.getNumResults() == module.getNumPorts());
2496 const size_t clockAndResetOffset = 2;
2497 for (
size_t i = 0; i < loopNode->
ninputs(); ++i)
2500 auto sourcePort = body->getArgument(i + clockAndResetOffset);
2503 for (
size_t i = 0; i < loopNode->
noutputs(); ++i)
2506 auto sinkPort = body->getArgument(i + loopNode->
ninputs() + clockAndResetOffset);
2512 circt::firrtl::BitsPrimOp
2515 auto type = value.getType().cast<circt::firrtl::UIntType>();
2516 auto width =
type.getWidth();
2517 auto result =
AddBitsOp(body, value, width.value() - 1 - amount, 0);
2528 auto region = arg->
region();
2529 auto node = region->
node();
2530 if (
dynamic_cast<LoopNode *
>(node))
2534 return ba->result()->origin();
2563 circt::firrtl::FModuleLike
2567 ::llvm::SmallVector<circt::firrtl::PortInfo> ports;
2573 for (
size_t i = 0; i < subRegion->
narguments(); ++i)
2579 circt::firrtl::Direction::In,
2585 for (
size_t i = 0; i < subRegion->
nresults(); ++i)
2591 circt::firrtl::Direction::Out,
2600 auto module =
Builder_->create<circt::firrtl::FModuleOp>(
2603 circt::firrtl::ConventionAttr::get(
2605 circt::firrtl::Convention::Internal),
2608 auto body = module.getBodyBlock();
2610 const size_t clockAndResetOffset = 2;
2612 std::unordered_map<rvsdg::Output *, mlir::Value>
output_map;
2614 for (
size_t i = 0; i < subRegion->
narguments(); ++i)
2619 auto op =
Builder_->create<circt::firrtl::WireOp>(
2623 body->push_back(op);
2630 if (!rvsdg::is<rvsdg::LambdaOperation>(subRegion->
node()))
2634 auto sourcePort = body->getArgument(ix + clockAndResetOffset);
2639 auto clock = body->getArgument(0);
2640 auto reset = body->getArgument(1);
2645 body->push_back(instance);
2647 Connect(body, instance->getResult(0), clock);
2648 Connect(body, instance->getResult(1), reset);
2650 for (
size_t i = 0; i < node->ninputs(); ++i)
2652 auto sourcePort =
output_map[node->input(i)->origin()];
2653 auto sinkPort = instance->getResult(i + clockAndResetOffset);
2654 Connect(body, sinkPort, sourcePort);
2657 for (
size_t i = 0; i < node->noutputs(); ++i)
2659 auto outputPort = instance->getResult(i + node->ninputs() + clockAndResetOffset);
2664 for (
size_t i = 0; i < subRegion->
nresults(); ++i)
2666 mlir::Value resultSink;
2670 auto op =
Builder_->create<circt::firrtl::WireOp>(
2674 body->push_back(op);
2675 resultSink = op.getResult();
2683 if (!rvsdg::is<rvsdg::LambdaOperation>(subRegion->
node()))
2687 resultSink = body->getArgument(ix + module.getNumInputPorts());
2691 circuitBody->push_back(module);
2700 auto node = output->
node();
2703 if (!
dynamic_cast<LoopNode *
>(node))
2705 throw std::logic_error(
"Expected a hls::LoopNode but found: " + node->DebugString());
2715 if (rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*origin))
2722 throw std::logic_error(
"Encountered pass through argument - should be eliminated");
2726 throw std::logic_error(
"Encountered an unexpected output type");
2731 circt::firrtl::CircuitOp
2738 auto moduleName =
Builder_->getStringAttr(
2741 auto circuit =
Builder_->create<circt::firrtl::CircuitOp>(
Builder_->getUnknownLoc(), moduleName);
2743 auto circuitBody = circuit.getBodyBlock();
2746 auto subRegion = lambdaNode->
subregion();
2752 ::llvm::SmallVector<circt::firrtl::PortInfo> ports;
2762 using BundleElement = circt::firrtl::BundleType::BundleElement;
2763 ::llvm::SmallVector<BundleElement> inputElements;
2767 for (
size_t i = 0; i < reg_args.size(); ++i)
2772 std::string portName(
"data_");
2773 portName.append(std::to_string(i));
2774 inputElements.push_back(BundleElement(
2779 auto inputType = circt::firrtl::BundleType::get(
Builder_->getContext(), inputElements);
2780 struct circt::firrtl::PortInfo iBundle = {
2781 Builder_->getStringAttr(
"i"), inputType, circt::firrtl::Direction::In, {},
2784 ports.push_back(iBundle);
2787 ::llvm::SmallVector<BundleElement> outputElements;
2790 for (
size_t i = 0; i < reg_results.size(); ++i)
2795 std::string portName(
"data_");
2796 portName.append(std::to_string(i));
2797 outputElements.push_back(BundleElement(
2802 auto outputType = circt::firrtl::BundleType::get(
Builder_->getContext(), outputElements);
2803 struct circt::firrtl::PortInfo oBundle = {
2804 Builder_->getStringAttr(
"o"), outputType, circt::firrtl::Direction::Out, {},
2807 ports.push_back(oBundle);
2812 JLM_ASSERT(mem_resps.size() == mem_reqs.size());
2813 for (
size_t i = 0; i < mem_reqs.size(); ++i)
2815 ::llvm::SmallVector<BundleElement> memElements;
2817 ::llvm::SmallVector<BundleElement> reqElements;
2820 reqElements.push_back(BundleElement(
2824 auto reqType = circt::firrtl::BundleType::get(
Builder_->getContext(), reqElements);
2825 memElements.push_back(BundleElement(
Builder_->getStringAttr(
"req"),
false, reqType));
2827 ::llvm::SmallVector<BundleElement> resElements;
2830 resElements.push_back(BundleElement(
2834 auto resType = circt::firrtl::BundleType::get(
Builder_->getContext(), resElements);
2835 memElements.push_back(BundleElement(
Builder_->getStringAttr(
"res"),
true, resType));
2837 auto memType = circt::firrtl::BundleType::get(
Builder_->getContext(), memElements);
2838 struct circt::firrtl::PortInfo memBundle = {
2839 Builder_->getStringAttr(
"mem_" + std::to_string(i)),
2841 circt::firrtl::Direction::Out,
2845 ports.push_back(memBundle);
2850 auto module =
Builder_->create<circt::firrtl::FModuleOp>(
2853 circt::firrtl::ConventionAttr::get(
2855 circt::firrtl::Convention::Internal),
2858 auto body = module.getBodyBlock();
2861 auto srModule =
MlirGen(subRegion, circuitBody);
2864 Builder_->create<circt::firrtl::InstanceOp>(
Builder_->getUnknownLoc(), srModule,
"sr");
2865 body->push_back(instance);
2880 ::llvm::SmallVector<circt::firrtl::RegResetOp> inputValidRegs;
2881 ::llvm::SmallVector<circt::firrtl::RegResetOp> inputDataRegs;
2882 for (
size_t i = 0; i < reg_args.size(); ++i)
2884 std::string validName(
"i");
2885 validName.append(std::to_string(i));
2886 validName.append(
"_valid_reg");
2887 auto validReg =
Builder_->create<circt::firrtl::RegResetOp>(
2893 Builder_->getStringAttr(validName));
2894 body->push_back(validReg);
2895 inputValidRegs.push_back(validReg);
2897 std::string dataName(
"i");
2898 dataName.append(std::to_string(i));
2899 dataName.append(
"_data_reg");
2900 auto dataReg =
Builder_->create<circt::firrtl::RegResetOp>(
2906 Builder_->getStringAttr(dataName));
2907 body->push_back(dataReg);
2908 inputDataRegs.push_back(dataReg);
2910 auto port =
GetInstancePort(instance,
"a" + std::to_string(reg_args[i]->index()));
2911 auto portValid =
GetSubfield(body, port,
"valid");
2912 Connect(body, portValid, validReg.getResult());
2914 Connect(body, portData, dataReg.getResult());
2917 auto portReady =
GetSubfield(body, port,
"ready");
2918 auto whenCondition =
AddAndOp(body, portReady, portValid);
2919 auto whenOp =
AddWhenOp(body, whenCondition,
false);
2923 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
2924 Connect(thenBody, validReg.getResult(), zeroBitValue);
2931 ::llvm::SmallVector<circt::firrtl::RegResetOp> outputValidRegs;
2932 ::llvm::SmallVector<circt::firrtl::RegResetOp> outputDataRegs;
2935 for (
size_t i = 0; i < reg_results.size(); ++i)
2937 std::string validName(
"o");
2938 validName.append(std::to_string(i));
2939 validName.append(
"_valid_reg");
2940 auto validReg =
Builder_->create<circt::firrtl::RegResetOp>(
2946 Builder_->getStringAttr(validName));
2947 body->push_back(validReg);
2948 outputValidRegs.push_back(validReg);
2950 std::string dataName(
"o");
2951 dataName.append(std::to_string(i));
2952 dataName.append(
"_data_reg");
2953 auto dataReg =
Builder_->create<circt::firrtl::RegResetOp>(
2959 Builder_->getStringAttr(dataName));
2960 body->push_back(dataReg);
2961 outputDataRegs.push_back(dataReg);
2964 auto port =
GetInstancePort(instance,
"r" + std::to_string(reg_results[i]->index()));
2966 auto portReady =
GetSubfield(body, port,
"ready");
2967 auto notValidReg =
Builder_->create<circt::firrtl::NotPrimOp>(
2969 circt::firrtl::IntType::get(
Builder_->getContext(),
false, 1),
2970 validReg.getResult());
2971 body->push_back(notValidReg);
2972 Connect(body, portReady, notValidReg);
2975 auto portValid =
GetSubfield(body, port,
"valid");
2977 auto whenCondition =
AddAndOp(body, portReady, portValid);
2978 auto whenOp =
AddWhenOp(body, whenCondition,
false);
2982 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
2983 Connect(thenBody, validReg.getResult(), oneBitValue);
2984 Connect(thenBody, dataReg.getResult(), portData);
2988 mlir::Value prevAnd = oneBitValue;
2989 for (
size_t i = 0; i < inputValidRegs.size(); i++)
2991 auto notReg =
Builder_->create<circt::firrtl::NotPrimOp>(
2993 circt::firrtl::IntType::get(
Builder_->getContext(),
false, 1),
2994 inputValidRegs[i].getResult());
2995 body->push_back(notReg);
2996 auto andOp =
AddAndOp(body, notReg, prevAnd);
2999 auto inBundle =
GetPort(module,
"i");
3000 auto inReady =
GetSubfield(body, inBundle,
"ready");
3001 Connect(body, inReady, prevAnd);
3004 prevAnd = oneBitValue;
3005 for (
size_t i = 0; i < outputValidRegs.size(); i++)
3007 auto andOp =
AddAndOp(body, outputValidRegs[i].getResult(), prevAnd);
3010 auto outBundle =
GetPort(module,
"o");
3011 auto outValid =
GetSubfield(body, outBundle,
"valid");
3012 Connect(body, outValid, prevAnd);
3015 for (
size_t i = 0; i < outputDataRegs.size(); i++)
3020 auto outData =
GetSubfield(body, outBundle,
"data_" + std::to_string(i));
3021 Connect(body, outData, outputDataRegs[i].getResult());
3024 if (inputValidRegs.size())
3027 auto inValid =
GetSubfield(body, inBundle,
"valid");
3028 auto whenCondition =
AddAndOp(body, inReady, inValid);
3029 auto whenOp =
AddWhenOp(body, whenCondition,
false);
3033 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
3034 for (
size_t i = 0; i < inputValidRegs.size(); i++)
3036 Connect(thenBody, inputValidRegs[i].getResult(), oneBitValue);
3040 auto inData =
GetSubfield(thenBody, inBundle,
"data_" + std::to_string(i));
3041 Connect(thenBody, inputDataRegs[i].getResult(), inData);
3046 auto outReady =
GetSubfield(body, outBundle,
"ready");
3047 auto whenCondition =
AddAndOp(body, outReady, outValid);
3048 auto whenOp =
AddWhenOp(body, whenCondition,
false);
3051 auto thenBody = whenOp.getThenBodyBuilder().getBlock();
3052 for (
size_t i = 0; i < outputValidRegs.size(); i++)
3054 Connect(thenBody, outputValidRegs[i].getResult(), zeroBitValue);
3058 for (
size_t i = 0; i < mem_reqs.size(); ++i)
3060 auto mem_port =
GetPort(module,
"mem_" + std::to_string(i));
3061 auto mem_req =
GetSubfield(body, mem_port,
"req");
3062 auto mem_res =
GetSubfield(body, mem_port,
"res");
3063 auto inst_req =
GetInstancePort(instance,
"r" + std::to_string(mem_reqs[i]->index()));
3064 auto inst_res =
GetInstancePort(instance,
"a" + std::to_string(mem_resps[i]->index()));
3065 Connect(body, mem_req, inst_req);
3066 Connect(body, inst_res, mem_res);
3070 circuitBody->push_back(module);
3083 struct circt::firrtl::PortInfo port = {
3084 Builder_->getStringAttr(
"clk"), circt::firrtl::ClockType::get(
Builder_->getContext()),
3085 circt::firrtl::Direction::In, {},
3088 ports->push_back(port);
3095 struct circt::firrtl::PortInfo port = {
3096 Builder_->getStringAttr(
"reset"), circt::firrtl::IntType::get(
Builder_->getContext(),
false, 1),
3097 circt::firrtl::Direction::In, {},
3100 ports->push_back(port);
3106 using BundleElement = circt::firrtl::BundleType::BundleElement;
3108 ::llvm::SmallVector<BundleElement> memReqElements;
3111 memReqElements.push_back(BundleElement(
3115 memReqElements.push_back(BundleElement(
3118 circt::firrtl::IntType::get(
Builder_->getContext(),
false, 64)));
3119 memReqElements.push_back(BundleElement(
3122 circt::firrtl::IntType::get(
Builder_->getContext(),
false, 1)));
3123 memReqElements.push_back(BundleElement(
3126 circt::firrtl::IntType::get(
Builder_->getContext(),
false, 3)));
3128 auto memType = circt::firrtl::BundleType::get(
Builder_->getContext(), memReqElements);
3129 struct circt::firrtl::PortInfo memBundle = {
3130 Builder_->getStringAttr(
"mem_req"), memType, circt::firrtl::Direction::Out, {},
3133 ports->push_back(memBundle);
3139 using BundleElement = circt::firrtl::BundleType::BundleElement;
3141 ::llvm::SmallVector<BundleElement> memResElements;
3143 memResElements.push_back(BundleElement(
3146 circt::firrtl::IntType::get(
Builder_->getContext(),
false, 64)));
3148 auto memResType = circt::firrtl::BundleType::get(
Builder_->getContext(), memResElements);
3149 struct circt::firrtl::PortInfo memResBundle = {
3150 Builder_->getStringAttr(
"mem_res"), memResType, circt::firrtl::Direction::In, {},
3153 ports->push_back(memResBundle);
3158 ::llvm::SmallVector<circt::firrtl::PortInfo> * ports,
3159 circt::firrtl::Direction direction,
3161 circt::firrtl::FIRRTLBaseType
type)
3164 struct circt::firrtl::PortInfo bundle = {
3165 Builder_->getStringAttr(name), bundleType, direction, {},
Builder_->getUnknownLoc(),
3167 ports->push_back(bundle);
3170 circt::firrtl::BundleType
3173 using BundleElement = circt::firrtl::BundleType::BundleElement;
3175 ::llvm::SmallVector<BundleElement> elements;
3178 elements.push_back(BundleElement(this->
Builder_->getStringAttr(
"data"),
false, type));
3180 return circt::firrtl::BundleType::get(this->
Builder_->getContext(), elements);
3183 circt::firrtl::SubfieldOp
3187 Builder_->create<circt::firrtl::SubfieldOp>(
Builder_->getUnknownLoc(), value, index);
3188 body->push_back(subfield);
3192 circt::firrtl::SubfieldOp
3196 ::llvm::StringRef fieldName)
3199 Builder_->create<circt::firrtl::SubfieldOp>(
Builder_->getUnknownLoc(), value, fieldName);
3200 body->push_back(subfield);
3207 for (
size_t i = 0; i < module.getNumPorts(); ++i)
3209 if (module.getPortName(i) == portName)
3211 return module.getArgument(i);
3214 llvm_unreachable(
"port not found");
3220 for (
size_t i = 0; i < instance.getNumResults(); ++i)
3223 if (instance.getPortName(i) == portName)
3225 return instance->getResult(i);
3228 llvm_unreachable(
"port not found");
3234 return GetPort(module,
"i" + std::to_string(portNr));
3240 return GetPort(module,
"o" + std::to_string(portNr));
3247 Builder_->create<circt::firrtl::ConnectOp>(
Builder_->getUnknownLoc(), sink, source));
3250 circt::firrtl::BitsPrimOp
3253 auto intType =
Builder_->getIntegerType(32);
3254 auto op =
Builder_->create<circt::firrtl::BitsPrimOp>(
3257 Builder_->getIntegerAttr(intType, high),
3258 Builder_->getIntegerAttr(intType, low));
3259 body->push_back(op);
3263 circt::firrtl::AndPrimOp
3266 auto op =
Builder_->create<circt::firrtl::AndPrimOp>(
Builder_->getUnknownLoc(), first, second);
3267 body->push_back(op);
3271 circt::firrtl::NodeOp
3274 auto op =
Builder_->create<circt::firrtl::NodeOp>(
Builder_->getUnknownLoc(), value, name);
3275 body->push_back(op);
3279 circt::firrtl::XorPrimOp
3282 auto op =
Builder_->create<circt::firrtl::XorPrimOp>(
Builder_->getUnknownLoc(), first, second);
3283 body->push_back(op);
3287 circt::firrtl::OrPrimOp
3290 auto op =
Builder_->create<circt::firrtl::OrPrimOp>(
Builder_->getUnknownLoc(), first, second);
3291 body->push_back(op);
3295 circt::firrtl::NotPrimOp
3298 auto op =
Builder_->create<circt::firrtl::NotPrimOp>(
Builder_->getUnknownLoc(), first);
3299 body->push_back(op);
3303 circt::firrtl::AddPrimOp
3306 auto op =
Builder_->create<circt::firrtl::AddPrimOp>(
Builder_->getUnknownLoc(), first, second);
3307 body->push_back(op);
3311 circt::firrtl::SubPrimOp
3314 auto op =
Builder_->create<circt::firrtl::SubPrimOp>(
Builder_->getUnknownLoc(), first, second);
3315 body->push_back(op);
3319 circt::firrtl::MulPrimOp
3322 auto op =
Builder_->create<circt::firrtl::MulPrimOp>(
Builder_->getUnknownLoc(), first, second);
3323 body->push_back(op);
3327 circt::firrtl::DivPrimOp
3330 auto op =
Builder_->create<circt::firrtl::DivPrimOp>(
Builder_->getUnknownLoc(), first, second);
3331 body->push_back(op);
3335 circt::firrtl::DShrPrimOp
3338 auto op =
Builder_->create<circt::firrtl::DShrPrimOp>(
Builder_->getUnknownLoc(), first, second);
3339 body->push_back(op);
3343 circt::firrtl::DShlPrimOp
3346 auto op =
Builder_->create<circt::firrtl::DShlPrimOp>(
Builder_->getUnknownLoc(), first, second);
3347 body->push_back(op);
3351 circt::firrtl::RemPrimOp
3354 auto op =
Builder_->create<circt::firrtl::RemPrimOp>(
Builder_->getUnknownLoc(), first, second);
3355 body->push_back(op);
3359 circt::firrtl::EQPrimOp
3362 auto op =
Builder_->create<circt::firrtl::EQPrimOp>(
Builder_->getUnknownLoc(), first, second);
3363 body->push_back(op);
3367 circt::firrtl::NEQPrimOp
3370 auto op =
Builder_->create<circt::firrtl::NEQPrimOp>(
Builder_->getUnknownLoc(), first, second);
3371 body->push_back(op);
3375 circt::firrtl::GTPrimOp
3378 auto op =
Builder_->create<circt::firrtl::GTPrimOp>(
Builder_->getUnknownLoc(), first, second);
3379 body->push_back(op);
3383 circt::firrtl::GEQPrimOp
3386 auto op =
Builder_->create<circt::firrtl::GEQPrimOp>(
Builder_->getUnknownLoc(), first, second);
3387 body->push_back(op);
3391 circt::firrtl::LTPrimOp
3394 auto op =
Builder_->create<circt::firrtl::LTPrimOp>(
Builder_->getUnknownLoc(), first, second);
3395 body->push_back(op);
3399 circt::firrtl::LEQPrimOp
3402 auto op =
Builder_->create<circt::firrtl::LEQPrimOp>(
Builder_->getUnknownLoc(), first, second);
3403 body->push_back(op);
3407 circt::firrtl::MuxPrimOp
3415 Builder_->create<circt::firrtl::MuxPrimOp>(
Builder_->getUnknownLoc(), select, high, low);
3416 body->push_back(op);
3420 circt::firrtl::AsSIntPrimOp
3423 auto op =
Builder_->create<circt::firrtl::AsSIntPrimOp>(
Builder_->getUnknownLoc(), value);
3424 body->push_back(op);
3428 circt::firrtl::AsUIntPrimOp
3431 auto op =
Builder_->create<circt::firrtl::AsUIntPrimOp>(
Builder_->getUnknownLoc(), value);
3432 body->push_back(op);
3436 circt::firrtl::PadPrimOp
3439 auto op =
Builder_->create<circt::firrtl::PadPrimOp>(
Builder_->getUnknownLoc(), value, amount);
3440 body->push_back(op);
3444 circt::firrtl::CvtPrimOp
3447 auto op =
Builder_->create<circt::firrtl::CvtPrimOp>(
Builder_->getUnknownLoc(), value);
3448 body->push_back(op);
3452 circt::firrtl::WireOp
3457 body->push_back(op);
3461 circt::firrtl::WhenOp
3465 Builder_->create<circt::firrtl::WhenOp>(
Builder_->getUnknownLoc(), condition, elseStatement);
3466 body->push_back(op);
3473 ::llvm::SmallPtrSet<mlir::Value, 16> & forbiddenDependencies,
3474 ::llvm::SmallPtrSet<mlir::Value, 16> & visited)
3476 if (visited.contains(value))
3480 visited.insert(value);
3481 if (forbiddenDependencies.contains(value))
3483 throw util::Error(
"forbidden dependency detected");
3485 auto op = value.getDefiningOp();
3488 if (mlir::dyn_cast<circt::firrtl::RegResetOp>(op))
3492 else if (mlir::dyn_cast<circt::firrtl::RegOp>(op))
3497 for (
auto & use : value.getUses())
3499 auto * user = use.getOwner();
3500 if (
auto connectOp = mlir::dyn_cast<circt::firrtl::ConnectOp>(user))
3502 if (connectOp.getDest() == value)
3512 if (mlir::dyn_cast<circt::firrtl::SubfieldOp>(op))
3517 for (
size_t i = 0; i < op->getNumOperands(); ++i)
3525 ::llvm::SmallVector<mlir::Value> & oReadys,
3526 ::llvm::SmallVector<mlir::Value> & oValids)
3528 ::llvm::SmallPtrSet<mlir::Value, 16> forbiddenDependencies(oReadys.begin(), oReadys.end());
3529 for (
auto oValid : oValids)
3531 ::llvm::SmallPtrSet<mlir::Value, 16> visited;
3542 ::llvm::SmallVector<mlir::Value> oReadys;
3543 ::llvm::SmallVector<mlir::Value> oValids;
3544 ::llvm::SmallVector<mlir::Value> oDatas;
3545 for (
size_t i = 0; i < module.getNumPorts(); ++i)
3547 auto portName = module.getPortName(i);
3548 auto port = module.getArgument(i);
3549 if (portName.starts_with(
"o"))
3552 for (
auto & use : port.getUses())
3554 auto * user = use.getOwner();
3555 if (
auto subfieldOp = mlir::dyn_cast<circt::firrtl::SubfieldOp>(user))
3558 subfieldOp.getInput().getType().cast<circt::firrtl::BundleType>().getElementName(
3559 subfieldOp.getFieldIndex());
3560 if (subfieldName ==
"ready")
3562 oReadys.push_back(subfieldOp);
3564 else if (subfieldName ==
"valid")
3566 oValids.push_back(subfieldOp);
3568 else if (subfieldName ==
"data")
3570 oDatas.push_back(subfieldOp);
3575 user->print(::llvm::outs());
3576 llvm_unreachable(
"unexpected GetOperation");
3584 #ifdef FIRRTL_RUNTIME_ASSERTIONS
3586 auto body = &module.getBody().back();
3590 for (
size_t i = 0; i < module.getNumPorts(); ++i)
3592 auto portName = module.getPortName(i);
3593 auto port = module.getArgument(i);
3594 if (portName.starts_with(
"o") || portName.starts_with(
"i"))
3599 if (data.getResult().getType().dyn_cast<circt::firrtl::BundleType>())
3604 auto fire =
AddAndOp(body, ready, valid);
3605 auto prev_ready_reg =
Builder_->create<circt::firrtl::RegResetOp>(
3611 std::string(portName) +
"_prev_ready_reg");
3612 body->push_back(prev_ready_reg);
3613 auto prev_valid_reg =
Builder_->create<circt::firrtl::RegResetOp>(
3619 std::string(portName) +
"_prev_valid_reg");
3620 body->push_back(prev_valid_reg);
3621 auto prev_data_reg =
Builder_->create<circt::firrtl::RegOp>(
3623 data.getResult().getType(),
3625 std::string(portName) +
"_prev_data_reg");
3626 body->push_back(prev_data_reg);
3627 Connect(body, prev_ready_reg.getResult(), ready);
3628 Connect(body, prev_valid_reg.getResult(), valid);
3629 Connect(body, prev_data_reg.getResult(), data);
3630 auto fireBody = &
AddWhenOp(body, fire,
false).getThenBlock();
3631 Connect(fireBody, prev_ready_reg.getResult(), zeroBitValue);
3632 Connect(fireBody, prev_valid_reg.getResult(), zeroBitValue);
3634 auto valid_assert =
Builder_->create<circt::firrtl::AssertOp>(
3639 std::string(portName) +
"_valid went down without firing",
3641 std::string(portName) +
"_valid_assert");
3642 body->push_back(valid_assert);
3644 auto ready_assert =
Builder_->create<circt::firrtl::AssertOp>(
3649 std::string(portName) +
"_ready went down without firing",
3651 std::string(portName) +
"_ready_assert");
3652 body->push_back(ready_assert);
3654 auto data_assert =
Builder_->create<circt::firrtl::AssertOp>(
3661 prev_valid_reg.getResult(),
3662 AddNeqOp(body, prev_data_reg.getResult(), data))),
3664 std::string(portName) +
"_data changed without firing",
3666 std::string(portName) +
"_data_assert");
3667 body->push_back(data_assert);
3673 circt::firrtl::InstanceOp
3683 if (circt::isa<circt::firrtl::FModuleOp>(module))
3684 check_module(circt::cast<circt::firrtl::FModuleOp>(module));
3686 circuitBody->push_back(module);
3691 auto ln =
dynamic_cast<LoopNode *
>(node);
3693 auto module =
MlirGen(ln, circuitBody);
3695 circuitBody->push_back(module);
3701 return Builder_->create<circt::firrtl::InstanceOp>(
3707 circt::firrtl::ConstantOp
3711 auto constant =
Builder_->create<circt::firrtl::ConstantOp>(
3714 ::llvm::APInt(size, value));
3715 body->push_back(constant);
3719 circt::firrtl::InvalidValueOp
3725 body->push_back(invalid);
3734 Builder_->create<circt::firrtl::InvalidValueOp>(
Builder_->getUnknownLoc(), value.getType());
3735 body->push_back(invalid);
3736 return Connect(body, value, invalid);
3743 auto clock = module.getArgument(0);
3744 auto ctype = clock.getType().cast<circt::firrtl::FIRRTLType>();
3745 if (!ctype.isa<circt::firrtl::ClockType>())
3756 auto reset = module.getArgument(1);
3757 auto rtype = reset.getType().cast<circt::firrtl::FIRRTLType>();
3758 if (!rtype.isa<circt::firrtl::ResetType>())
3765 circt::firrtl::BundleType::BundleElement
3768 using BundleElement = circt::firrtl::BundleType::BundleElement;
3770 return BundleElement(
3773 circt::firrtl::IntType::get(
Builder_->getContext(),
false, 1));
3776 circt::firrtl::BundleType::BundleElement
3779 using BundleElement = circt::firrtl::BundleType::BundleElement;
3781 return BundleElement(
3784 circt::firrtl::IntType::get(
Builder_->getContext(),
false, 1));
3790 mlir::BlockArgument mem =
GetPort(module,
"mem_req");
3791 mlir::Block * body = module.getBodyBlock();
3805 Connect(body, memValid, zeroBitValue);
3806 Connect(body, memAddr, invalidPtr);
3807 Connect(body, memData, invalid64);
3808 Connect(body, memWrite, invalid1);
3809 Connect(body, memWidth, invalid3);
3815 circt::firrtl::FModuleOp
3819 ::llvm::SmallVector<circt::firrtl::PortInfo> ports;
3825 for (
size_t i = 0; i < node->
ninputs(); ++i)
3827 std::string name(
"i");
3828 name.append(std::to_string(i));
3831 circt::firrtl::Direction::In,
3835 for (
size_t i = 0; i < node->
noutputs(); ++i)
3837 std::string name(
"o");
3838 name.append(std::to_string(i));
3841 circt::firrtl::Direction::Out,
3854 mlir::StringAttr name =
Builder_->getStringAttr(nodeName);
3856 return Builder_->create<circt::firrtl::FModuleOp>(
3859 circt::firrtl::ConventionAttr::get(
3861 circt::firrtl::Convention::Internal),
3870 circt::firrtl::IntType
3873 return circt::firrtl::IntType::get(
Builder_->getContext(),
false, size);
3880 circt::firrtl::IntType
3883 return circt::firrtl::IntType::get(
Builder_->getContext(),
false,
JlmSize(
type) + extend);
3886 circt::firrtl::FIRRTLBaseType
3891 using BundleElement = circt::firrtl::BundleType::BundleElement;
3892 ::llvm::SmallVector<BundleElement> elements;
3893 for (
size_t i = 0; i < bt->elements_.size(); ++i)
3895 auto t = &bt->elements_.at(i);
3899 return circt::firrtl::BundleType::get(
Builder_->getContext(), elements);
3911 std::string append =
"";
3912 for (
size_t i = 0; i < node->
ninputs(); ++i)
3914 append.append(
"_I");
3918 for (
size_t i = 0; i < node->
noutputs(); ++i)
3920 append.append(
"_O");
3927 for (
size_t i = 1; i < node->
ninputs(); i++)
3929 int bits =
JlmSize(pointeeType);
3933 pointeeType =
nullptr;
3935 else if (
auto arrayType =
dynamic_cast<const llvm::ArrayType *
>(pointeeType))
3937 pointeeType = &arrayType->element_type();
3939 else if (
auto vectorType =
dynamic_cast<const llvm::VectorType *
>(pointeeType))
3941 pointeeType = vectorType->
Type().get();
3945 throw std::logic_error(pointeeType->
debug_string() +
" pointer not implemented!");
3947 int bytes = bits / 8;
3949 append.append(std::to_string(bytes));
3954 auto loadTypes = op->GetLoadTypes();
3955 for (
size_t i = 0; i < loadTypes->size(); i++)
3957 auto loadType = loadTypes->at(i).get();
3958 int bitWidth =
JlmSize(loadType);
3960 append.append(std::to_string(bitWidth));
3965 append.append(
"_S");
3966 append.append(std::to_string(
3967 std::dynamic_pointer_cast<const llvm::ArrayType>(op->result(0))->nelements()));
3968 append.append(
"_L");
3970 rvsdg::TryGetOwnerNode<rvsdg::Node>(*node->
output(0)->
Users().
begin())->noutputs();
3971 append.append(std::to_string(loads));
3972 append.append(
"_S");
3974 (rvsdg::TryGetOwnerNode<rvsdg::Node>(*node->
output(1)->
Users().
begin())->ninputs() - 1
3977 append.append(std::to_string(stores));
3993 for (
const auto & pair : op)
3995 if (pair.first != pair.second)
4006 const circt::firrtl::FModuleOp fModuleOp,
4013 auto moduleName =
Builder_->getStringAttr(name);
4016 auto circuit =
Builder_->create<circt::firrtl::CircuitOp>(
Builder_->getUnknownLoc(), moduleName);
4017 auto body = circuit.getBodyBlock();
4018 body->push_back(fModuleOp);
4028 auto module = mlir::ModuleOp::create(
Builder_->getUnknownLoc());
4029 module.push_back(circuit);
4032 if (failed(mlir::verify(module)))
4034 module.emitError(
"module verification error");
4035 throw std::logic_error(
"Verification of firrtl failed");
4038 module.print(::llvm::outs());
4041 std::string fileName = name +
extension();
4043 ::llvm::raw_fd_ostream output(fileName, EC);
4044 size_t targetLineLength = 100;
4045 auto status = circt::firrtl::exportFIRFile(module, output, targetLineLength,
DefaultFIRVersion_);
4047 if (status.failed())
4053 std::cout <<
"\nWritten firrtl to " << fileName <<
"\n";
4060 auto module = mlir::ModuleOp::create(
Builder_->getUnknownLoc());
4061 module.push_back(circuit);
4064 if (failed(mlir::verify(module)))
4066 module.emitError(
"module verification error");
4067 module.print(::llvm::outs());
4068 throw std::logic_error(
"Verification of firrtl failed");
4072 std::string outputString;
4073 ::llvm::raw_string_ostream output(outputString);
4075 size_t targetLineLength = 100;
4076 auto status = circt::firrtl::exportFIRFile(module, output, targetLineLength,
DefaultFIRVersion_);
4077 if (status.failed())
4078 throw std::logic_error(
"Exporting of firrtl failed");
4080 return outputString;
4083 circt::firrtl::FExtModuleOp
4087 ::llvm::SmallVector<circt::firrtl::PortInfo> ports;
4093 for (
size_t i = 0; i < node->
ninputs(); ++i)
4095 std::string name(
"i");
4096 name.append(std::to_string(i));
4099 circt::firrtl::Direction::In,
4103 for (
size_t i = 0; i < node->
noutputs(); ++i)
4105 std::string name(
"o");
4106 name.append(std::to_string(i));
4109 circt::firrtl::Direction::Out,
4116 mlir::StringAttr name =
Builder_->getStringAttr(nodeName);
4118 return Builder_->create<circt::firrtl::FExtModuleOp>(
4121 circt::firrtl::ConventionAttr::get(
4123 circt::firrtl::Convention::Internal),
std::vector< rvsdg::RegionArgument * > get_reg_args(const rvsdg::LambdaNode &lambda)
std::vector< rvsdg::RegionResult * > get_reg_results(const rvsdg::LambdaNode &lambda)
std::vector< rvsdg::RegionResult * > get_mem_reqs(const rvsdg::LambdaNode &lambda)
static std::string get_port_name(jlm::rvsdg::Input *port)
void create_node_names(rvsdg::Region *r)
static int JlmSize(const jlm::rvsdg::Type *type)
std::unordered_map< jlm::rvsdg::Output *, std::string > output_map
std::string get_node_name(const rvsdg::Node *node)
std::vector< rvsdg::RegionArgument * > get_mem_resps(const rvsdg::LambdaNode &lambda)
std::size_t Capacity() const noexcept
bool IsConstant() const noexcept
rvsdg::Region * subregion() const noexcept
const std::vector< std::shared_ptr< const rvsdg::Type > > * GetLoadTypes() const
circt::firrtl::InstanceOp AddInstanceOp(mlir::Block *circuitBody, jlm::rvsdg::Node *node)
circt::firrtl::GEQPrimOp AddGeqOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenBuffer(const jlm::rvsdg::SimpleNode *node)
mlir::BlockArgument GetPort(circt::firrtl::FModuleOp &module, std::string portName)
circt::firrtl::FModuleOp MlirGenHlsMemReq(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::EQPrimOp AddEqOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::LTPrimOp AddLtOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::BitsPrimOp AddBitsOp(mlir::Block *body, mlir::Value value, int high, int low)
void check_module(circt::firrtl::FModuleOp &module)
circt::firrtl::XorPrimOp AddXorOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenNDMux(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::BundleType GetBundleType(const circt::firrtl::FIRRTLBaseType &type)
circt::firrtl::BitsPrimOp DropMSBs(mlir::Block *body, mlir::Value value, int amount)
circt::firrtl::WireOp AddWireOp(mlir::Block *body, std::string name, int size)
void AddMemResPort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports)
circt::firrtl::RemPrimOp AddRemOp(mlir::Block *body, mlir::Value first, mlir::Value second)
std::unordered_map< std::string, circt::firrtl::FModuleLike > modules
circt::firrtl::FModuleOp MlirGenFork(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::FModuleOp nodeToModule(const jlm::rvsdg::Node *node, bool mem=false)
void WriteModuleToFile(const circt::firrtl::FModuleOp fModuleOp, const rvsdg::Node *node)
rvsdg::Output * TraceStructuralOutput(rvsdg::StructuralOutput *out)
circt::firrtl::NodeOp AddNodeOp(mlir::Block *body, mlir::Value value, std::string name)
circt::firrtl::FModuleOp MlirGenTrigger(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::DShrPrimOp AddDShrOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::NEQPrimOp AddNeqOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenPrint(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::FModuleOp MlirGenHlsMemResp(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::BundleType::BundleElement GetReadyElement()
circt::firrtl::BundleType::BundleElement GetValidElement()
void AddResetPort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports)
circt::firrtl::FModuleOp MlirGenStateGate(const jlm::rvsdg::SimpleNode *node)
const circt::firrtl::FIRVersion DefaultFIRVersion_
void InitializeMemReq(circt::firrtl::FModuleOp module)
circt::firrtl::FModuleOp MlirGenSink(const jlm::rvsdg::SimpleNode *node)
void Connect(mlir::Block *body, mlir::Value sink, mlir::Value source)
circt::firrtl::FModuleOp MlirGenHlsStore(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::FIRRTLBaseType GetFirrtlType(const jlm::rvsdg::Type *type)
void AddMemReqPort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports)
circt::firrtl::DShlPrimOp AddDShlOp(mlir::Block *body, mlir::Value first, mlir::Value second)
void WriteCircuitToFile(const circt::firrtl::CircuitOp circuit, std::string name)
bool IsIdentityMapping(const rvsdg::MatchOperation &op)
circt::firrtl::CircuitOp MlirGen(const rvsdg::LambdaNode *lamdaNode)
circt::firrtl::FModuleOp MlirGenSimpleNode(const jlm::rvsdg::SimpleNode *node)
mlir::BlockArgument GetResetSignal(circt::firrtl::FModuleOp module)
std::string toString(const circt::firrtl::CircuitOp circuit)
circt::firrtl::ConstantOp GetConstant(mlir::Block *body, int size, int value)
circt::firrtl::InvalidValueOp GetInvalid(mlir::Block *body, int size)
mlir::BlockArgument GetOutPort(circt::firrtl::FModuleOp &module, size_t portNr)
circt::firrtl::FModuleOp MlirGenBranch(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::SubPrimOp AddSubOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::PadPrimOp AddPadOp(mlir::Block *body, mlir::Value value, int amount)
circt::firrtl::MuxPrimOp AddMuxOp(mlir::Block *body, mlir::Value select, mlir::Value high, mlir::Value low)
circt::firrtl::WhenOp AddWhenOp(mlir::Block *body, mlir::Value condition, bool elseStatment)
circt::firrtl::AsUIntPrimOp AddAsUIntOp(mlir::Block *body, mlir::Value value)
circt::firrtl::FModuleOp MlirGenPredicationBuffer(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::NotPrimOp AddNotOp(mlir::Block *body, mlir::Value first)
circt::firrtl::FModuleOp MlirGenAddrQueue(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::GTPrimOp AddGtOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FExtModuleOp MlirGenExtModule(const jlm::rvsdg::SimpleNode *node)
void AddClockPort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports)
std::string extension() override
circt::firrtl::FModuleOp MlirGenHlsDLoad(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::FModuleOp MlirGenLoopConstBuffer(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::OrPrimOp AddOrOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::IntType GetIntType(int size)
circt::firrtl::MulPrimOp AddMulOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::LEQPrimOp AddLeqOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenHlsLocalMem(const jlm::rvsdg::SimpleNode *node)
std::string GetModuleName(const rvsdg::Node *node)
jlm::rvsdg::Output * TraceArgument(rvsdg::RegionArgument *arg)
std::unique_ptr<::mlir::OpBuilder > Builder_
circt::firrtl::AsSIntPrimOp AddAsSIntOp(mlir::Block *body, mlir::Value value)
circt::firrtl::FModuleOp MlirGenDMux(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::DivPrimOp AddDivOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenHlsLoad(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::AddPrimOp AddAddOp(mlir::Block *body, mlir::Value first, mlir::Value second)
mlir::BlockArgument GetInPort(circt::firrtl::FModuleOp &module, size_t portNr)
circt::firrtl::CvtPrimOp AddCvtOp(mlir::Block *body, mlir::Value value)
circt::firrtl::SubfieldOp GetSubfield(mlir::Block *body, mlir::Value value, int index)
mlir::OpResult GetInstancePort(circt::firrtl::InstanceOp &instance, std::string portName)
mlir::BlockArgument GetClockSignal(circt::firrtl::FModuleOp module)
circt::firrtl::AndPrimOp AddAndOp(mlir::Block *body, mlir::Value first, mlir::Value second)
void ConnectInvalid(mlir::Block *body, mlir::Value value)
circt::firrtl::FModuleOp MlirGenMem(const jlm::rvsdg::SimpleNode *node)
void AddBundlePort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports, circt::firrtl::Direction direction, std::string name, circt::firrtl::FIRRTLBaseType type)
const std::string & name() const noexcept
UndefValueOperation class.
rvsdg::Region * subregion() const noexcept
LambdaOperation & GetOperation() const noexcept override
virtual const Operation & GetOperation() const noexcept=0
virtual std::string DebugString() const =0
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
size_t ninputs() const noexcept
size_t noutputs() const noexcept
rvsdg::Region * region() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
size_t index() const noexcept
Represents the argument of a region.
StructuralInput * input() const noexcept
StructuralOutput * output() const noexcept
Represent acyclic RVSDG subgraphs.
RegionResult * result(size_t index) const noexcept
rvsdg::StructuralNode * node() const noexcept
size_t nresults() const noexcept
RegionArgument * argument(size_t index) const noexcept
size_t narguments() const noexcept
const SimpleOperation & GetOperation() const noexcept override
std::string DebugString() const override
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
StructuralNode * node() const noexcept
constexpr Type() noexcept
virtual std::string debug_string() const =0
size_type size() const noexcept
Iterator begin() noexcept
void check_may_not_depend_on(mlir::Value value, ::llvm::SmallPtrSet< mlir::Value, 16 > &forbiddenDependencies, ::llvm::SmallPtrSet< mlir::Value, 16 > &visited)
void check_oValids(::llvm::SmallVector< mlir::Value > &oReadys, ::llvm::SmallVector< mlir::Value > &oValids)
bool isForbiddenChar(char c)
size_t GetPointerSizeInBits()
static std::string type(const Node *n)
@ State
Designate a state type.
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
size_t ninputs(const rvsdg::Region *region) noexcept
static std::string strfmt(Args... args)