17#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
18#include "mlir/Dialect/MemRef/IR/MemRef.h"
19#include "mlir/Dialect/SCF/IR/SCF.h"
20#include "mlir/IR/Matchers.h"
26using namespace mlir::arith;
31template <
typename OpTy>
33 PatternRewriter &rewriter) {
34 auto *body = parOp.getBodyBlock();
35 if (body->getOperations().size() < 2)
38 LogicalResult result = LogicalResult::failure();
39 SetVector<StringRef> members;
40 for (
auto &op : make_early_inc_range(*body)) {
41 auto enableOp = dyn_cast<EnableOp>(&op);
42 if (enableOp ==
nullptr)
44 bool inserted = members.insert(enableOp.getGroupName());
46 rewriter.eraseOp(enableOp);
47 result = LogicalResult::success();
54 Value memref,
unsigned memoryID,
55 SmallVectorImpl<calyx::PortInfo> &inPorts,
56 SmallVectorImpl<calyx::PortInfo> &outPorts) {
57 MemRefType memrefType = cast<MemRefType>(memref.getType());
62 auto getMemoryInterfaceAttr = [&](StringRef tag,
63 std::optional<unsigned> addrIdx = {}) {
64 auto attrs = SmallVector<NamedAttribute>{
66 rewriter.getNamedAttr(
"id", rewriter.getI32IntegerAttr(memoryID)),
68 rewriter.getNamedAttr(
"tag", rewriter.getStringAttr(tag))};
69 if (addrIdx.has_value())
72 attrs.push_back(rewriter.getNamedAttr(
73 "addr_idx", rewriter.getI32IntegerAttr(*addrIdx)));
75 return rewriter.getNamedAttr(
"mem", rewriter.getDictionaryAttr(attrs));
80 rewriter.getStringAttr(memName +
"_read_data"),
82 DictionaryAttr::get(rewriter.getContext(),
83 {getMemoryInterfaceAttr(
"read_data")})});
89 DictionaryAttr::get(rewriter.getContext(),
90 {getMemoryInterfaceAttr(
"done")})});
94 rewriter.getStringAttr(memName +
"_write_data"),
96 DictionaryAttr::get(rewriter.getContext(),
97 {getMemoryInterfaceAttr(
"write_data")})});
100 for (
auto dim : enumerate(memrefType.getShape())) {
102 rewriter.getStringAttr(memName +
"_addr" + std::to_string(dim.index())),
105 DictionaryAttr::get(rewriter.getContext(),
106 {getMemoryInterfaceAttr(
"addr", dim.index())})});
111 rewriter.getStringAttr(memName +
"_write_en"), rewriter.getI1Type(),
113 DictionaryAttr::get(rewriter.getContext(),
114 {getMemoryInterfaceAttr(
"write_en")})});
119 SmallVectorImpl<Attribute> &sourceLocations) {
120 Builder builder(component->getContext());
121 return component.getControlOp().walk([&](Operation *op) {
123 return WalkResult::advance();
125 std::string sourceLocation;
126 llvm::raw_string_ostream os(sourceLocation);
127 op->getLoc()->print(os);
128 int64_t position = sourceLocations.size();
129 sourceLocations.push_back(
130 StringAttr::get(op->getContext(), sourceLocation));
132 op->setAttr(
"pos", builder.getI64IntegerAttr(position));
133 return WalkResult::advance();
138 return mlir::detail::constant_int_value_binder(&value).match(op);
142 return llvm::count_if(memoryReference.getUses(), [](OpOperand &user) {
143 return isa<mlir::memref::LoadOp>(user.getOwner());
148 return llvm::none_of(memoryReference.getUses(), [](OpOperand &user) {
149 return isa<mlir::memref::StoreOp>(user.getOwner());
154 size_t index = compOp.getInputPortInfo().size() + outPortIdx;
155 assert(index < compOp.getNumArguments() &&
156 "Exceeded number of arguments in the Component");
157 return compOp.getArgument(index);
162 return builder.getI32Type();
163 if (type.isIntOrFloat())
169 calyx::GroupOp groupOp,
170 calyx::ComponentOp componentOp,
171 calyx::RegisterOp ®,
173 mlir::IRRewriter::InsertionGuard guard(builder);
174 auto loc = inputValue.getLoc();
175 builder.setInsertionPointToEnd(groupOp.getBodyBlock());
176 calyx::AssignOp::create(builder, loc, reg.getIn(), inputValue);
177 calyx::AssignOp::create(builder, loc, reg.getWriteEn(),
179 calyx::GroupDoneOp::create(builder, loc, reg.getDone());
203 assert(
readEn.has_value() &&
"Memory does not have readEn");
221 assert(
writeEn.has_value() &&
"Memory does not have writeEn");
227 assert(
done.has_value() &&
"Memory does not have done");
232 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
233 return memOp->getName().str();
236 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
237 return memOp->getName().str();
239 return std::get<MemoryPortsImpl>(
impl).memName;
243 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
244 return memOp->readData();
247 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
248 return memOp->readData();
250 return std::get<MemoryPortsImpl>(
impl).readData;
254 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
258 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
262 if (std::get<MemoryPortsImpl>(
impl).readOrContentEn.has_value()) {
263 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.has_value());
264 assert(!std::get<MemoryPortsImpl>(
impl).isContentEn.value());
266 return std::get<MemoryPortsImpl>(
impl).readOrContentEn;
270 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
274 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
275 return memOp->contentEn();
278 if (std::get<MemoryPortsImpl>(
impl).readOrContentEn.has_value()) {
280 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.has_value());
281 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.value());
283 return std::get<MemoryPortsImpl>(
impl).readOrContentEn;
287 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
288 return memOp->writeData();
291 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
292 return memOp->writeData();
294 return std::get<MemoryPortsImpl>(
impl).writeData;
298 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
299 return memOp->writeEn();
302 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
303 return memOp->writeEn();
305 return std::get<MemoryPortsImpl>(
impl).writeEn;
309 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
310 return memOp->done();
313 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
314 return memOp->done();
316 return std::get<MemoryPortsImpl>(
impl).done;
320 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
321 return memOp->addrPorts();
324 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
325 return memOp->addrPorts();
327 return std::get<MemoryPortsImpl>(
impl).addrPorts;
341 calyx::ComponentOp component)
342 : component(component), extMemData(
llvm::
json::Object{}) {}
351 calyx::RegisterOp reg,
354 assert(idx < block->getArguments().size());
358const DenseMap<unsigned, calyx::RegisterOp> &
364 calyx::GroupOp grp) {
368ArrayRef<calyx::GroupOp>
374 std::string prefixStr = prefix.str();
377 return (prefix +
"_" + std::to_string(idx)).str();
382 assert(it !=
opNames.end() &&
"A unique name should have been set for op");
389 "A unique name was already set for op");
394 Value v, calyx::GroupInterface group) {
401 "A register was already registered for this index");
412 assert(isa<MemRefType>(memref.getType()));
414 "Memory already registered for memref");
420 assert(isa<MemRefType>(memref.getType()));
422 assert(it !=
memories.end() &&
"No memory registered for memref");
426std::optional<calyx::MemoryInterface>
429 auto &mem = memIf.getSecond();
430 if (mem.writeEn() == v || mem.writeData() == v ||
431 llvm::any_of(mem.addrPorts(), [=](Value port) { return port == v; }))
438 const DenseMap<unsigned, unsigned> &mapping) {
443 unsigned funcReturnIdx) {
446 "No component return port index recorded for the requested function "
456 InstanceOp instanceOp) {
473 StringRef topLevelFunction)
474 : topLevelFunction(topLevelFunction), module(module) {}
477 assert(module.getOperation() !=
nullptr);
498 StringRef topLevelFunction) {
500 if (moduleOp->hasAttr(
"calyx.entrypoint"))
503 moduleOp->setAttr(
"calyx.entrypoint",
504 StringAttr::get(moduleOp.getContext(), topLevelFunction));
513 MLIRContext *context, LogicalResult &resRef,
515 DenseMap<mlir::func::FuncOp, calyx::ComponentOp> &map,
518 functionMapping(map), calyxLoweringState(state) {}
522 PatternRewriter &rewriter)
const {
537 "Component operation should be set during pattern construction");
551 PatternRewriter &rewriter)
const {
552 funcOp.walk([&](Block *block) {
553 for (Value arg : block->getArguments())
557 funcOp.walk([&](Operation *op) {
558 for (Value result : op->getResults()) {
559 Type resType = result.getType();
560 if (!resType.isIndex())
564 auto constant = dyn_cast<mlir::arith::ConstantOp>(op);
570 rewriter.setInsertionPoint(constant);
571 rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
572 constant, rewriter.getI32IntegerAttr(value.getSExtValue()));
584 PatternRewriter &)
const {
585 Block *block = groupDoneOp->getBlock();
586 if (&block->back() == groupDoneOp)
589 groupDoneOp->moveBefore(groupDoneOp->getBlock(),
590 groupDoneOp->getBlock()->end());
600 PatternRewriter &rewriter)
const {
601 auto groupDoneOps = SmallVector<calyx::GroupDoneOp>(
602 groupOp.getBodyBlock()->getOps<calyx::GroupDoneOp>());
604 if (groupDoneOps.size() <= 1)
608 rewriter.setInsertionPointToEnd(groupDoneOps[0]->getBlock());
609 SmallVector<Value> doneOpSrcs;
610 llvm::transform(groupDoneOps, std::back_inserter(doneOpSrcs),
611 [](calyx::GroupDoneOp op) {
return op.getSrc(); });
612 Value allDone = comb::AndOp::create(rewriter, groupDoneOps.front().getLoc(),
616 calyx::GroupDoneOp::create(
617 rewriter, groupOp.getLoc(),
619 for (
auto groupDoneOp : groupDoneOps)
620 rewriter.eraseOp(groupDoneOp);
631 PatternRewriter &rewriter)
const {
633 combGroupOp->getParentOfType<calyx::ComponentOp>().getControlOp();
634 if (!SymbolTable::symbolKnownUseEmpty(combGroupOp.getSymNameAttr(), control))
637 rewriter.eraseOp(combGroupOp);
647 PatternRewriter &rewriter)
const {
648 return deduplicateParallelOperation<calyx::ParOp>(parOp, rewriter);
653 PatternRewriter &rewriter)
const {
654 return deduplicateParallelOperation<calyx::StaticParOp>(parOp, rewriter);
668 PatternRewriter &rewriter)
const {
669 auto component = originGroup->getParentOfType<calyx::ComponentOp>();
673 if (SymbolTable::symbolKnownUseEmpty(originGroup.symName(),
674 component.getControlOp()))
679 llvm::SmallSetVector<Operation *, 8> inlinedGroups;
680 inlinedGroups.insert(originGroup);
693 llvm::SmallSetVector<Operation *, 8> &inlinedGroups,
694 calyx::GroupInterface originGroup, calyx::GroupInterface recGroup,
695 bool doInline)
const {
696 inlinedGroups.insert(recGroup);
697 for (
auto assignOp : recGroup.getBody()->getOps<calyx::AssignOp>()) {
700 auto *clonedAssignOp = rewriter.clone(*assignOp.getOperation());
701 clonedAssignOp->moveBefore(originGroup.getBody(),
702 originGroup.getBody()->end());
704 Value src = assignOp.getSrc();
716 if (isa<BlockArgument>(src) ||
717 isa<calyx::RegisterOp, calyx::MemoryOp, calyx::SeqMemoryOp,
719 calyx::DivUPipeLibOp, calyx::DivSPipeLibOp, calyx::RemSPipeLibOp,
720 calyx::RemUPipeLibOp, mlir::scf::WhileOp, calyx::InstanceOp,
721 calyx::ConstantOp, calyx::AddFOpIEEE754, calyx::MulFOpIEEE754,
722 calyx::CompareFOpIEEE754, calyx::FpToIntOpIEEE754,
723 calyx::IntToFpOpIEEE754, calyx::DivSqrtOpIEEE754>(
724 src.getDefiningOp()))
731 auto srcCombGroup = dyn_cast<calyx::CombGroupOp>(
735 if (inlinedGroups.count(srcCombGroup))
749 PatternRewriter &rewriter)
const {
750 auto *state =
cls.
getState(assignOp->getParentOfType<calyx::ComponentOp>());
752 Value dest = assignOp.getDest();
753 if (!state->isInputPortOfMemory(dest))
756 Value src = assignOp.getSrc();
757 unsigned srcBits = src.getType().getIntOrFloatBitWidth();
758 unsigned dstBits = dest.getType().getIntOrFloatBitWidth();
759 if (srcBits == dstBits)
762 SmallVector<Type> types = {
763 rewriter.getIntegerType(srcBits),
764 rewriter.getIntegerType(dstBits),
766 mlir::Location loc = assignOp.getLoc();
768 if (srcBits > dstBits)
770 state->getNewLibraryOpInstance<calyx::SliceLibOp>(rewriter, loc, types);
773 state->getNewLibraryOpInstance<calyx::PadLibOp>(rewriter, loc, types);
775 rewriter.setInsertionPoint(assignOp->getBlock(),
776 assignOp->getBlock()->begin());
777 calyx::AssignOp::create(rewriter, assignOp->getLoc(), newOp->getResult(0),
779 assignOp.setOperand(1, newOp->getResult(1));
790 PatternRewriter &rewriter)
const {
791 funcOp.walk([&](Block *block) {
793 if (block == &block->getParent()->front())
796 for (
auto arg : enumerate(block->getArguments())) {
797 Type argType = arg.value().getType();
798 assert(isa<IntegerType>(argType) &&
"unsupported block argument type");
799 unsigned width = argType.getIntOrFloatBitWidth();
800 std::string index = std::to_string(arg.index());
804 getState().addBlockArgReg(block, reg, arg.index());
805 arg.value().replaceAllUsesWith(reg.getOut());
817 PatternRewriter &rewriter)
const {
819 for (
auto argType : enumerate(funcOp.getResultTypes())) {
821 assert((isa<IntegerType>(convArgType) || isa<FloatType>(convArgType)) &&
822 "unsupported return type");
823 std::string name =
"ret_arg" + std::to_string(argType.index());
825 convArgType.getIntOrFloatBitWidth(), name);
826 getState().addReturnReg(reg, argType.index());
828 rewriter.setInsertionPointToStart(
830 calyx::AssignOp::create(
831 rewriter, funcOp->getLoc(),
845 PatternRewriter &rewriter)
const {
846 funcOp.walk([&](mlir::func::CallOp callOp) {
848 SmallVector<Type, 8> resultTypes;
850 resultTypes.push_back(type);
852 resultTypes.push_back(type);
858 if (!
getState().getInstance(instanceName)) {
859 InstanceOp instanceOp =
862 getState().addInstance(instanceName, instanceOp);
864 WalkResult::advance();
871 std::string callee =
"func_" + callOp.getCallee().str();
873 if (funcOp.getSymName() == callee)
884 case CmpFPredicate::OEQ: {
885 info.logic = CombLogic::And;
886 info.inputPorts = {{Port::Eq,
false},
887 {Port::Unordered,
true}};
890 case CmpFPredicate::OGT: {
892 info.inputPorts = {{Port::Gt,
false},
893 {Port::Unordered,
true}};
896 case CmpFPredicate::OGE: {
898 info.inputPorts = {{Port::Lt,
true},
899 {Port::Unordered,
true}};
902 case CmpFPredicate::OLT: {
904 info.inputPorts = {{Port::Lt,
false},
905 {Port::Unordered,
true}};
908 case CmpFPredicate::OLE: {
910 info.inputPorts = {{Port::Gt,
true},
911 {Port::Unordered,
true}};
914 case CmpFPredicate::ONE: {
916 info.inputPorts = {{Port::Eq,
true},
917 {Port::Unordered,
true}};
920 case CmpFPredicate::ORD: {
922 info.inputPorts = {{Port::Unordered,
true}};
925 case CmpFPredicate::UEQ: {
927 info.inputPorts = {{Port::Eq,
false},
928 {Port::Unordered,
false}};
931 case CmpFPredicate::UGT: {
933 info.inputPorts = {{Port::Gt,
false},
934 {Port::Unordered,
false}};
937 case CmpFPredicate::UGE: {
939 info.inputPorts = {{Port::Lt,
true},
940 {Port::Unordered,
false}};
943 case CmpFPredicate::ULT: {
945 info.inputPorts = {{Port::Lt,
false},
946 {Port::Unordered,
false}};
949 case CmpFPredicate::ULE: {
951 info.inputPorts = {{Port::Gt,
true},
952 {Port::Unordered,
false}};
955 case CmpFPredicate::UNE: {
957 info.inputPorts = {{Port::Eq,
true},
958 {Port::Unordered,
false}};
961 case CmpFPredicate::UNO: {
963 info.inputPorts = {{Port::Unordered,
false}};
966 case CmpFPredicate::AlwaysTrue:
967 case CmpFPredicate::AlwaysFalse:
976 if (Operation *defOp = value.getDefiningOp()) {
977 auto cellOp = dyn_cast_or_null<calyx::CellInterface>(defOp);
978 return cellOp && !cellOp.isCombinational();
assert(baseType &&"element must be base type")
static Block * getBodyBlock(FModuleLike mod)
virtual ~BasicLoopInterface()
LogicalResult partiallyLowerFuncToComp(mlir::func::FuncOp funcOp, PatternRewriter &rewriter) const override
LogicalResult partiallyLowerFuncToComp(mlir::func::FuncOp funcOp, PatternRewriter &rewriter) const override
ComponentOp getCallComponent(mlir::func::CallOp callOp) const
LogicalResult partiallyLowerFuncToComp(mlir::func::FuncOp funcOp, PatternRewriter &rewriter) const override
An interface for conversion passes that lower Calyx programs.
std::string irName(ValueOrBlock &v)
Returns a meaningful name for a value within the program scope.
mlir::ModuleOp getModule()
Returns the current program.
CalyxLoweringState(mlir::ModuleOp module, StringRef topLevelFunction)
std::string blockName(Block *b)
Returns a meaningful name for a block within the program scope (removes the ^ prefix from block names...
StringRef getTopLevelFunction() const
Returns the name of the top-level function in the source program.
StringRef topLevelFunction
The name of this top-level function.
T * getState(calyx::ComponentOp op)
Returns the component lowering state associated with op.
void addSeqGuardCmpLibOp(Operation *op)
Add op if it's a compare operator that requires a register to hold the value of its sequential guard ...
const DenseMap< unsigned, calyx::RegisterOp > & getBlockArgRegs(Block *block)
Return a mapping of block argument indices to block argument registers.
void setFuncOpResultMapping(const DenseMap< unsigned, unsigned > &mapping)
Assign a mapping between the source funcOp result indices and the corresponding output port indices o...
DenseMap< Value, calyx::MemoryInterface > memories
A mapping from memref's to their corresponding Calyx memory interface.
TGroupOp getEvaluatingGroup(Value v)
Return the group which evaluates the value v.
void addReturnReg(calyx::RegisterOp reg, unsigned idx)
Register reg as being the idx'th return value register.
calyx::MemoryInterface getMemoryInterface(Value memref)
Returns the memory interface registered for the given memref.
llvm::StringMap< calyx::InstanceOp > instanceMap
A mapping between the callee and the instance.
DenseMap< Block *, DenseMap< Block *, SmallVector< calyx::GroupOp > > > blockArgGroups
Block arg groups is a list of groups that should be sequentially executed when passing control from t...
void setUniqueName(Operation *op, StringRef prefix)
Registers a unique name for a given operation using a provided prefix.
calyx::RegisterOp getReturnReg(unsigned idx)
Returns the idx'th return value register.
std::string getUniqueName(StringRef prefix)
Returns a unique name within compOp with the provided prefix.
calyx::ComponentOp component
The component which this lowering state is associated to.
void registerMemoryInterface(Value memref, const calyx::MemoryInterface &memoryInterface)
Registers a memory interface as being associated with a memory identified by 'memref'.
calyx::ComponentOp getComponentOp()
Returns the calyx::ComponentOp associated with this lowering state.
void addBlockArgReg(Block *block, calyx::RegisterOp reg, unsigned idx)
Register reg as being the idx'th argument register for block.
InstanceOp getInstance(StringRef calleeName)
The instance is obtained from the name of the callee.
unsigned getFuncOpResultMapping(unsigned funcReturnIdx)
Get the output port index of this component for which the funcReturnIdx of the original function maps...
DenseMap< unsigned, unsigned > funcOpResultMapping
A mapping between the source funcOp result indices and the corresponding output port indices of this ...
void addInstance(StringRef calleeName, InstanceOp instanceOp)
Put the name of the callee and the instance of the call into map.
DenseMap< Value, calyx::GroupInterface > valueGroupAssigns
A mapping between SSA values and the groups which assign them.
bool isSeqGuardCmpLibOp(Operation *op)
Returns if op is a compare operator that requires a register to hold the value of its sequential guar...
std::map< std::string, unsigned > prefixIdMap
A mapping of string prefixes and the current uniqueness counter for that prefix.
ArrayRef< calyx::GroupOp > getBlockArgGroups(Block *from, Block *to)
Returns a list of groups to be evaluated to perform the block argument register assignments when tran...
ComponentLoweringStateInterface(calyx::ComponentOp component)
void registerEvaluatingGroup(Value v, calyx::GroupInterface group)
Register value v as being evaluated when scheduling group.
DenseSet< Operation * > seqGuardCmpLibOps
A set of compare operators that require registers to hold their sequential guard computation.
std::optional< calyx::MemoryInterface > isInputPortOfMemory(Value v)
If v is an input to any memory registered within this component, returns the memory.
void addBlockArgGroup(Block *from, Block *to, calyx::GroupOp grp)
Register 'grp' as a group which performs block argument register transfer when transitioning from bas...
virtual ~ComponentLoweringStateInterface()
DenseMap< Block *, DenseMap< unsigned, calyx::RegisterOp > > blockArgRegs
A mapping from blocks to block argument registers.
DenseMap< unsigned, calyx::RegisterOp > returnRegs
A mapping from return value indexes to return value registers.
std::map< Operation *, std::string > opNames
A mapping from Operations and previously assigned unique name of the op.
LogicalResult partiallyLowerFuncToComp(mlir::func::FuncOp funcOp, PatternRewriter &rewriter) const override
calyx::ComponentOp getComponent() const
Returns the component operation associated with the currently executing partial lowering.
CalyxLoweringState & calyxLoweringState
ComponentLoweringStateInterface * componentLoweringState
DenseMap< mlir::func::FuncOp, calyx::ComponentOp > & functionMapping
virtual LogicalResult partiallyLowerFuncToComp(mlir::func::FuncOp funcOp, PatternRewriter &rewriter) const =0
CalyxLoweringState & loweringState() const
Return the calyx lowering state for this pattern.
FuncOpPartialLoweringPattern(MLIRContext *context, LogicalResult &resRef, PatternApplicationState &patternState, DenseMap< mlir::func::FuncOp, calyx::ComponentOp > &map, calyx::CalyxLoweringState &state)
LogicalResult partiallyLower(mlir::func::FuncOp funcOp, PatternRewriter &rewriter) const override final
Entry point to initialize the state of this class and conduct the partial lowering.
LogicalResult partiallyLower(calyx::GroupInterface originGroup, PatternRewriter &rewriter) const override
InlineCombGroups(MLIRContext *context, LogicalResult &resRef, PatternApplicationState &patternState, calyx::CalyxLoweringState &pls)
void recurseInlineCombGroups(PatternRewriter &rewriter, ComponentLoweringStateInterface &state, llvm::SmallSetVector< Operation *, 8 > &inlinedGroups, calyx::GroupInterface originGroup, calyx::GroupInterface recGroup, bool doInline) const
calyx::CalyxLoweringState & cls
Base class for partial lowering passes.
calyx::CalyxLoweringState & cls
LogicalResult partiallyLower(calyx::AssignOp assignOp, PatternRewriter &rewriter) const override
bool parentIsSeqCell(Value value)
void appendPortsForExternalMemref(PatternRewriter &rewriter, StringRef memName, Value memref, unsigned memoryID, SmallVectorImpl< calyx::PortInfo > &inPorts, SmallVectorImpl< calyx::PortInfo > &outPorts)
void buildAssignmentsForRegisterWrite(OpBuilder &builder, calyx::GroupOp groupOp, calyx::ComponentOp componentOp, calyx::RegisterOp ®, Value inputValue)
Creates register assignment operations within the provided groupOp.
DenseMap< const mlir::RewritePattern *, SmallPtrSet< Operation *, 16 > > PatternApplicationState
Extra state that is passed to all PartialLoweringPatterns so they can record when they have run on an...
PredicateInfo getPredicateInfo(mlir::arith::CmpFPredicate pred)
bool isControlLeafNode(Operation *op)
Type normalizeType(OpBuilder &builder, Type type)
LogicalResult applyModuleOpConversion(mlir::ModuleOp, StringRef topLevelFunction)
Helper to update the top-level ModuleOp to set the entrypoing function.
static LogicalResult deduplicateParallelOperation(OpTy parOp, PatternRewriter &rewriter)
WalkResult getCiderSourceLocationMetadata(calyx::ComponentOp component, SmallVectorImpl< Attribute > &sourceLocations)
bool matchConstantOp(Operation *op, APInt &value)
unsigned handleZeroWidth(int64_t dim)
hw::ConstantOp createConstant(Location loc, OpBuilder &builder, ComponentOp component, size_t width, size_t value)
A helper function to create constants in the HW dialect.
calyx::RegisterOp createRegister(Location loc, OpBuilder &builder, ComponentOp component, size_t width, Twine prefix)
Creates a RegisterOp, with input and output port bit widths defined by width.
bool noStoresToMemory(Value memoryReference)
Value getComponentOutput(calyx::ComponentOp compOp, unsigned outPortIdx)
bool singleLoadFromMemory(Value memoryReference)
calyx::InstanceOp createInstance(Location loc, OpBuilder &builder, ComponentOp component, SmallVectorImpl< Type > &resultTypes, StringRef instanceName, StringRef componentName)
A helper function to create calyx.instance operation.
Type toBitVector(T type)
Performs a bit cast from a non-signless integer type value, such as a floating point value,...
std::string getInstanceName(mlir::func::CallOp callOp)
A helper function to get the instance name.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
LogicalResult matchAndRewrite(calyx::ParOp parOp, PatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(calyx::StaticParOp parOp, PatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(calyx::CombGroupOp combGroupOp, PatternRewriter &rewriter) const override
std::optional< Value > contentEnOpt()
std::variant< calyx::MemoryOp, calyx::SeqMemoryOp, MemoryPortsImpl > impl
std::optional< Value > writeDataOpt()
std::optional< Value > readEnOpt()
std::optional< Value > readDataOpt()
std::optional< Value > doneOpt()
std::optional< Value > writeEnOpt()
std::optional< Value > readOrContentEn
std::optional< Value > writeEn
std::optional< bool > isContentEn
LogicalResult matchAndRewrite(calyx::GroupOp groupOp, PatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(calyx::GroupDoneOp groupDoneOp, PatternRewriter &) const override
This holds information about the port for either a Component or Cell.
Predicate information for the floating point comparisons.