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"
27 using namespace mlir::arith;
33 Value memref,
unsigned memoryID,
34 SmallVectorImpl<calyx::PortInfo> &inPorts,
35 SmallVectorImpl<calyx::PortInfo> &outPorts) {
36 MemRefType memrefType = cast<MemRefType>(memref.getType());
41 auto getMemoryInterfaceAttr = [&](StringRef tag,
42 std::optional<unsigned> addrIdx = {}) {
43 auto attrs = SmallVector<NamedAttribute>{
45 rewriter.getNamedAttr(
"id", rewriter.getI32IntegerAttr(memoryID)),
47 rewriter.getNamedAttr(
"tag", rewriter.getStringAttr(tag))};
48 if (addrIdx.has_value())
51 attrs.push_back(rewriter.getNamedAttr(
52 "addr_idx", rewriter.getI32IntegerAttr(*addrIdx)));
54 return rewriter.getNamedAttr(
"mem", rewriter.getDictionaryAttr(attrs));
59 rewriter.getStringAttr(memName +
"_read_data"),
62 {getMemoryInterfaceAttr(
"read_data")})});
69 {getMemoryInterfaceAttr(
"done")})});
73 rewriter.getStringAttr(memName +
"_write_data"),
76 {getMemoryInterfaceAttr(
"write_data")})});
79 for (
auto dim : enumerate(memrefType.getShape())) {
81 rewriter.getStringAttr(memName +
"_addr" + std::to_string(dim.index())),
85 {getMemoryInterfaceAttr(
"addr", dim.index())})});
90 rewriter.getStringAttr(memName +
"_write_en"), rewriter.getI1Type(),
93 {getMemoryInterfaceAttr(
"write_en")})});
98 SmallVectorImpl<Attribute> &sourceLocations) {
99 Builder builder(component->getContext());
100 return component.getControlOp().walk([&](Operation *op) {
102 return WalkResult::advance();
104 std::string sourceLocation;
105 llvm::raw_string_ostream os(sourceLocation);
106 op->getLoc()->print(os);
107 int64_t position = sourceLocations.size();
108 sourceLocations.push_back(
111 op->setAttr(
"pos", builder.getI64IntegerAttr(position));
112 return WalkResult::advance();
117 return mlir::detail::constant_int_value_binder(&value).match(op);
121 return llvm::count_if(memoryReference.getUses(), [](OpOperand &user) {
122 return isa<mlir::memref::LoadOp>(user.getOwner());
127 return llvm::none_of(memoryReference.getUses(), [](OpOperand &user) {
128 return isa<mlir::memref::StoreOp>(user.getOwner());
133 size_t index = compOp.getInputPortInfo().size() + outPortIdx;
134 assert(index < compOp.getNumArguments() &&
135 "Exceeded number of arguments in the Component");
136 return compOp.getArgument(index);
141 return builder.getI32Type();
142 if (type.isIntOrFloat() && !type.isInteger())
143 return builder.getIntegerType(type.getIntOrFloatBitWidth());
148 calyx::GroupOp groupOp,
149 calyx::ComponentOp componentOp,
150 calyx::RegisterOp &
reg,
152 mlir::IRRewriter::InsertionGuard guard(builder);
153 auto loc = inputValue.getLoc();
154 builder.setInsertionPointToEnd(groupOp.getBodyBlock());
155 builder.create<calyx::AssignOp>(loc,
reg.getIn(), inputValue);
156 builder.create<calyx::AssignOp>(
158 builder.create<calyx::GroupDoneOp>(loc,
reg.getDone());
165 MemoryInterface::MemoryInterface() =
default;
182 assert(
readEn.has_value() &&
"Memory does not have readEn");
200 assert(
writeEn.has_value() &&
"Memory does not have writeEn");
206 assert(
done.has_value() &&
"Memory does not have done");
211 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
212 return memOp->getName().str();
215 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
216 return memOp->getName().str();
218 return std::get<MemoryPortsImpl>(
impl).memName;
222 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
223 return memOp->readData();
226 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
227 return memOp->readData();
229 return std::get<MemoryPortsImpl>(
impl).readData;
233 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
237 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
241 if (std::get<MemoryPortsImpl>(
impl).readOrContentEn.has_value()) {
242 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.has_value());
243 assert(!std::get<MemoryPortsImpl>(
impl).isContentEn.value());
245 return std::get<MemoryPortsImpl>(
impl).readOrContentEn;
249 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
253 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
254 return memOp->contentEn();
257 if (std::get<MemoryPortsImpl>(
impl).readOrContentEn.has_value()) {
259 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.has_value());
260 assert(std::get<MemoryPortsImpl>(
impl).isContentEn.value());
262 return std::get<MemoryPortsImpl>(
impl).readOrContentEn;
266 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
267 return memOp->writeData();
270 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
271 return memOp->writeData();
273 return std::get<MemoryPortsImpl>(
impl).writeData;
277 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
278 return memOp->writeEn();
281 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
282 return memOp->writeEn();
284 return std::get<MemoryPortsImpl>(
impl).writeEn;
288 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
289 return memOp->done();
292 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
293 return memOp->done();
295 return std::get<MemoryPortsImpl>(
impl).done;
299 if (
auto *memOp = std::get_if<calyx::MemoryOp>(&
impl); memOp) {
300 return memOp->addrPorts();
303 if (
auto *memOp = std::get_if<calyx::SeqMemoryOp>(&
impl); memOp) {
304 return memOp->addrPorts();
306 return std::get<MemoryPortsImpl>(
impl).addrPorts;
320 calyx::ComponentOp component)
321 : component(component) {}
330 calyx::RegisterOp
reg,
333 assert(idx < block->getArguments().size());
337 const DenseMap<unsigned, calyx::RegisterOp> &
343 calyx::GroupOp grp) {
347 ArrayRef<calyx::GroupOp>
353 std::string prefixStr = prefix.str();
356 return (prefix +
"_" + std::to_string(idx)).str();
361 assert(it !=
opNames.end() &&
"A unique name should have been set for op");
368 "A unique name was already set for op");
373 Value v, calyx::GroupInterface group) {
380 "A register was already registered for this index");
391 assert(isa<MemRefType>(memref.getType()));
393 "Memory already registered for memref");
399 assert(isa<MemRefType>(memref.getType()));
401 assert(it !=
memories.end() &&
"No memory registered for memref");
405 std::optional<calyx::MemoryInterface>
408 auto &mem = memIf.getSecond();
409 if (mem.writeEn() == v || mem.writeData() == v ||
410 llvm::any_of(mem.addrPorts(), [=](Value port) { return port == v; }))
417 const DenseMap<unsigned, unsigned> &mapping) {
422 unsigned funcReturnIdx) {
425 "No component return port index recorded for the requested function "
435 InstanceOp instanceOp) {
444 StringRef topLevelFunction)
445 : topLevelFunction(topLevelFunction), module(module) {}
469 StringRef topLevelFunction) {
471 if (moduleOp->hasAttr(
"calyx.entrypoint"))
474 moduleOp->setAttr(
"calyx.entrypoint",
484 MLIRContext *context, LogicalResult &resRef,
486 DenseMap<mlir::func::FuncOp, calyx::ComponentOp> &map,
489 functionMapping(map), calyxLoweringState(state) {}
493 PatternRewriter &rewriter)
const {
508 "Component operation should be set during pattern construction");
522 PatternRewriter &rewriter)
const {
523 funcOp.walk([&](Block *block) {
524 for (Value arg : block->getArguments())
528 funcOp.walk([&](Operation *op) {
529 for (Value result : op->getResults()) {
530 Type resType = result.getType();
531 if (!resType.isIndex())
534 result.setType(calyx::convIndexType(rewriter, resType));
535 auto constant = dyn_cast<mlir::arith::ConstantOp>(op);
540 calyx::matchConstantOp(constant, value);
541 rewriter.setInsertionPoint(constant);
542 rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
543 constant, rewriter.getI32IntegerAttr(value.getSExtValue()));
555 PatternRewriter &)
const {
556 Block *block = groupDoneOp->getBlock();
557 if (&block->back() == groupDoneOp)
560 groupDoneOp->moveBefore(groupDoneOp->getBlock(),
561 groupDoneOp->getBlock()->end());
571 PatternRewriter &rewriter)
const {
572 auto groupDoneOps = SmallVector<calyx::GroupDoneOp>(
573 groupOp.getBodyBlock()->getOps<calyx::GroupDoneOp>());
575 if (groupDoneOps.size() <= 1)
579 rewriter.setInsertionPointToEnd(groupDoneOps[0]->getBlock());
580 SmallVector<Value> doneOpSrcs;
581 llvm::transform(groupDoneOps, std::back_inserter(doneOpSrcs),
582 [](calyx::GroupDoneOp op) {
return op.getSrc(); });
583 Value allDone = rewriter.create<
comb::AndOp>(groupDoneOps.front().getLoc(),
587 rewriter.create<calyx::GroupDoneOp>(
589 rewriter.create<
hw::ConstantOp>(groupOp.getLoc(), APInt(1, 1)), allDone);
590 for (
auto groupDoneOp : groupDoneOps)
591 rewriter.eraseOp(groupDoneOp);
602 PatternRewriter &rewriter)
const {
604 combGroupOp->getParentOfType<calyx::ComponentOp>().getControlOp();
605 if (!SymbolTable::symbolKnownUseEmpty(combGroupOp.getSymNameAttr(), control))
608 rewriter.eraseOp(combGroupOp);
623 PatternRewriter &rewriter)
const {
624 auto component = originGroup->getParentOfType<calyx::ComponentOp>();
628 if (SymbolTable::symbolKnownUseEmpty(originGroup.symName(),
629 component.getControlOp()))
634 llvm::SmallSetVector<Operation *, 8> inlinedGroups;
635 inlinedGroups.insert(originGroup);
648 llvm::SmallSetVector<Operation *, 8> &inlinedGroups,
649 calyx::GroupInterface originGroup, calyx::GroupInterface recGroup,
650 bool doInline)
const {
651 inlinedGroups.insert(recGroup);
652 for (
auto assignOp : recGroup.getBody()->getOps<calyx::AssignOp>()) {
655 auto *clonedAssignOp = rewriter.clone(*assignOp.getOperation());
656 clonedAssignOp->moveBefore(originGroup.getBody(),
657 originGroup.getBody()->end());
659 Value src = assignOp.getSrc();
671 if (isa<BlockArgument>(src) ||
672 isa<calyx::RegisterOp, calyx::MemoryOp, calyx::SeqMemoryOp,
674 calyx::DivUPipeLibOp, calyx::DivSPipeLibOp, calyx::RemSPipeLibOp,
675 calyx::RemUPipeLibOp, mlir::scf::WhileOp, calyx::InstanceOp,
676 calyx::ConstantOp, calyx::AddFOpIEEE754, calyx::MulFOpIEEE754>(
677 src.getDefiningOp()))
680 auto srcCombGroup = dyn_cast<calyx::CombGroupOp>(
684 if (inlinedGroups.count(srcCombGroup))
698 PatternRewriter &rewriter)
const {
699 auto *state =
cls.
getState(assignOp->getParentOfType<calyx::ComponentOp>());
701 Value dest = assignOp.getDest();
702 if (!state->isInputPortOfMemory(dest))
705 Value src = assignOp.getSrc();
706 unsigned srcBits = src.getType().getIntOrFloatBitWidth();
707 unsigned dstBits = dest.getType().getIntOrFloatBitWidth();
708 if (srcBits == dstBits)
711 SmallVector<Type> types = {
712 rewriter.getIntegerType(srcBits),
713 rewriter.getIntegerType(dstBits),
715 mlir::Location loc = assignOp.getLoc();
717 if (srcBits > dstBits)
719 state->getNewLibraryOpInstance<calyx::SliceLibOp>(rewriter, loc, types);
722 state->getNewLibraryOpInstance<calyx::PadLibOp>(rewriter, loc, types);
724 rewriter.setInsertionPoint(assignOp->getBlock(),
725 assignOp->getBlock()->begin());
726 rewriter.create<calyx::AssignOp>(assignOp->getLoc(), newOp->getResult(0),
728 assignOp.setOperand(1, newOp->getResult(1));
739 PatternRewriter &rewriter)
const {
740 funcOp.walk([&](Block *block) {
742 if (block == &block->getParent()->front())
745 for (
auto arg : enumerate(block->getArguments())) {
746 Type argType = arg.value().getType();
747 assert(isa<IntegerType>(argType) &&
"unsupported block argument type");
748 unsigned width = argType.getIntOrFloatBitWidth();
749 std::string index = std::to_string(arg.index());
750 std::string name = loweringState().blockName(block) +
"_arg" + index;
751 auto reg = createRegister(arg.value().getLoc(), rewriter, getComponent(),
753 getState().addBlockArgReg(block, reg, arg.index());
754 arg.value().replaceAllUsesWith(reg.getOut());
766 PatternRewriter &rewriter)
const {
768 for (
auto argType : enumerate(funcOp.getResultTypes())) {
770 assert((isa<IntegerType>(convArgType) || isa<FloatType>(convArgType)) &&
771 "unsupported return type");
772 std::string name =
"ret_arg" + std::to_string(argType.index());
774 convArgType.getIntOrFloatBitWidth(), name);
777 rewriter.setInsertionPointToStart(
779 rewriter.create<calyx::AssignOp>(
794 PatternRewriter &rewriter)
const {
795 funcOp.walk([&](mlir::func::CallOp callOp) {
797 SmallVector<Type, 8> resultTypes;
799 resultTypes.push_back(type);
801 resultTypes.push_back(type);
807 if (!
getState().getInstance(instanceName)) {
808 InstanceOp instanceOp =
811 getState().addInstance(instanceName, instanceOp);
814 OpBuilder::InsertionGuard g(rewriter);
815 rewriter.setInsertionPointToStart(
819 calyx::GroupOp groupOp = rewriter.create<calyx::GroupOp>(
820 callOp.getLoc(),
"init_" + instanceName);
821 rewriter.setInsertionPointToStart(groupOp.getBodyBlock());
822 auto portInfos = instanceOp.getReferencedComponent().getPortInfo();
823 auto results = instanceOp.getResults();
824 for (
const auto &[portInfo, result] : llvm::zip(portInfos, results)) {
826 rewriter.create<calyx::AssignOp>(callOp.getLoc(), result, constantOp);
827 else if (portInfo.hasAttribute(
donePort))
828 rewriter.create<calyx::GroupDoneOp>(callOp.getLoc(), result);
831 WalkResult::advance();
838 std::string callee =
"func_" + callOp.getCallee().str();
840 if (funcOp.getSymName() == callee)
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)
T * getState(calyx::ComponentOp op)
Returns the component lowering state associated with op.
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.
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.
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.
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...
~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
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
void appendPortsForExternalMemref(PatternRewriter &rewriter, StringRef memName, Value memref, unsigned memoryID, SmallVectorImpl< calyx::PortInfo > &inPorts, SmallVectorImpl< calyx::PortInfo > &outPorts)
static constexpr std::string_view donePort
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...
bool isControlLeafNode(Operation *op)
Type convIndexType(OpBuilder &builder, Type type)
LogicalResult applyModuleOpConversion(mlir::ModuleOp, StringRef topLevelFunction)
Helper to update the top-level ModuleOp to set the entrypoing function.
static constexpr std::string_view resetPort
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.
static constexpr std::string_view goPort
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.
def reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)
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.