19#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
20#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
21#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
22#include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h"
23#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
24#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
25#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
26#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
27#include "mlir/Dialect/Func/IR/FuncOps.h"
28#include "mlir/Dialect/Index/IR/IndexOps.h"
29#include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
30#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
31#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
32#include "mlir/Dialect/SCF/IR/SCF.h"
33#include "mlir/IR/BuiltinDialect.h"
34#include "mlir/Pass/Pass.h"
35#include "mlir/Transforms/DialectConversion.h"
36#include "llvm/Support/Debug.h"
37#include "llvm/Support/FormatVariadic.h"
39#define DEBUG_TYPE "lower-arc-to-llvm"
42#define GEN_PASS_DEF_LOWERARCTOLLVM
43#include "circt/Conversion/Passes.h.inc"
56 return modelName +
"_eval";
62 using OpConversionPattern::OpConversionPattern;
64 matchAndRewrite(arc::ModelOp op, OpAdaptor adaptor,
65 ConversionPatternRewriter &rewriter)
const final {
67 IRRewriter::InsertionGuard guard(rewriter);
68 rewriter.setInsertionPointToEnd(&op.getBodyBlock());
69 func::ReturnOp::create(rewriter, op.getLoc());
74 rewriter.getFunctionType(op.getBody().getArgumentTypes(), {});
76 mlir::func::FuncOp::create(rewriter, op.getLoc(), funcName, funcType);
77 rewriter.inlineRegionBefore(op.getRegion(), func.getBody(), func.end());
83struct AllocStorageOpLowering
85 using OpConversionPattern::OpConversionPattern;
87 matchAndRewrite(arc::AllocStorageOp op, OpAdaptor adaptor,
88 ConversionPatternRewriter &rewriter)
const final {
89 auto type = typeConverter->convertType(op.getType());
90 if (!op.getOffset().has_value())
92 rewriter.replaceOpWithNewOp<LLVM::GEPOp>(op, type, rewriter.getI8Type(),
94 LLVM::GEPArg(*op.getOffset()));
99template <
class ConcreteOp>
103 using OpAdaptor =
typename ConcreteOp::Adaptor;
106 matchAndRewrite(ConcreteOp op, OpAdaptor adaptor,
107 ConversionPatternRewriter &rewriter)
const final {
109 auto offsetAttr = op->template getAttrOfType<IntegerAttr>(
"offset");
112 Value ptr = LLVM::GEPOp::create(
113 rewriter, op->getLoc(), adaptor.getStorage().getType(),
114 rewriter.getI8Type(), adaptor.getStorage(),
115 LLVM::GEPArg(offsetAttr.getValue().getZExtValue()));
116 rewriter.replaceOp(op, ptr);
122 using OpConversionPattern::OpConversionPattern;
124 matchAndRewrite(arc::StateReadOp op, OpAdaptor adaptor,
125 ConversionPatternRewriter &rewriter)
const final {
126 auto type = typeConverter->convertType(op.getType());
127 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(op, type, adaptor.getState());
133 using OpConversionPattern::OpConversionPattern;
135 matchAndRewrite(arc::StateWriteOp op, OpAdaptor adaptor,
136 ConversionPatternRewriter &rewriter)
const final {
137 if (adaptor.getCondition()) {
138 rewriter.replaceOpWithNewOp<scf::IfOp>(
139 op, adaptor.getCondition(), [&](
auto &builder,
auto loc) {
140 LLVM::StoreOp::create(builder, loc, adaptor.getValue(),
142 scf::YieldOp::create(builder, loc);
145 rewriter.replaceOpWithNewOp<LLVM::StoreOp>(op, adaptor.getValue(),
153 using OpConversionPattern::OpConversionPattern;
155 matchAndRewrite(arc::AllocMemoryOp op, OpAdaptor adaptor,
156 ConversionPatternRewriter &rewriter)
const final {
157 auto offsetAttr = op->getAttrOfType<IntegerAttr>(
"offset");
160 Value ptr = LLVM::GEPOp::create(
161 rewriter, op.getLoc(), adaptor.getStorage().getType(),
162 rewriter.getI8Type(), adaptor.getStorage(),
163 LLVM::GEPArg(offsetAttr.getValue().getZExtValue()));
165 rewriter.replaceOp(op, ptr);
171 using OpConversionPattern::OpConversionPattern;
173 matchAndRewrite(arc::StorageGetOp op, OpAdaptor adaptor,
174 ConversionPatternRewriter &rewriter)
const final {
175 Value offset = LLVM::ConstantOp::create(
176 rewriter, op.getLoc(), rewriter.getI32Type(), op.getOffsetAttr());
177 Value ptr = LLVM::GEPOp::create(
178 rewriter, op.getLoc(), adaptor.getStorage().getType(),
179 rewriter.getI8Type(), adaptor.getStorage(), offset);
180 rewriter.replaceOp(op, ptr);
190static MemoryAccess prepareMemoryAccess(Location loc, Value memory,
191 Value address, MemoryType type,
192 ConversionPatternRewriter &rewriter) {
193 auto zextAddrType = rewriter.getIntegerType(
194 cast<IntegerType>(address.getType()).getWidth() + 1);
195 Value
addr = LLVM::ZExtOp::create(rewriter, loc, zextAddrType, address);
197 LLVM::ConstantOp::create(rewriter, loc, zextAddrType,
198 rewriter.getI32IntegerAttr(type.getNumWords()));
199 Value withinBounds = LLVM::ICmpOp::create(
200 rewriter, loc, LLVM::ICmpPredicate::ult, addr, addrLimit);
201 Value ptr = LLVM::GEPOp::create(
202 rewriter, loc, LLVM::LLVMPointerType::get(memory.getContext()),
203 rewriter.getIntegerType(type.getStride() * 8), memory, ValueRange{addr});
204 return {ptr, withinBounds};
208 using OpConversionPattern::OpConversionPattern;
210 matchAndRewrite(arc::MemoryReadOp op, OpAdaptor adaptor,
211 ConversionPatternRewriter &rewriter)
const final {
212 auto type = typeConverter->convertType(op.getType());
213 auto memoryType = cast<MemoryType>(op.getMemory().getType());
215 prepareMemoryAccess(op.getLoc(), adaptor.getMemory(),
216 adaptor.getAddress(), memoryType, rewriter);
220 rewriter.replaceOpWithNewOp<scf::IfOp>(
221 op, access.withinBounds,
222 [&](
auto &builder,
auto loc) {
223 Value loadOp = LLVM::LoadOp::create(
224 builder, loc, memoryType.getWordType(), access.ptr);
225 scf::YieldOp::create(builder, loc, loadOp);
227 [&](
auto &builder,
auto loc) {
228 Value zeroValue = LLVM::ConstantOp::create(
229 builder, loc, type, builder.getI64IntegerAttr(0));
230 scf::YieldOp::create(builder, loc, zeroValue);
237 using OpConversionPattern::OpConversionPattern;
239 matchAndRewrite(arc::MemoryWriteOp op, OpAdaptor adaptor,
240 ConversionPatternRewriter &rewriter)
const final {
241 auto access = prepareMemoryAccess(
242 op.getLoc(), adaptor.getMemory(), adaptor.getAddress(),
243 cast<MemoryType>(op.getMemory().getType()), rewriter);
244 auto enable = access.withinBounds;
245 if (adaptor.getEnable())
246 enable = LLVM::AndOp::create(rewriter, op.getLoc(), adaptor.getEnable(),
250 rewriter.replaceOpWithNewOp<scf::IfOp>(
251 op, enable, [&](
auto &builder,
auto loc) {
252 LLVM::StoreOp::create(builder, loc, adaptor.getData(), access.ptr);
253 scf::YieldOp::create(builder, loc);
261 using OpConversionPattern::OpConversionPattern;
263 matchAndRewrite(seq::ClockGateOp op, OpAdaptor adaptor,
264 ConversionPatternRewriter &rewriter)
const final {
265 rewriter.replaceOpWithNewOp<LLVM::AndOp>(op, adaptor.getInput(),
266 adaptor.getEnable());
273 using OpConversionPattern::OpConversionPattern;
275 matchAndRewrite(seq::ClockInverterOp op, OpAdaptor adaptor,
276 ConversionPatternRewriter &rewriter)
const final {
277 auto constTrue = LLVM::ConstantOp::create(rewriter, op->getLoc(),
278 rewriter.getI1Type(), 1);
279 rewriter.replaceOpWithNewOp<LLVM::XOrOp>(op, adaptor.getInput(), constTrue);
285 using OpConversionPattern::OpConversionPattern;
287 matchAndRewrite(arc::ZeroCountOp op, OpAdaptor adaptor,
288 ConversionPatternRewriter &rewriter)
const override {
290 IntegerAttr isZeroPoison = rewriter.getBoolAttr(
true);
292 if (op.getPredicate() == arc::ZeroCountPredicate::leading) {
293 rewriter.replaceOpWithNewOp<LLVM::CountLeadingZerosOp>(
294 op, adaptor.getInput().getType(), adaptor.getInput(), isZeroPoison);
298 rewriter.replaceOpWithNewOp<LLVM::CountTrailingZerosOp>(
299 op, adaptor.getInput().getType(), adaptor.getInput(), isZeroPoison);
305 using OpConversionPattern::OpConversionPattern;
307 matchAndRewrite(seq::ConstClockOp op, OpAdaptor adaptor,
308 ConversionPatternRewriter &rewriter)
const override {
309 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(
310 op, rewriter.getI1Type(),
static_cast<int64_t
>(op.getValue()));
315template <
typename OpTy>
318 using OpAdaptor =
typename OpTy::Adaptor;
320 matchAndRewrite(OpTy op, OpAdaptor adaptor,
321 ConversionPatternRewriter &rewriter)
const override {
322 rewriter.replaceOp(op, adaptor.getInput());
336 size_t numStateBytes;
337 llvm::DenseMap<StringRef, StateInfo> states;
338 mlir::FlatSymbolRefAttr initialFnSymbol;
339 mlir::FlatSymbolRefAttr finalFnSymbol;
342template <
typename OpTy>
344 ModelAwarePattern(
const TypeConverter &typeConverter, MLIRContext *context,
345 llvm::DenseMap<StringRef, ModelInfoMap> &modelInfo)
347 modelInfo(modelInfo) {}
350 Value createPtrToPortState(ConversionPatternRewriter &rewriter, Location loc,
351 Value state,
const StateInfo &port)
const {
352 MLIRContext *ctx = rewriter.getContext();
353 return LLVM::GEPOp::create(rewriter, loc, LLVM::LLVMPointerType::get(ctx),
354 IntegerType::get(ctx, 8), state,
355 LLVM::GEPArg(port.offset));
358 llvm::DenseMap<StringRef, ModelInfoMap> &modelInfo;
363struct SimInstantiateOpLowering
364 :
public ModelAwarePattern<arc::SimInstantiateOp> {
365 using ModelAwarePattern::ModelAwarePattern;
368 matchAndRewrite(arc::SimInstantiateOp op, OpAdaptor adaptor,
369 ConversionPatternRewriter &rewriter)
const final {
370 auto modelIt = modelInfo.find(
371 cast<SimModelInstanceType>(op.getBody().getArgument(0).getType())
374 ModelInfoMap &model = modelIt->second;
376 ModuleOp moduleOp = op->getParentOfType<ModuleOp>();
380 ConversionPatternRewriter::InsertionGuard guard(rewriter);
384 Type convertedIndex = typeConverter->convertType(rewriter.getIndexType());
386 FailureOr<LLVM::LLVMFuncOp> mallocFunc =
387 LLVM::lookupOrCreateMallocFn(rewriter, moduleOp, convertedIndex);
388 if (failed(mallocFunc))
391 FailureOr<LLVM::LLVMFuncOp> freeFunc =
392 LLVM::lookupOrCreateFreeFn(rewriter, moduleOp);
393 if (failed(freeFunc))
396 Location loc = op.getLoc();
397 Value numStateBytes = LLVM::ConstantOp::create(
398 rewriter, loc, convertedIndex, model.numStateBytes);
399 Value allocated = LLVM::CallOp::create(rewriter, loc, mallocFunc.value(),
400 ValueRange{numStateBytes})
403 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI8Type(), 0);
404 LLVM::MemsetOp::create(rewriter, loc, allocated, zero, numStateBytes,
408 if (model.initialFnSymbol) {
409 auto initialFnType = LLVM::LLVMFunctionType::get(
410 LLVM::LLVMVoidType::get(op.getContext()),
411 {LLVM::LLVMPointerType::get(op.getContext())});
412 LLVM::CallOp::create(rewriter, loc, initialFnType, model.initialFnSymbol,
413 ValueRange{allocated});
417 rewriter.inlineBlockBefore(&adaptor.getBody().getBlocks().front(), op,
421 if (model.finalFnSymbol) {
422 auto finalFnType = LLVM::LLVMFunctionType::get(
423 LLVM::LLVMVoidType::get(op.getContext()),
424 {LLVM::LLVMPointerType::get(op.getContext())});
425 LLVM::CallOp::create(rewriter, loc, finalFnType, model.finalFnSymbol,
426 ValueRange{allocated});
429 LLVM::CallOp::create(rewriter, loc, freeFunc.value(),
430 ValueRange{allocated});
431 rewriter.eraseOp(op);
437struct SimSetInputOpLowering :
public ModelAwarePattern<arc::SimSetInputOp> {
438 using ModelAwarePattern::ModelAwarePattern;
441 matchAndRewrite(arc::SimSetInputOp op, OpAdaptor adaptor,
442 ConversionPatternRewriter &rewriter)
const final {
444 modelInfo.find(cast<SimModelInstanceType>(op.getInstance().getType())
447 ModelInfoMap &model = modelIt->second;
449 auto portIt = model.states.find(op.getInput());
450 if (portIt == model.states.end()) {
453 rewriter.eraseOp(op);
457 StateInfo &port = portIt->second;
458 Value statePtr = createPtrToPortState(rewriter, op.getLoc(),
459 adaptor.getInstance(), port);
460 rewriter.replaceOpWithNewOp<LLVM::StoreOp>(op, adaptor.getValue(),
467struct SimGetPortOpLowering :
public ModelAwarePattern<arc::SimGetPortOp> {
468 using ModelAwarePattern::ModelAwarePattern;
471 matchAndRewrite(arc::SimGetPortOp op, OpAdaptor adaptor,
472 ConversionPatternRewriter &rewriter)
const final {
474 modelInfo.find(cast<SimModelInstanceType>(op.getInstance().getType())
477 ModelInfoMap &model = modelIt->second;
479 auto type = typeConverter->convertType(op.getValue().getType());
482 auto portIt = model.states.find(op.getPort());
483 if (portIt == model.states.end()) {
486 rewriter.replaceOpWithNewOp<LLVM::ConstantOp>(op, type, 0);
490 StateInfo &port = portIt->second;
491 Value statePtr = createPtrToPortState(rewriter, op.getLoc(),
492 adaptor.getInstance(), port);
493 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(op, type, statePtr);
499struct SimStepOpLowering :
public ModelAwarePattern<arc::SimStepOp> {
500 using ModelAwarePattern::ModelAwarePattern;
503 matchAndRewrite(arc::SimStepOp op, OpAdaptor adaptor,
504 ConversionPatternRewriter &rewriter)
const final {
505 StringRef modelName = cast<SimModelInstanceType>(op.getInstance().getType())
509 StringAttr evalFunc =
511 rewriter.replaceOpWithNewOp<LLVM::CallOp>(op, mlir::TypeRange(), evalFunc,
512 adaptor.getInstance());
521struct SimEmitValueOpLowering
523 using OpConversionPattern::OpConversionPattern;
526 matchAndRewrite(arc::SimEmitValueOp op, OpAdaptor adaptor,
527 ConversionPatternRewriter &rewriter)
const final {
528 auto valueType = dyn_cast<IntegerType>(adaptor.getValue().getType());
532 Location loc = op.getLoc();
534 ModuleOp moduleOp = op->getParentOfType<ModuleOp>();
538 SmallVector<Value> printfVariadicArgs;
539 SmallString<16> printfFormatStr;
540 int remainingBits = valueType.getWidth();
541 Value value = adaptor.getValue();
545 constexpr llvm::StringRef intFormatter =
"llx";
546 auto intType = IntegerType::get(getContext(), 64);
547 Value shiftValue = LLVM::ConstantOp::create(
548 rewriter, loc, rewriter.getIntegerAttr(valueType, intType.getWidth()));
550 if (valueType.getWidth() < intType.getWidth()) {
551 int width = llvm::divideCeil(valueType.getWidth(), 4);
552 printfFormatStr = llvm::formatv(
"%0{0}{1}", width, intFormatter);
553 printfVariadicArgs.push_back(
554 LLVM::ZExtOp::create(rewriter, loc, intType, value));
559 int otherChunkWidth = intType.getWidth() / 4;
560 int firstChunkWidth =
561 llvm::divideCeil(valueType.getWidth() % intType.getWidth(), 4);
562 if (firstChunkWidth == 0) {
563 firstChunkWidth = otherChunkWidth;
566 std::string firstChunkFormat =
567 llvm::formatv(
"%0{0}{1}", firstChunkWidth, intFormatter);
568 std::string otherChunkFormat =
569 llvm::formatv(
"%0{0}{1}", otherChunkWidth, intFormatter);
571 for (
int i = 0; remainingBits > 0; ++i) {
574 printfVariadicArgs.push_back(
575 LLVM::TruncOp::create(rewriter, loc, intType, value));
578 printfFormatStr.append(i == 0 ? firstChunkFormat : otherChunkFormat);
581 LLVM::LShrOp::create(rewriter, loc, value, shiftValue).getResult();
582 remainingBits -= intType.getWidth();
587 auto printfFunc = LLVM::lookupOrCreateFn(
588 rewriter, moduleOp,
"printf", LLVM::LLVMPointerType::get(getContext()),
589 LLVM::LLVMVoidType::get(getContext()),
true);
590 if (failed(printfFunc))
594 SmallString<16> formatStrName{
"_arc_sim_emit_"};
595 formatStrName.append(adaptor.getValueName());
596 LLVM::GlobalOp formatStrGlobal;
597 if (!(formatStrGlobal =
598 moduleOp.lookupSymbol<LLVM::GlobalOp>(formatStrName))) {
599 ConversionPatternRewriter::InsertionGuard insertGuard(rewriter);
601 SmallString<16> formatStr = adaptor.getValueName();
602 formatStr.append(
" = ");
603 formatStr.append(printfFormatStr);
604 formatStr.append(
"\n");
605 SmallVector<char> formatStrVec{formatStr.begin(), formatStr.end()};
606 formatStrVec.push_back(0);
608 rewriter.setInsertionPointToStart(moduleOp.getBody());
610 LLVM::LLVMArrayType::get(rewriter.getI8Type(), formatStrVec.size());
611 formatStrGlobal = LLVM::GlobalOp::create(
612 rewriter, loc, globalType,
true,
613 LLVM::Linkage::Internal,
614 formatStrName, rewriter.getStringAttr(formatStrVec),
618 Value formatStrGlobalPtr =
619 LLVM::AddressOfOp::create(rewriter, loc, formatStrGlobal);
623 printfVariadicArgs.push_back(formatStrGlobalPtr);
624 std::reverse(printfVariadicArgs.begin(), printfVariadicArgs.end());
626 rewriter.replaceOpWithNewOp<LLVM::CallOp>(op, printfFunc.value(),
635static LogicalResult
convert(arc::ExecuteOp op, arc::ExecuteOp::Adaptor adaptor,
636 ConversionPatternRewriter &rewriter,
637 const TypeConverter &converter) {
639 if (failed(rewriter.convertRegionTypes(&op.getBody(), converter)))
645 auto *blockBefore = rewriter.getInsertionBlock();
647 rewriter.splitBlock(blockBefore, rewriter.getInsertionPoint());
650 rewriter.setInsertionPointToEnd(blockBefore);
651 mlir::cf::BranchOp::create(rewriter, op.getLoc(), &op.getBody().front(),
652 adaptor.getInputs());
656 for (
auto &block : op.getBody()) {
657 auto outputOp = dyn_cast<arc::OutputOp>(block.getTerminator());
660 rewriter.setInsertionPointToEnd(&block);
661 rewriter.replaceOpWithNewOp<mlir::cf::BranchOp>(outputOp, blockAfter,
662 outputOp.getOperands());
666 rewriter.inlineRegionBefore(op.getBody(), blockAfter);
670 SmallVector<Value> args;
671 args.reserve(op.getNumResults());
672 for (
auto result : op.getResults())
673 args.push_back(blockAfter->addArgument(result.getType(), result.getLoc()));
674 rewriter.replaceOp(op, args);
675 auto conversion = converter.convertBlockSignature(blockAfter);
678 rewriter.applySignatureConversion(blockAfter, *conversion, &converter);
687struct LowerArcToLLVMPass
688 :
public circt::impl::LowerArcToLLVMBase<LowerArcToLLVMPass> {
689 void runOnOperation()
override;
693void LowerArcToLLVMPass::runOnOperation() {
697 DenseMap<Region *, hw::ConstantOp> zeros;
698 getOperation().walk([&](Operation *op) {
699 if (op->hasTrait<OpTrait::ConstantLike>())
701 for (
auto result : op->getResults()) {
702 auto type = dyn_cast<IntegerType>(result.getType());
703 if (!type || type.getWidth() != 0)
705 auto *region = op->getParentRegion();
706 auto &zero = zeros[region];
708 auto builder = OpBuilder::atBlockBegin(®ion->front());
712 result.replaceAllUsesWith(zero);
728 LLVMConversionTarget target(getContext());
729 target.addLegalOp<mlir::ModuleOp>();
730 target.addLegalOp<scf::YieldOp>();
733 LLVMTypeConverter converter(&getContext());
734 converter.addConversion([&](seq::ClockType type) {
735 return IntegerType::get(type.getContext(), 1);
737 converter.addConversion([&](StorageType type) {
738 return LLVM::LLVMPointerType::get(type.getContext());
740 converter.addConversion([&](MemoryType type) {
741 return LLVM::LLVMPointerType::get(type.getContext());
743 converter.addConversion([&](StateType type) {
744 return LLVM::LLVMPointerType::get(type.getContext());
746 converter.addConversion([&](SimModelInstanceType type) {
747 return LLVM::LLVMPointerType::get(type.getContext());
754 populateSCFToControlFlowConversionPatterns(
patterns);
755 populateFuncToLLVMConversionPatterns(converter,
patterns);
756 cf::populateControlFlowToLLVMConversionPatterns(converter,
patterns);
757 arith::populateArithToLLVMConversionPatterns(converter,
patterns);
758 index::populateIndexToLLVMConversionPatterns(converter,
patterns);
759 populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns, converter);
762 DenseMap<std::pair<Type, ArrayAttr>, LLVM::GlobalOp> constAggregateGlobalsMap;
764 std::optional<HWToLLVMArraySpillCache> spillCacheOpt =
767 OpBuilder spillBuilder(getOperation());
768 spillCacheOpt->spillNonHWOps(spillBuilder, converter, getOperation());
771 constAggregateGlobalsMap, spillCacheOpt);
779 AllocMemoryOpLowering,
780 AllocStateLikeOpLowering<arc::AllocStateOp>,
781 AllocStateLikeOpLowering<arc::RootInputOp>,
782 AllocStateLikeOpLowering<arc::RootOutputOp>,
783 AllocStorageOpLowering,
786 MemoryReadOpLowering,
787 MemoryWriteOpLowering,
789 ReplaceOpWithInputPattern<seq::ToClockOp>,
790 ReplaceOpWithInputPattern<seq::FromClockOp>,
791 SeqConstClockLowering,
792 SimEmitValueOpLowering,
794 StateWriteOpLowering,
795 StorageGetOpLowering,
797 >(converter, &getContext());
801 SmallVector<ModelInfo> models;
807 llvm::DenseMap<StringRef, ModelInfoMap> modelMap(models.size());
808 for (ModelInfo &modelInfo : models) {
809 llvm::DenseMap<StringRef, StateInfo> states(modelInfo.states.size());
810 for (StateInfo &stateInfo : modelInfo.states)
811 states.insert({stateInfo.name, stateInfo});
814 ModelInfoMap{modelInfo.numStateBytes, std::move(states),
815 modelInfo.initialFnSym, modelInfo.finalFnSym}});
818 patterns.add<SimInstantiateOpLowering, SimSetInputOpLowering,
819 SimGetPortOpLowering, SimStepOpLowering>(
820 converter, &getContext(), modelMap);
823 ConversionConfig config;
824 config.allowPatternRollback =
false;
825 if (failed(applyFullConversion(getOperation(), target, std::move(
patterns),
831 return std::make_unique<LowerArcToLLVMPass>();
static llvm::Twine evalSymbolFromModelName(StringRef modelName)
static LogicalResult convert(arc::ExecuteOp op, arc::ExecuteOp::Adaptor adaptor, ConversionPatternRewriter &rewriter, const TypeConverter &converter)
Extension of RewritePatternSet that allows adding matchAndRewrite functions with op adaptors and Conv...
A namespace that is used to store existing names and generate new names in some scope within the IR.
void add(mlir::ModuleOp module)
void addDefinitions(mlir::Operation *top)
Populate the symbol cache with all symbol-defining operations within the 'top' operation.
Default symbol cache implementation; stores associations between names (StringAttr's) to mlir::Operat...
mlir::LogicalResult collectModels(mlir::ModuleOp module, llvm::SmallVector< ModelInfo > &models)
Collects information about all Arc models in the provided module, and adds it to models.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
void populateCombToArithConversionPatterns(TypeConverter &converter, RewritePatternSet &patterns)
void populateCombToLLVMConversionPatterns(mlir::LLVMTypeConverter &converter, RewritePatternSet &patterns)
Get the Comb to LLVM conversion patterns.
void populateHWToLLVMTypeConversions(mlir::LLVMTypeConverter &converter)
Get the HW to LLVM type conversions.
void populateHWToLLVMConversionPatterns(mlir::LLVMTypeConverter &converter, RewritePatternSet &patterns, Namespace &globals, DenseMap< std::pair< Type, ArrayAttr >, mlir::LLVM::GlobalOp > &constAggregateGlobalsMap, std::optional< HWToLLVMArraySpillCache > &spillCacheOpt)
Get the HW to LLVM conversion patterns.
std::unique_ptr< OperationPass< ModuleOp > > createLowerArcToLLVMPass()
Helper class mapping array values (HW or LLVM Dialect) to pointers to buffers containing the array va...