17#include "mlir/IR/Attributes.h"
18#include "mlir/IR/DialectImplementation.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/TypeSwitch.h"
26AnyType AnyType::get(MLIRContext *context) {
return Base::get(context); }
31 return llvm::make_filter_range(chan.getUses(), [](
auto &use) {
32 return !isa<SnoopValidReadyOp>(use.getOwner());
35SmallVector<std::reference_wrapper<OpOperand>, 4>
36ChannelType::getConsumers(mlir::TypedValue<ChannelType> chan) {
37 return SmallVector<std::reference_wrapper<OpOperand>, 4>(
40bool ChannelType::hasOneConsumer(mlir::TypedValue<ChannelType> chan) {
42 if (consumers.empty())
44 return ++consumers.begin() == consumers.end();
46bool ChannelType::hasNoConsumers(mlir::TypedValue<ChannelType> chan) {
49OpOperand *ChannelType::getSingleConsumer(mlir::TypedValue<ChannelType> chan) {
51 auto iter = consumers.begin();
52 if (iter == consumers.end())
54 OpOperand *result = &*iter;
55 if (++iter != consumers.end())
59LogicalResult ChannelType::verifyChannel(mlir::TypedValue<ChannelType> chan) {
61 if (consumers.empty() || ++consumers.begin() == consumers.end())
63 auto err = chan.getDefiningOp()->emitOpError(
64 "channels must have at most one consumer");
65 for (
auto &consumer : consumers)
66 err.attachNote(consumer.getOwner()->getLoc()) <<
"channel used here";
71WindowType::verify(llvm::function_ref<InFlightDiagnostic()> emitError,
72 StringAttr name, Type into,
73 ArrayRef<WindowFrameType> frames) {
74 auto structInto = hw::type_dyn_cast<hw::StructType>(into);
76 return emitError() <<
"only windows into structs are currently supported";
78 auto fields = structInto.getElements();
79 for (
auto frame : frames) {
81 DenseMap<StringAttr, WindowFieldType> frameFields;
82 for (
auto field : frame.getMembers())
87 while (!fields.empty() && !frameFields.empty()) {
88 hw::StructType::FieldInfo field = fields.front();
89 fields = fields.drop_front();
90 auto f = frameFields.find(field.name);
94 if (f == frameFields.end())
98 uint64_t numItems = f->getSecond().getNumItems();
100 auto arrField = hw::type_dyn_cast<hw::ArrayType>(field.type);
102 return emitError() <<
"cannot specify num items on non-array field "
104 if (numItems > arrField.getNumElements())
105 return emitError() <<
"num items is larger than array size in field "
107 if (frame.getMembers().size() != 1)
109 <<
"array with size specified must be in their own frame (in "
110 << field.name <<
")";
112 frameFields.erase(f);
118 if (!frameFields.empty())
119 return emitError() <<
"invalid field name: "
120 << frameFields.begin()->getSecond().getFieldName();
125hw::UnionType WindowType::getLoweredType()
const {
127 auto into = hw::type_cast<hw::StructType>(getInto());
129 for (hw::StructType::FieldInfo field : into.getElements())
130 intoFields[field.name] = field.type;
133 SmallVector<hw::UnionType::FieldInfo, 4> unionFields;
134 for (WindowFrameType frame : getFrames()) {
137 SmallVector<hw::StructType::FieldInfo, 4> fields;
138 for (WindowFieldType field : frame.getMembers()) {
139 auto fieldTypeIter = intoFields.find(field.getFieldName());
140 assert(fieldTypeIter != intoFields.end());
143 if (field.getNumItems() == 0) {
144 fields.push_back({field.getFieldName(), fieldTypeIter->getSecond()});
148 auto array = hw::type_cast<hw::ArrayType>(fieldTypeIter->getSecond());
153 {field.getFieldName(),
154 hw::ArrayType::get(array.getElementType(), field.getNumItems())});
155 unionFields.push_back(
156 {frame.getName(), hw::StructType::get(getContext(), fields), 0});
161 size_t leftOver = array.getNumElements() % field.getNumItems();
164 {field.getFieldName(),
165 hw::ArrayType::get(array.getElementType(), leftOver)});
167 unionFields.push_back(
168 {StringAttr::get(getContext(),
169 Twine(frame.getName().getValue(),
"_leftOver")),
170 hw::StructType::get(getContext(), fields), 0});
177 unionFields.push_back(
178 {frame.getName(), hw::StructType::get(getContext(), fields), 0});
181 return hw::UnionType::get(getContext(), unionFields);
187 static FailureOr<::BundledChannel>
parse(AsmParser &p) {
190 if (p.parseType(type))
192 auto dir = FieldParser<::ChannelDirection>::parse(p);
195 if (p.parseKeywordOrString(&name))
197 return BundledChannel{StringAttr::get(p.getContext(), name), *dir, type};
203inline ::llvm::raw_ostream &
operator<<(::llvm::raw_ostream &p,
210ChannelBundleType ChannelBundleType::getReversed()
const {
211 SmallVector<BundledChannel, 4> reversed;
212 for (
auto channel : getChannels())
213 reversed.push_back({channel.name,
flip(channel.direction), channel.type});
214 return ChannelBundleType::get(getContext(), reversed, getResettable());
217#define GET_TYPEDEF_CLASSES
218#include "circt/Dialect/ESI/ESITypes.cpp.inc"
220void ESIDialect::registerTypes() {
222#define GET_TYPEDEF_LIST
223#include "circt/Dialect/ESI/ESITypes.cpp.inc"
228 circt::esi::ChannelType chan =
229 dyn_cast_or_null<circt::esi::ChannelType>(type);
231 type = chan.getInner();
assert(baseType &&"element must be base type")
static auto getChannelConsumers(mlir::TypedValue< ChannelType > chan)
Get the list of users with snoops filtered out.
static bool getFieldName(const FieldRef &fieldRef, SmallString< 32 > &string)
mlir::Type innerType(mlir::Type type)
ModulePort::Direction flip(ModulePort::Direction direction)
Flip a port direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
inline ::llvm::raw_ostream & operator<<(::llvm::raw_ostream &p, ::BundledChannel channel)
ChannelDirection direction
static FailureOr<::BundledChannel > parse(AsmParser &p)