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) {
466 StringRef topLevelFunction)
467 : topLevelFunction(topLevelFunction), module(module) {}
470 assert(module.getOperation() !=
nullptr);
491 StringRef topLevelFunction) {
493 if (moduleOp->hasAttr(
"calyx.entrypoint"))
496 moduleOp->setAttr(
"calyx.entrypoint",
497 StringAttr::get(moduleOp.getContext(), topLevelFunction));
506 MLIRContext *context, LogicalResult &resRef,
508 DenseMap<mlir::func::FuncOp, calyx::ComponentOp> &map,
511 functionMapping(map), calyxLoweringState(state) {}
515 PatternRewriter &rewriter)
const {
530 "Component operation should be set during pattern construction");
544 PatternRewriter &rewriter)
const {
545 funcOp.walk([&](Block *block) {
546 for (Value arg : block->getArguments())
550 funcOp.walk([&](Operation *op) {
551 for (Value result : op->getResults()) {
552 Type resType = result.getType();
553 if (!resType.isIndex())
557 auto constant = dyn_cast<mlir::arith::ConstantOp>(op);
563 rewriter.setInsertionPoint(constant);
564 rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
565 constant, rewriter.getI32IntegerAttr(value.getSExtValue()));
577 PatternRewriter &)
const {
578 Block *block = groupDoneOp->getBlock();
579 if (&block->back() == groupDoneOp)
582 groupDoneOp->moveBefore(groupDoneOp->getBlock(),
583 groupDoneOp->getBlock()->end());
593 PatternRewriter &rewriter)
const {
594 auto groupDoneOps = SmallVector<calyx::GroupDoneOp>(
595 groupOp.getBodyBlock()->getOps<calyx::GroupDoneOp>());
597 if (groupDoneOps.size() <= 1)
601 rewriter.setInsertionPointToEnd(groupDoneOps[0]->getBlock());
602 SmallVector<Value> doneOpSrcs;
603 llvm::transform(groupDoneOps, std::back_inserter(doneOpSrcs),
604 [](calyx::GroupDoneOp op) {
return op.getSrc(); });
605 Value allDone = rewriter.create<
comb::AndOp>(groupDoneOps.front().getLoc(),
609 rewriter.create<calyx::GroupDoneOp>(
611 rewriter.create<
hw::ConstantOp>(groupOp.getLoc(), APInt(1, 1)), allDone);
612 for (
auto groupDoneOp : groupDoneOps)
613 rewriter.eraseOp(groupDoneOp);
624 PatternRewriter &rewriter)
const {
626 combGroupOp->getParentOfType<calyx::ComponentOp>().getControlOp();
627 if (!SymbolTable::symbolKnownUseEmpty(combGroupOp.getSymNameAttr(), control))
630 rewriter.eraseOp(combGroupOp);
640 PatternRewriter &rewriter)
const {
641 return deduplicateParallelOperation<calyx::ParOp>(parOp, rewriter);
646 PatternRewriter &rewriter)
const {
647 return deduplicateParallelOperation<calyx::StaticParOp>(parOp, rewriter);
661 PatternRewriter &rewriter)
const {
662 auto component = originGroup->getParentOfType<calyx::ComponentOp>();
666 if (SymbolTable::symbolKnownUseEmpty(originGroup.symName(),
667 component.getControlOp()))
672 llvm::SmallSetVector<Operation *, 8> inlinedGroups;
673 inlinedGroups.insert(originGroup);
686 llvm::SmallSetVector<Operation *, 8> &inlinedGroups,
687 calyx::GroupInterface originGroup, calyx::GroupInterface recGroup,
688 bool doInline)
const {
689 inlinedGroups.insert(recGroup);
690 for (
auto assignOp : recGroup.getBody()->getOps<calyx::AssignOp>()) {
693 auto *clonedAssignOp = rewriter.clone(*assignOp.getOperation());
694 clonedAssignOp->moveBefore(originGroup.getBody(),
695 originGroup.getBody()->end());
697 Value src = assignOp.getSrc();
709 if (isa<BlockArgument>(src) ||
710 isa<calyx::RegisterOp, calyx::MemoryOp, calyx::SeqMemoryOp,
712 calyx::DivUPipeLibOp, calyx::DivSPipeLibOp, calyx::RemSPipeLibOp,
713 calyx::RemUPipeLibOp, mlir::scf::WhileOp, calyx::InstanceOp,
714 calyx::ConstantOp, calyx::AddFOpIEEE754, calyx::MulFOpIEEE754,
715 calyx::CompareFOpIEEE754>(src.getDefiningOp()))
718 auto srcCombGroup = dyn_cast<calyx::CombGroupOp>(
722 if (inlinedGroups.count(srcCombGroup))
736 PatternRewriter &rewriter)
const {
737 auto *state =
cls.
getState(assignOp->getParentOfType<calyx::ComponentOp>());
739 Value dest = assignOp.getDest();
740 if (!state->isInputPortOfMemory(dest))
743 Value src = assignOp.getSrc();
744 unsigned srcBits = src.getType().getIntOrFloatBitWidth();
745 unsigned dstBits = dest.getType().getIntOrFloatBitWidth();
746 if (srcBits == dstBits)
749 SmallVector<Type> types = {
750 rewriter.getIntegerType(srcBits),
751 rewriter.getIntegerType(dstBits),
753 mlir::Location loc = assignOp.getLoc();
755 if (srcBits > dstBits)
757 state->getNewLibraryOpInstance<calyx::SliceLibOp>(rewriter, loc, types);
760 state->getNewLibraryOpInstance<calyx::PadLibOp>(rewriter, loc, types);
762 rewriter.setInsertionPoint(assignOp->getBlock(),
763 assignOp->getBlock()->begin());
764 rewriter.create<calyx::AssignOp>(assignOp->getLoc(), newOp->getResult(0),
766 assignOp.setOperand(1, newOp->getResult(1));
777 PatternRewriter &rewriter)
const {
778 funcOp.walk([&](Block *block) {
780 if (block == &block->getParent()->front())
783 for (
auto arg : enumerate(block->getArguments())) {
784 Type argType = arg.value().getType();
785 assert(isa<IntegerType>(argType) &&
"unsupported block argument type");
786 unsigned width = argType.getIntOrFloatBitWidth();
787 std::string index = std::to_string(arg.index());
791 getState().addBlockArgReg(block, reg, arg.index());
792 arg.value().replaceAllUsesWith(reg.getOut());
804 PatternRewriter &rewriter)
const {
806 for (
auto argType : enumerate(funcOp.getResultTypes())) {
808 assert((isa<IntegerType>(convArgType) || isa<FloatType>(convArgType)) &&
809 "unsupported return type");
810 std::string name =
"ret_arg" + std::to_string(argType.index());
812 convArgType.getIntOrFloatBitWidth(), name);
813 getState().addReturnReg(reg, argType.index());
815 rewriter.setInsertionPointToStart(
817 rewriter.create<calyx::AssignOp>(
832 PatternRewriter &rewriter)
const {
833 funcOp.walk([&](mlir::func::CallOp callOp) {
835 SmallVector<Type, 8> resultTypes;
837 resultTypes.push_back(type);
839 resultTypes.push_back(type);
845 if (!
getState().getInstance(instanceName)) {
846 InstanceOp instanceOp =
849 getState().addInstance(instanceName, instanceOp);
851 WalkResult::advance();
858 std::string callee =
"func_" + callOp.getCallee().str();
860 if (funcOp.getSymName() == callee)
871 case CmpFPredicate::OEQ: {
872 info.
logic = CombLogic::And;
874 {Port::Unordered,
true}};
877 case CmpFPredicate::OGT: {
880 {Port::Unordered,
true}};
883 case CmpFPredicate::OGE: {
886 {Port::Unordered,
true}};
889 case CmpFPredicate::OLT: {
892 {Port::Unordered,
true}};
895 case CmpFPredicate::OLE: {
898 {Port::Unordered,
true}};
901 case CmpFPredicate::ONE: {
904 {Port::Unordered,
true}};
907 case CmpFPredicate::ORD: {
912 case CmpFPredicate::UEQ: {
915 {Port::Unordered,
false}};
918 case CmpFPredicate::UGT: {
921 {Port::Unordered,
false}};
924 case CmpFPredicate::UGE: {
927 {Port::Unordered,
false}};
930 case CmpFPredicate::ULT: {
933 {Port::Unordered,
false}};
936 case CmpFPredicate::ULE: {
939 {Port::Unordered,
false}};
942 case CmpFPredicate::UNE: {
945 {Port::Unordered,
false}};
948 case CmpFPredicate::UNO: {
953 case CmpFPredicate::AlwaysTrue:
954 case CmpFPredicate::AlwaysFalse:
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.
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
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.
SmallVector< InputPorts > inputPorts