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"
25using namespace mlir::arith;
30template <
typename OpTy>
32 PatternRewriter &rewriter) {
33 auto *body = parOp.getBodyBlock();
34 if (body->getOperations().size() < 2)
37 LogicalResult result = LogicalResult::failure();
38 SetVector<StringRef> members;
39 for (
auto &op : make_early_inc_range(*body)) {
40 auto enableOp = dyn_cast<EnableOp>(&op);
41 if (enableOp ==
nullptr)
43 bool inserted = members.insert(enableOp.getGroupName());
45 rewriter.eraseOp(enableOp);
46 result = LogicalResult::success();
53 Value memref,
unsigned memoryID,
54 SmallVectorImpl<calyx::PortInfo> &inPorts,
55 SmallVectorImpl<calyx::PortInfo> &outPorts) {
56 MemRefType memrefType = cast<MemRefType>(memref.getType());
61 auto getMemoryInterfaceAttr = [&](StringRef tag,
62 std::optional<unsigned> addrIdx = {}) {
63 auto attrs = SmallVector<NamedAttribute>{
65 rewriter.getNamedAttr(
"id", rewriter.getI32IntegerAttr(memoryID)),
67 rewriter.getNamedAttr(
"tag", rewriter.getStringAttr(tag))};
68 if (addrIdx.has_value())
71 attrs.push_back(rewriter.getNamedAttr(
72 "addr_idx", rewriter.getI32IntegerAttr(*addrIdx)));
74 return rewriter.getNamedAttr(
"mem", rewriter.getDictionaryAttr(
attrs));
79 rewriter.getStringAttr(memName +
"_read_data"),
81 DictionaryAttr::get(rewriter.getContext(),
82 {getMemoryInterfaceAttr(
"read_data")})});
88 DictionaryAttr::get(rewriter.getContext(),
89 {getMemoryInterfaceAttr(
"done")})});
93 rewriter.getStringAttr(memName +
"_write_data"),
95 DictionaryAttr::get(rewriter.getContext(),
96 {getMemoryInterfaceAttr(
"write_data")})});
99 for (
auto dim : enumerate(memrefType.getShape())) {
101 rewriter.getStringAttr(memName +
"_addr" + std::to_string(dim.index())),
104 DictionaryAttr::get(rewriter.getContext(),
105 {getMemoryInterfaceAttr(
"addr", dim.index())})});
110 rewriter.getStringAttr(memName +
"_write_en"), rewriter.getI1Type(),
112 DictionaryAttr::get(rewriter.getContext(),
113 {getMemoryInterfaceAttr(
"write_en")})});
118 SmallVectorImpl<Attribute> &sourceLocations) {
119 Builder builder(component->getContext());
120 return component.getControlOp().walk([&](Operation *op) {
122 return WalkResult::advance();
124 std::string sourceLocation;
125 llvm::raw_string_ostream os(sourceLocation);
126 op->getLoc()->print(os);
127 int64_t position = sourceLocations.size();
128 sourceLocations.push_back(
129 StringAttr::get(op->getContext(), sourceLocation));
131 op->setAttr(
"pos", builder.getI64IntegerAttr(position));
132 return WalkResult::advance();
137 return mlir::detail::constant_int_value_binder(&value).match(op);
141 return llvm::count_if(memoryReference.getUses(), [](OpOperand &user) {
142 return isa<mlir::memref::LoadOp>(user.getOwner());
147 return llvm::none_of(memoryReference.getUses(), [](OpOperand &user) {
148 return isa<mlir::memref::StoreOp>(user.getOwner());
153 size_t index = compOp.getInputPortInfo().size() + outPortIdx;
154 assert(index < compOp.getNumArguments() &&
155 "Exceeded number of arguments in the Component");
156 return compOp.getArgument(index);
161 return builder.getI32Type();
162 if (type.isIntOrFloat())
168 calyx::GroupOp groupOp,
169 calyx::ComponentOp componentOp,
170 calyx::RegisterOp ®,
172 mlir::IRRewriter::InsertionGuard guard(builder);
173 auto loc = inputValue.getLoc();
174 builder.setInsertionPointToEnd(groupOp.getBodyBlock());
175 calyx::AssignOp::create(builder, loc, reg.getIn(), inputValue);
176 calyx::AssignOp::create(builder, loc, reg.getWriteEn(),
178 calyx::GroupDoneOp::create(builder, loc, reg.getDone());
188 assert(ports.isContentEn.value());
202 assert(
readEn.has_value() &&
"Memory does not have readEn");
220 assert(
writeEn.has_value() &&
"Memory does not have writeEn");
226 assert(
done.has_value() &&
"Memory does not have done");
231 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
232 return memOp->instanceName().str();
235 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
236 return memOp->instanceName().str();
238 return std::get<MemoryPortsImpl>(
impl).memName;
242 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
243 return memOp->readData();
246 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
247 return memOp->readData();
249 return std::get<MemoryPortsImpl>(
impl).readData;
253 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
257 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
261 if (std::get<MemoryPortsImpl>(
impl).readOrContentEn.has_value()) {
262 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.has_value());
263 assert(!std::get<MemoryPortsImpl>(
impl).isContentEn.value());
265 return std::get<MemoryPortsImpl>(
impl).readOrContentEn;
269 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
273 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
274 return memOp->contentEn();
277 if (std::get<MemoryPortsImpl>(
impl).readOrContentEn.has_value()) {
279 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.has_value());
280 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.value());
282 return std::get<MemoryPortsImpl>(
impl).readOrContentEn;
286 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
287 return memOp->writeData();
290 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
291 return memOp->writeData();
293 return std::get<MemoryPortsImpl>(
impl).writeData;
297 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
298 return memOp->writeEn();
301 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
302 return memOp->writeEn();
304 return std::get<MemoryPortsImpl>(
impl).writeEn;
308 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
309 return memOp->done();
312 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
313 return memOp->done();
315 return std::get<MemoryPortsImpl>(
impl).done;
319 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
320 return memOp->addrPorts();
323 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
324 return memOp->addrPorts();
326 return std::get<MemoryPortsImpl>(
impl).addrPorts;
350 calyx::RegisterOp reg,
353 assert(idx < block->getArguments().size());
357const DenseMap<unsigned, calyx::RegisterOp> &
363 calyx::GroupOp grp) {
367ArrayRef<calyx::GroupOp>
373 std::string prefixStr = prefix.str();
376 return (prefix +
"_" + std::to_string(idx)).str();
381 assert(it !=
opNames.end() &&
"A unique name should have been set for op");
388 "A unique name was already set for op");
393 Value v, calyx::GroupInterface group) {
400 "A register was already registered for this index");
411 assert(isa<MemRefType>(memref.getType()));
413 "Memory already registered for memref");
419 assert(isa<MemRefType>(memref.getType()));
421 assert(it !=
memories.end() &&
"No memory registered for memref");
425std::optional<calyx::MemoryInterface>
428 auto &mem = memIf.getSecond();
429 if (mem.writeEn() == v || mem.writeData() == v ||
430 llvm::any_of(mem.addrPorts(), [=](Value port) { return port == v; }))
437 const DenseMap<unsigned, unsigned> &mapping) {
442 unsigned funcReturnIdx) {
445 "No component return port index recorded for the requested function "
455 InstanceOp instanceOp) {
497 StringRef topLevelFunction) {
499 if (moduleOp->hasAttr(
"calyx.entrypoint"))
502 moduleOp->setAttr(
"calyx.entrypoint",
503 StringAttr::get(moduleOp.getContext(), topLevelFunction));
512 MLIRContext *
context, LogicalResult &resRef,
514 DenseMap<mlir::func::FuncOp, calyx::ComponentOp> &map,
521 PatternRewriter &rewriter)
const {
536 "Component operation should be set during pattern construction");
550 PatternRewriter &rewriter)
const {
551 funcOp.walk([&](Block *block) {
552 for (Value arg : block->getArguments())
556 funcOp.walk([&](Operation *op) {
557 for (Value result : op->getResults()) {
558 Type resType = result.getType();
559 if (!resType.isIndex())
563 auto constant = dyn_cast<mlir::arith::ConstantOp>(op);
569 rewriter.setInsertionPoint(constant);
570 rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
571 constant, rewriter.getI32IntegerAttr(value.getSExtValue()));
583 PatternRewriter &)
const {
584 Block *block = groupDoneOp->getBlock();
585 if (&block->back() == groupDoneOp)
588 groupDoneOp->moveBefore(groupDoneOp->getBlock(),
589 groupDoneOp->getBlock()->end());
599 PatternRewriter &rewriter)
const {
600 auto groupDoneOps = SmallVector<calyx::GroupDoneOp>(
601 groupOp.getBodyBlock()->getOps<calyx::GroupDoneOp>());
603 if (groupDoneOps.size() <= 1)
607 rewriter.setInsertionPointToEnd(groupDoneOps[0]->getBlock());
608 SmallVector<Value> doneOpSrcs;
609 llvm::transform(groupDoneOps, std::back_inserter(doneOpSrcs),
610 [](calyx::GroupDoneOp op) {
return op.getSrc(); });
611 Value allDone = comb::AndOp::create(rewriter, groupDoneOps.front().getLoc(),
615 calyx::GroupDoneOp::create(
616 rewriter, groupOp.getLoc(),
618 for (
auto groupDoneOp : groupDoneOps)
619 rewriter.eraseOp(groupDoneOp);
630 PatternRewriter &rewriter)
const {
632 combGroupOp->getParentOfType<calyx::ComponentOp>().getControlOp();
633 if (!SymbolTable::symbolKnownUseEmpty(combGroupOp.getSymNameAttr(), control))
636 rewriter.eraseOp(combGroupOp);
646 PatternRewriter &rewriter)
const {
652 PatternRewriter &rewriter)
const {
667 PatternRewriter &rewriter)
const {
668 auto component = originGroup->getParentOfType<calyx::ComponentOp>();
672 if (SymbolTable::symbolKnownUseEmpty(originGroup.symName(),
673 component.getControlOp()))
679 inlinedGroups.insert(originGroup);
693 calyx::GroupInterface originGroup, calyx::GroupInterface recGroup,
694 bool doInline)
const {
695 inlinedGroups.insert(recGroup);
696 for (
auto assignOp : recGroup.getBody()->getOps<calyx::AssignOp>()) {
699 auto *clonedAssignOp = rewriter.clone(*assignOp.getOperation());
700 clonedAssignOp->moveBefore(originGroup.getBody(),
701 originGroup.getBody()->end());
703 Value src = assignOp.getSrc();
715 if (isa<BlockArgument>(src) ||
716 isa<calyx::RegisterOp, calyx::MemoryOp, calyx::SeqMemoryOp,
718 calyx::DivUPipeLibOp, calyx::DivSPipeLibOp, calyx::RemSPipeLibOp,
719 calyx::RemUPipeLibOp, mlir::scf::WhileOp, calyx::InstanceOp,
720 calyx::ConstantOp, calyx::AddFOpIEEE754, calyx::MulFOpIEEE754,
721 calyx::CompareFOpIEEE754, calyx::FpToIntOpIEEE754,
722 calyx::IntToFpOpIEEE754, calyx::DivSqrtOpIEEE754>(
723 src.getDefiningOp()))
730 auto srcCombGroup = dyn_cast<calyx::CombGroupOp>(
734 if (inlinedGroups.count(srcCombGroup))
748 PatternRewriter &rewriter)
const {
749 auto *state =
cls.getState(assignOp->getParentOfType<calyx::ComponentOp>());
751 Value dest = assignOp.getDest();
752 if (!state->isInputPortOfMemory(dest))
755 Value src = assignOp.getSrc();
756 unsigned srcBits = src.getType().getIntOrFloatBitWidth();
757 unsigned dstBits = dest.getType().getIntOrFloatBitWidth();
758 if (srcBits == dstBits)
761 SmallVector<Type> types = {
762 rewriter.getIntegerType(srcBits),
763 rewriter.getIntegerType(dstBits),
765 mlir::Location loc = assignOp.getLoc();
767 if (srcBits > dstBits)
769 state->getNewLibraryOpInstance<calyx::SliceLibOp>(rewriter, loc, types);
772 state->getNewLibraryOpInstance<calyx::PadLibOp>(rewriter, loc, types);
774 rewriter.setInsertionPoint(assignOp->getBlock(),
775 assignOp->getBlock()->begin());
776 calyx::AssignOp::create(rewriter, assignOp->getLoc(), newOp->getResult(0),
778 assignOp.setOperand(1, newOp->getResult(1));
789 PatternRewriter &rewriter)
const {
790 funcOp.walk([&](Block *block) {
792 if (block == &block->getParent()->front())
795 for (
auto arg : enumerate(block->getArguments())) {
796 Type argType = arg.value().getType();
797 assert(isa<IntegerType>(argType) &&
"unsupported block argument type");
798 unsigned width = argType.getIntOrFloatBitWidth();
799 std::string index = std::to_string(arg.index());
803 getState().addBlockArgReg(block, reg, arg.index());
804 rewriter.replaceAllUsesWith(arg.value(), reg.getOut());
816 PatternRewriter &rewriter)
const {
818 for (
auto argType : enumerate(funcOp.getResultTypes())) {
820 assert((isa<IntegerType>(convArgType) || isa<FloatType>(convArgType)) &&
821 "unsupported return type");
822 std::string name =
"ret_arg" + std::to_string(argType.index());
824 convArgType.getIntOrFloatBitWidth(), name);
825 getState().addReturnReg(reg, argType.index());
827 rewriter.setInsertionPointToStart(
829 calyx::AssignOp::create(
830 rewriter, funcOp->getLoc(),
844 PatternRewriter &rewriter)
const {
845 funcOp.walk([&](mlir::func::CallOp callOp) {
847 SmallVector<Type, 8> resultTypes;
849 resultTypes.push_back(type);
851 resultTypes.push_back(type);
857 if (!
getState().getInstance(instanceName)) {
858 InstanceOp instanceOp =
861 getState().addInstance(instanceName, instanceOp);
863 WalkResult::advance();
870 std::string callee =
"func_" + callOp.getCallee().str();
872 if (funcOp.getSymName() == callee)
883 case CmpFPredicate::OEQ: {
884 info.logic = CombLogic::And;
885 info.inputPorts = {{Port::Eq,
false},
886 {Port::Unordered,
true}};
889 case CmpFPredicate::OGT: {
891 info.inputPorts = {{Port::Gt,
false},
892 {Port::Unordered,
true}};
895 case CmpFPredicate::OGE: {
897 info.inputPorts = {{Port::Lt,
true},
898 {Port::Unordered,
true}};
901 case CmpFPredicate::OLT: {
903 info.inputPorts = {{Port::Lt,
false},
904 {Port::Unordered,
true}};
907 case CmpFPredicate::OLE: {
909 info.inputPorts = {{Port::Gt,
true},
910 {Port::Unordered,
true}};
913 case CmpFPredicate::ONE: {
915 info.inputPorts = {{Port::Eq,
true},
916 {Port::Unordered,
true}};
919 case CmpFPredicate::ORD: {
921 info.inputPorts = {{Port::Unordered,
true}};
924 case CmpFPredicate::UEQ: {
926 info.inputPorts = {{Port::Eq,
false},
927 {Port::Unordered,
false}};
930 case CmpFPredicate::UGT: {
932 info.inputPorts = {{Port::Gt,
false},
933 {Port::Unordered,
false}};
936 case CmpFPredicate::UGE: {
938 info.inputPorts = {{Port::Lt,
true},
939 {Port::Unordered,
false}};
942 case CmpFPredicate::ULT: {
944 info.inputPorts = {{Port::Lt,
false},
945 {Port::Unordered,
false}};
948 case CmpFPredicate::ULE: {
950 info.inputPorts = {{Port::Gt,
true},
951 {Port::Unordered,
false}};
954 case CmpFPredicate::UNE: {
956 info.inputPorts = {{Port::Eq,
true},
957 {Port::Unordered,
false}};
960 case CmpFPredicate::UNO: {
962 info.inputPorts = {{Port::Unordered,
false}};
965 case CmpFPredicate::AlwaysTrue:
966 case CmpFPredicate::AlwaysFalse:
975 if (Operation *defOp = value.getDefiningOp()) {
976 auto cellOp = dyn_cast_or_null<calyx::CellInterface>(defOp);
977 return cellOp && !cellOp.isCombinational();
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
false return failure()
Parse an optional keyword or string and set instance into 'result'.
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.
mlir::ModuleOp module
The program associated with this state.
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.
llvm::json::Value extMemData
A json file to store external global memory data.
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
PatternApplicationState & patternState
PartialLoweringPattern(MLIRContext *ctx, LogicalResult &resRef, PatternApplicationState &patternState)
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
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.