19 #include "mlir/IR/DialectImplementation.h"
20 #include "mlir/IR/OpDefinition.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/TypeSwitch.h"
25 using namespace circt;
26 using namespace chirrtl;
27 using namespace firrtl;
34 NamedAttrList &resultAttrs) {
36 auto result = parser.parseOptionalAttrDict(resultAttrs);
37 if (!resultAttrs.get(
"annotations"))
38 resultAttrs.append(
"annotations", parser.getBuilder().getArrayAttr({}));
42 if (resultAttrs.get(
"name"))
45 auto resultName = parser.getResultName(0).first;
46 if (!resultName.empty() &&
isdigit(resultName[0]))
48 auto nameAttr = parser.getBuilder().getStringAttr(resultName);
49 auto *context = parser.getBuilder().getContext();
54 static void printCHIRRTLOp(OpAsmPrinter &p, Operation *op, DictionaryAttr attr,
55 ArrayRef<StringRef> extraElides = {}) {
56 SmallVector<StringRef> elides(extraElides.begin(), extraElides.end());
59 elides.push_back(hw::InnerSymbolTable::getInnerSymbolAttrName());
64 SmallString<32> resultNameStr;
65 llvm::raw_svector_ostream tmpStream(resultNameStr);
66 p.printOperand(op->getResult(0), tmpStream);
67 auto actualName = tmpStream.str().drop_front();
68 auto expectedName = op->getAttrOfType<StringAttr>(
"name").getValue();
70 if (actualName == expectedName ||
71 (expectedName.empty() &&
isdigit(actualName[0])))
72 elides.push_back(
"name");
73 elides.push_back(
"nameKind");
76 if (op->getAttrOfType<ArrayAttr>(
"annotations").empty())
77 elides.push_back(
"annotations");
79 p.printOptionalAttrDict(op->getAttrs(), elides);
87 firrtl::NameKindEnumAttr &result) {
90 if (!parser.parseOptionalKeyword(&keyword,
91 {
"interesting_name",
"droppable_name"})) {
92 auto kind = symbolizeNameKindEnum(keyword);
104 firrtl::NameKindEnumAttr attr,
105 ArrayRef<StringRef> extraElides = {}) {
106 if (attr.getValue() != NameKindEnum::DroppableName)
107 p <<
" " << stringifyNameKindEnum(attr.getValue());
114 void MemoryPortOp::build(OpBuilder &
builder, OperationState &result,
115 Type dataType, Value memory, MemDirAttr direction,
116 StringRef name, ArrayRef<Attribute> annotations) {
118 memory, direction, name,
builder.getArrayAttr(annotations));
122 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
123 DictionaryAttr attrs, mlir::OpaqueProperties properties,
124 mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
125 auto inType = operands[0].getType();
126 auto memType = type_dyn_cast<CMemoryType>(inType);
129 mlir::emitError(*loc,
"memory port requires memory operand");
132 results.push_back(memType.getElementType());
137 LogicalResult MemoryPortOp::verify() {
141 return emitOpError(
"port should be used by a chirrtl.memoryport.access");
145 MemoryPortAccessOp MemoryPortOp::getAccess() {
146 auto uses =
getPort().use_begin();
147 if (uses ==
getPort().use_end())
149 return cast<MemoryPortAccessOp>(uses->getOwner());
153 function_ref<
void(Value, StringRef)> setNameFn) {
157 setNameFn(getData(), (base +
"_data").str());
158 setNameFn(
getPort(), (base +
"_port").str());
162 NamedAttrList &resultAttrs) {
164 auto result = parser.parseOptionalAttrDict(resultAttrs);
165 if (!resultAttrs.get(
"annotations"))
166 resultAttrs.append(
"annotations", parser.getBuilder().getArrayAttr({}));
173 DictionaryAttr attr) {
175 SmallVector<StringRef> elides = {
"direction"};
177 if (op->getAttrOfType<ArrayAttr>(
"annotations").empty())
178 elides.push_back(
"annotations");
179 p.printOptionalAttrDict(op->getAttrs(), elides);
186 void MemoryDebugPortOp::build(OpBuilder &
builder, OperationState &result,
187 Type dataType, Value memory, StringRef name,
188 ArrayRef<Attribute> annotations) {
189 build(
builder, result, dataType, memory, name,
190 builder.getArrayAttr(annotations));
194 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
195 DictionaryAttr attrs, mlir::OpaqueProperties properties,
196 mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
197 auto inType = operands[0].getType();
198 auto memType = type_dyn_cast<CMemoryType>(inType);
201 mlir::emitError(*loc,
"memory port requires memory operand");
210 function_ref<
void(Value, StringRef)> setNameFn) {
214 setNameFn(getData(), (base +
"_data").str());
218 NamedAttrList &resultAttrs) {
220 auto result = parser.parseOptionalAttrDict(resultAttrs);
221 if (!resultAttrs.get(
"annotations"))
222 resultAttrs.append(
"annotations", parser.getBuilder().getArrayAttr({}));
229 DictionaryAttr attr) {
230 SmallVector<StringRef, 1> elides;
232 if (op->getAttrOfType<ArrayAttr>(
"annotations").empty())
233 elides.push_back(
"annotations");
234 p.printOptionalAttrDict(op->getAttrs(), elides);
242 NamedAttrList &resultAttrs) {
247 DictionaryAttr attr) {
251 void CombMemOp::build(OpBuilder &
builder, OperationState &result,
253 StringRef name, NameKindEnum nameKind,
254 ArrayAttr annotations, StringAttr innerSym,
255 MemoryInitAttr init) {
258 nameKind, annotations,
263 setNameFn(getResult(),
getName());
266 std::optional<size_t> CombMemOp::getTargetResultIndex() {
276 NamedAttrList &resultAttrs) {
281 static void printSeqMemOp(OpAsmPrinter &p, Operation *op, DictionaryAttr attr) {
285 void SeqMemOp::build(OpBuilder &
builder, OperationState &result,
287 RUWAttr ruw, StringRef name, NameKindEnum nameKind,
288 ArrayAttr annotations, StringAttr innerSym,
289 MemoryInitAttr init) {
292 name, nameKind, annotations,
297 setNameFn(getResult(),
getName());
300 std::optional<size_t> SeqMemOp::getTargetResultIndex() {
312 struct CHIRRTLOpAsmDialectInterface :
public OpAsmDialectInterface {
313 using OpAsmDialectInterface::OpAsmDialectInterface;
317 if (op->getNumResults() == 1)
318 if (
auto nameAttr = op->getAttrOfType<StringAttr>(
"name"))
319 setNameFn(op->getResult(0), nameAttr.getValue());
324 #define GET_TYPEDEF_CLASSES
325 #include "circt/Dialect/FIRRTL/CHIRRTLTypes.cpp.inc"
327 #define GET_OP_CLASSES
328 #include "circt/Dialect/FIRRTL/CHIRRTL.cpp.inc"
330 void CHIRRTLDialect::initialize() {
334 #include "circt/Dialect/FIRRTL/CHIRRTL.cpp.inc"
339 #define GET_TYPEDEF_LIST
340 #include "circt/Dialect/FIRRTL/CHIRRTLTypes.cpp.inc"
344 addInterfaces<CHIRRTLOpAsmDialectInterface>();
347 #include "circt/Dialect/FIRRTL/CHIRRTLDialect.cpp.inc"
353 void CMemoryType::print(AsmPrinter &printer)
const {
357 printer <<
", " << getNumElements() <<
">";
360 Type CMemoryType::parse(AsmParser &parser) {
364 parser.parseComma() || parser.parseInteger(
numElements) ||
365 parser.parseGreater())
370 LogicalResult CMemoryType::verify(function_ref<InFlightDiagnostic()> emitError,
374 return emitError() <<
"behavioral memory element type must be passive";
static void printSeqMemOp(OpAsmPrinter &p, Operation *op, DictionaryAttr attr)
Always elide "ruw" and elide "annotations" if it exists or if it is empty.
static void printNameKind(OpAsmPrinter &p, Operation *op, firrtl::NameKindEnumAttr attr, ArrayRef< StringRef > extraElides={})
static void printCHIRRTLOp(OpAsmPrinter &p, Operation *op, DictionaryAttr attr, ArrayRef< StringRef > extraElides={})
static ParseResult parseMemoryDebugPortOp(OpAsmParser &parser, NamedAttrList &resultAttrs)
static ParseResult parseNameKind(OpAsmParser &parser, firrtl::NameKindEnumAttr &result)
static void printMemoryPortOp(OpAsmPrinter &p, Operation *op, DictionaryAttr attr)
Always elide "direction" and elide "annotations" if it exists or if it is empty.
static ParseResult parseSeqMemOp(OpAsmParser &parser, NamedAttrList &resultAttrs)
static ParseResult parseCombMemOp(OpAsmParser &parser, NamedAttrList &resultAttrs)
static ParseResult parseCHIRRTLOp(OpAsmParser &parser, NamedAttrList &resultAttrs)
static void printCombMemOp(OpAsmPrinter &p, Operation *op, DictionaryAttr attr)
static void printMemoryDebugPortOp(OpAsmPrinter &p, Operation *op, DictionaryAttr attr)
Always elide "direction" and elide "annotations" if it exists or if it is empty.
static ParseResult parseMemoryPortOp(OpAsmParser &parser, NamedAttrList &resultAttrs)
MlirType uint64_t numElements
static PortInfo getPort(ModuleTy &mod, size_t idx)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
LogicalResult inferReturnTypes(MLIRContext *context, std::optional< Location > loc, ValueRange operands, DictionaryAttr attrs, mlir::OpaqueProperties properties, mlir::RegionRange regions, SmallVectorImpl< Type > &results, llvm::function_ref< FIRRTLType(ValueRange, ArrayRef< NamedAttribute >, std::optional< Location >)> callback)
ParseResult parseNestedBaseType(FIRRTLBaseType &result, AsmParser &parser)
void printNestedType(Type type, AsmPrinter &os)
Print a type defined by this dialect.
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
void getAsmResultNames(OpAsmSetValueNameFn setNameFn, StringRef instanceName, ArrayAttr resultNames, ValueRange results)
Suggest a name for each result value based on the saved result names attribute.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn