18#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
19#include "mlir/Dialect/MemRef/IR/MemRef.h"
20#include "mlir/Dialect/SCF/IR/SCF.h"
21#include "mlir/IR/Matchers.h"
27using namespace mlir::arith;
32template <
typename OpTy>
34 PatternRewriter &rewriter) {
35 auto *body = parOp.getBodyBlock();
36 if (body->getOperations().size() < 2)
39 LogicalResult result = LogicalResult::failure();
40 SetVector<StringRef> members;
41 for (
auto &op : make_early_inc_range(*body)) {
42 auto enableOp = dyn_cast<EnableOp>(&op);
43 if (enableOp ==
nullptr)
45 bool inserted = members.insert(enableOp.getGroupName());
47 rewriter.eraseOp(enableOp);
48 result = LogicalResult::success();
55 Value memref,
unsigned memoryID,
56 SmallVectorImpl<calyx::PortInfo> &inPorts,
57 SmallVectorImpl<calyx::PortInfo> &outPorts) {
58 MemRefType memrefType = cast<MemRefType>(memref.getType());
63 auto getMemoryInterfaceAttr = [&](StringRef tag,
64 std::optional<unsigned> addrIdx = {}) {
65 auto attrs = SmallVector<NamedAttribute>{
67 rewriter.getNamedAttr(
"id", rewriter.getI32IntegerAttr(memoryID)),
69 rewriter.getNamedAttr(
"tag", rewriter.getStringAttr(tag))};
70 if (addrIdx.has_value())
73 attrs.push_back(rewriter.getNamedAttr(
74 "addr_idx", rewriter.getI32IntegerAttr(*addrIdx)));
76 return rewriter.getNamedAttr(
"mem", rewriter.getDictionaryAttr(attrs));
81 rewriter.getStringAttr(memName +
"_read_data"),
83 DictionaryAttr::get(rewriter.getContext(),
84 {getMemoryInterfaceAttr(
"read_data")})});
90 DictionaryAttr::get(rewriter.getContext(),
91 {getMemoryInterfaceAttr(
"done")})});
95 rewriter.getStringAttr(memName +
"_write_data"),
97 DictionaryAttr::get(rewriter.getContext(),
98 {getMemoryInterfaceAttr(
"write_data")})});
101 for (
auto dim : enumerate(memrefType.getShape())) {
103 rewriter.getStringAttr(memName +
"_addr" + std::to_string(dim.index())),
106 DictionaryAttr::get(rewriter.getContext(),
107 {getMemoryInterfaceAttr(
"addr", dim.index())})});
112 rewriter.getStringAttr(memName +
"_write_en"), rewriter.getI1Type(),
114 DictionaryAttr::get(rewriter.getContext(),
115 {getMemoryInterfaceAttr(
"write_en")})});
120 SmallVectorImpl<Attribute> &sourceLocations) {
121 Builder builder(component->getContext());
122 return component.getControlOp().walk([&](Operation *op) {
124 return WalkResult::advance();
126 std::string sourceLocation;
127 llvm::raw_string_ostream os(sourceLocation);
128 op->getLoc()->print(os);
129 int64_t position = sourceLocations.size();
130 sourceLocations.push_back(
131 StringAttr::get(op->getContext(), sourceLocation));
133 op->setAttr(
"pos", builder.getI64IntegerAttr(position));
134 return WalkResult::advance();
139 return mlir::detail::constant_int_value_binder(&value).match(op);
143 return llvm::count_if(memoryReference.getUses(), [](OpOperand &user) {
144 return isa<mlir::memref::LoadOp>(user.getOwner());
149 return llvm::none_of(memoryReference.getUses(), [](OpOperand &user) {
150 return isa<mlir::memref::StoreOp>(user.getOwner());
155 size_t index = compOp.getInputPortInfo().size() + outPortIdx;
156 assert(index < compOp.getNumArguments() &&
157 "Exceeded number of arguments in the Component");
158 return compOp.getArgument(index);
163 return builder.getI32Type();
164 if (type.isIntOrFloat())
170 calyx::GroupOp groupOp,
171 calyx::ComponentOp componentOp,
172 calyx::RegisterOp ®,
174 mlir::IRRewriter::InsertionGuard guard(builder);
175 auto loc = inputValue.getLoc();
176 builder.setInsertionPointToEnd(groupOp.getBodyBlock());
177 builder.create<calyx::AssignOp>(loc, reg.getIn(), inputValue);
178 builder.create<calyx::AssignOp>(
179 loc, reg.getWriteEn(),
createConstant(loc, builder, componentOp, 1, 1));
180 builder.create<calyx::GroupDoneOp>(loc, reg.getDone());
204 assert(
readEn.has_value() &&
"Memory does not have readEn");
222 assert(
writeEn.has_value() &&
"Memory does not have writeEn");
228 assert(
done.has_value() &&
"Memory does not have done");
233 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
234 return memOp->getName().str();
237 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
238 return memOp->getName().str();
240 return std::get<MemoryPortsImpl>(
impl).memName;
244 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
245 return memOp->readData();
248 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
249 return memOp->readData();
251 return std::get<MemoryPortsImpl>(
impl).readData;
255 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
259 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
263 if (std::get<MemoryPortsImpl>(
impl).readOrContentEn.has_value()) {
264 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.has_value());
265 assert(!std::get<MemoryPortsImpl>(
impl).isContentEn.value());
267 return std::get<MemoryPortsImpl>(
impl).readOrContentEn;
271 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
275 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
276 return memOp->contentEn();
279 if (std::get<MemoryPortsImpl>(
impl).readOrContentEn.has_value()) {
281 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.has_value());
282 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.value());
284 return std::get<MemoryPortsImpl>(
impl).readOrContentEn;
288 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
289 return memOp->writeData();
292 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
293 return memOp->writeData();
295 return std::get<MemoryPortsImpl>(
impl).writeData;
299 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
300 return memOp->writeEn();
303 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
304 return memOp->writeEn();
306 return std::get<MemoryPortsImpl>(
impl).writeEn;
310 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
311 return memOp->done();
314 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
315 return memOp->done();
317 return std::get<MemoryPortsImpl>(
impl).done;
321 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
322 return memOp->addrPorts();
325 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
326 return memOp->addrPorts();
328 return std::get<MemoryPortsImpl>(
impl).addrPorts;
342 calyx::ComponentOp component)
343 : component(component), extMemData(
llvm::
json::Object{}) {}
352 calyx::RegisterOp reg,
355 assert(idx < block->getArguments().size());
359const DenseMap<unsigned, calyx::RegisterOp> &
365 calyx::GroupOp grp) {
369ArrayRef<calyx::GroupOp>
375 std::string prefixStr = prefix.str();
378 return (prefix +
"_" + std::to_string(idx)).str();
383 assert(it !=
opNames.end() &&
"A unique name should have been set for op");
390 "A unique name was already set for op");
395 Value v, calyx::GroupInterface group) {
402 "A register was already registered for this index");
413 assert(isa<MemRefType>(memref.getType()));
415 "Memory already registered for memref");
421 assert(isa<MemRefType>(memref.getType()));
423 assert(it !=
memories.end() &&
"No memory registered for memref");
427std::optional<calyx::MemoryInterface>
430 auto &mem = memIf.getSecond();
431 if (mem.writeEn() == v || mem.writeData() == v ||
432 llvm::any_of(mem.addrPorts(), [=](Value port) { return port == v; }))
439 const DenseMap<unsigned, unsigned> &mapping) {
444 unsigned funcReturnIdx) {
447 "No component return port index recorded for the requested function "
457 InstanceOp instanceOp) {
474 StringRef topLevelFunction)
475 : topLevelFunction(topLevelFunction), module(module) {}
478 assert(module.getOperation() !=
nullptr);
499 StringRef topLevelFunction) {
501 if (moduleOp->hasAttr(
"calyx.entrypoint"))
504 moduleOp->setAttr(
"calyx.entrypoint",
505 StringAttr::get(moduleOp.getContext(), topLevelFunction));
514 MLIRContext *context, LogicalResult &resRef,
516 DenseMap<mlir::func::FuncOp, calyx::ComponentOp> &map,
519 functionMapping(map), calyxLoweringState(state) {}
523 PatternRewriter &rewriter)
const {
538 "Component operation should be set during pattern construction");
552 PatternRewriter &rewriter)
const {
553 funcOp.walk([&](Block *block) {
554 for (Value arg : block->getArguments())
558 funcOp.walk([&](Operation *op) {
559 for (Value result : op->getResults()) {
560 Type resType = result.getType();
561 if (!resType.isIndex())
565 auto constant = dyn_cast<mlir::arith::ConstantOp>(op);
571 rewriter.setInsertionPoint(constant);
572 rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
573 constant, rewriter.getI32IntegerAttr(value.getSExtValue()));
585 PatternRewriter &)
const {
586 Block *block = groupDoneOp->getBlock();
587 if (&block->back() == groupDoneOp)
590 groupDoneOp->moveBefore(groupDoneOp->getBlock(),
591 groupDoneOp->getBlock()->end());
601 PatternRewriter &rewriter)
const {
602 auto groupDoneOps = SmallVector<calyx::GroupDoneOp>(
603 groupOp.getBodyBlock()->getOps<calyx::GroupDoneOp>());
605 if (groupDoneOps.size() <= 1)
609 rewriter.setInsertionPointToEnd(groupDoneOps[0]->getBlock());
610 SmallVector<Value> doneOpSrcs;
611 llvm::transform(groupDoneOps, std::back_inserter(doneOpSrcs),
612 [](calyx::GroupDoneOp op) {
return op.getSrc(); });
613 Value allDone = rewriter.create<
comb::AndOp>(groupDoneOps.front().getLoc(),
617 rewriter.create<calyx::GroupDoneOp>(
619 rewriter.create<
hw::ConstantOp>(groupOp.getLoc(), APInt(1, 1)), allDone);
620 for (
auto groupDoneOp : groupDoneOps)
621 rewriter.eraseOp(groupDoneOp);
632 PatternRewriter &rewriter)
const {
634 combGroupOp->getParentOfType<calyx::ComponentOp>().getControlOp();
635 if (!SymbolTable::symbolKnownUseEmpty(combGroupOp.getSymNameAttr(), control))
638 rewriter.eraseOp(combGroupOp);
648 PatternRewriter &rewriter)
const {
649 return deduplicateParallelOperation<calyx::ParOp>(parOp, rewriter);
654 PatternRewriter &rewriter)
const {
655 return deduplicateParallelOperation<calyx::StaticParOp>(parOp, rewriter);
669 PatternRewriter &rewriter)
const {
670 auto component = originGroup->getParentOfType<calyx::ComponentOp>();
674 if (SymbolTable::symbolKnownUseEmpty(originGroup.symName(),
675 component.getControlOp()))
680 llvm::SmallSetVector<Operation *, 8> inlinedGroups;
681 inlinedGroups.insert(originGroup);
694 llvm::SmallSetVector<Operation *, 8> &inlinedGroups,
695 calyx::GroupInterface originGroup, calyx::GroupInterface recGroup,
696 bool doInline)
const {
697 inlinedGroups.insert(recGroup);
698 for (
auto assignOp : recGroup.getBody()->getOps<calyx::AssignOp>()) {
701 auto *clonedAssignOp = rewriter.clone(*assignOp.getOperation());
702 clonedAssignOp->moveBefore(originGroup.getBody(),
703 originGroup.getBody()->end());
705 Value src = assignOp.getSrc();
717 if (isa<BlockArgument>(src) ||
718 isa<calyx::RegisterOp, calyx::MemoryOp, calyx::SeqMemoryOp,
720 calyx::DivUPipeLibOp, calyx::DivSPipeLibOp, calyx::RemSPipeLibOp,
721 calyx::RemUPipeLibOp, mlir::scf::WhileOp, calyx::InstanceOp,
722 calyx::ConstantOp, calyx::AddFOpIEEE754, calyx::MulFOpIEEE754,
723 calyx::CompareFOpIEEE754, calyx::FpToIntOpIEEE754,
724 calyx::IntToFpOpIEEE754, calyx::DivSqrtOpIEEE754>(
725 src.getDefiningOp()))
732 auto srcCombGroup = dyn_cast<calyx::CombGroupOp>(
736 if (inlinedGroups.count(srcCombGroup))
750 PatternRewriter &rewriter)
const {
751 auto *state =
cls.
getState(assignOp->getParentOfType<calyx::ComponentOp>());
753 Value dest = assignOp.getDest();
754 if (!state->isInputPortOfMemory(dest))
757 Value src = assignOp.getSrc();
758 unsigned srcBits = src.getType().getIntOrFloatBitWidth();
759 unsigned dstBits = dest.getType().getIntOrFloatBitWidth();
760 if (srcBits == dstBits)
763 SmallVector<Type> types = {
764 rewriter.getIntegerType(srcBits),
765 rewriter.getIntegerType(dstBits),
767 mlir::Location loc = assignOp.getLoc();
769 if (srcBits > dstBits)
771 state->getNewLibraryOpInstance<calyx::SliceLibOp>(rewriter, loc, types);
774 state->getNewLibraryOpInstance<calyx::PadLibOp>(rewriter, loc, types);
776 rewriter.setInsertionPoint(assignOp->getBlock(),
777 assignOp->getBlock()->begin());
778 rewriter.create<calyx::AssignOp>(assignOp->getLoc(), newOp->getResult(0),
780 assignOp.setOperand(1, newOp->getResult(1));
791 PatternRewriter &rewriter)
const {
792 funcOp.walk([&](Block *block) {
794 if (block == &block->getParent()->front())
797 for (
auto arg : enumerate(block->getArguments())) {
798 Type argType = arg.value().getType();
799 assert(isa<IntegerType>(argType) &&
"unsupported block argument type");
800 unsigned width = argType.getIntOrFloatBitWidth();
801 std::string index = std::to_string(arg.index());
805 getState().addBlockArgReg(block, reg, arg.index());
806 arg.value().replaceAllUsesWith(reg.getOut());
818 PatternRewriter &rewriter)
const {
820 for (
auto argType : enumerate(funcOp.getResultTypes())) {
822 assert((isa<IntegerType>(convArgType) || isa<FloatType>(convArgType)) &&
823 "unsupported return type");
824 std::string name =
"ret_arg" + std::to_string(argType.index());
826 convArgType.getIntOrFloatBitWidth(), name);
827 getState().addReturnReg(reg, argType.index());
829 rewriter.setInsertionPointToStart(
831 rewriter.create<calyx::AssignOp>(
846 PatternRewriter &rewriter)
const {
847 funcOp.walk([&](mlir::func::CallOp callOp) {
849 SmallVector<Type, 8> resultTypes;
851 resultTypes.push_back(type);
853 resultTypes.push_back(type);
859 if (!
getState().getInstance(instanceName)) {
860 InstanceOp instanceOp =
863 getState().addInstance(instanceName, instanceOp);
865 WalkResult::advance();
872 std::string callee =
"func_" + callOp.getCallee().str();
874 if (funcOp.getSymName() == callee)
885 case CmpFPredicate::OEQ: {
886 info.logic = CombLogic::And;
887 info.inputPorts = {{Port::Eq,
false},
888 {Port::Unordered,
true}};
891 case CmpFPredicate::OGT: {
893 info.inputPorts = {{Port::Gt,
false},
894 {Port::Unordered,
true}};
897 case CmpFPredicate::OGE: {
899 info.inputPorts = {{Port::Lt,
true},
900 {Port::Unordered,
true}};
903 case CmpFPredicate::OLT: {
905 info.inputPorts = {{Port::Lt,
false},
906 {Port::Unordered,
true}};
909 case CmpFPredicate::OLE: {
911 info.inputPorts = {{Port::Gt,
true},
912 {Port::Unordered,
true}};
915 case CmpFPredicate::ONE: {
917 info.inputPorts = {{Port::Eq,
true},
918 {Port::Unordered,
true}};
921 case CmpFPredicate::ORD: {
923 info.inputPorts = {{Port::Unordered,
true}};
926 case CmpFPredicate::UEQ: {
928 info.inputPorts = {{Port::Eq,
false},
929 {Port::Unordered,
false}};
932 case CmpFPredicate::UGT: {
934 info.inputPorts = {{Port::Gt,
false},
935 {Port::Unordered,
false}};
938 case CmpFPredicate::UGE: {
940 info.inputPorts = {{Port::Lt,
true},
941 {Port::Unordered,
false}};
944 case CmpFPredicate::ULT: {
946 info.inputPorts = {{Port::Lt,
false},
947 {Port::Unordered,
false}};
950 case CmpFPredicate::ULE: {
952 info.inputPorts = {{Port::Gt,
true},
953 {Port::Unordered,
false}};
956 case CmpFPredicate::UNE: {
958 info.inputPorts = {{Port::Eq,
true},
959 {Port::Unordered,
false}};
962 case CmpFPredicate::UNO: {
964 info.inputPorts = {{Port::Unordered,
false}};
967 case CmpFPredicate::AlwaysTrue:
968 case CmpFPredicate::AlwaysFalse:
977 if (Operation *defOp = value.getDefiningOp()) {
978 auto cellOp = dyn_cast_or_null<calyx::CellInterface>(defOp);
979 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.