25 #include "mlir/IR/BuiltinOps.h"
26 #include "mlir/IR/BuiltinTypes.h"
27 #include "mlir/IR/Diagnostics.h"
28 #include "mlir/IR/ImplicitLocOpBuilder.h"
29 #include "mlir/IR/PatternMatch.h"
30 #include "mlir/IR/Threading.h"
31 #include "mlir/IR/Verifier.h"
32 #include "mlir/Support/Timing.h"
33 #include "mlir/Tools/mlir-translate/Translation.h"
34 #include "llvm/ADT/PointerEmbeddedInt.h"
35 #include "llvm/ADT/STLExtras.h"
36 #include "llvm/ADT/SmallPtrSet.h"
37 #include "llvm/ADT/StringExtras.h"
38 #include "llvm/ADT/StringSet.h"
39 #include "llvm/ADT/StringSwitch.h"
40 #include "llvm/ADT/TypeSwitch.h"
41 #include "llvm/Support/JSON.h"
42 #include "llvm/Support/SourceMgr.h"
43 #include "llvm/Support/raw_ostream.h"
47 using namespace circt;
48 using namespace firrtl;
49 using namespace chirrtl;
52 using llvm::SourceMgr;
53 using mlir::LocationAttr;
66 struct SharedParserConstants {
68 : context(context), options(options),
69 emptyArrayAttr(ArrayAttr::
get(context, {})),
80 MLIRContext *
const context;
86 llvm::StringMap<FIRRTLType> aliasMap;
89 llvm::DenseMap<StringRef, ClassLike> classMap;
92 const ArrayAttr emptyArrayAttr;
95 const StringAttr loIdentifier, hiIdentifier, amountIdentifier;
96 const StringAttr fieldIndexIdentifier, indexIdentifier;
99 const hw::InnerRefAttr placeholderInnerRef;
102 SharedParserConstants(
const SharedParserConstants &) =
delete;
103 void operator=(
const SharedParserConstants &) =
delete;
116 FIRParser(SharedParserConstants &constants,
FIRLexer &lexer,
118 : version(version), constants(constants), lexer(lexer),
119 locatorFilenameCache(constants.loIdentifier ) {
123 SharedParserConstants &getConstants()
const {
return constants; }
124 MLIRContext *getContext()
const {
return constants.context; }
126 FIRLexer &getLexer() {
return lexer; }
129 std::optional<unsigned> getIndentation()
const {
134 const FIRToken &getToken()
const {
return lexer.getToken(); }
135 StringRef getTokenSpelling()
const {
return getToken().
getSpelling(); }
142 InFlightDiagnostic emitError(
const Twine &message = {}) {
143 return emitError(getToken().getLoc(), message);
145 InFlightDiagnostic emitError(SMLoc loc,
const Twine &message = {});
148 InFlightDiagnostic emitWarning(
const Twine &message = {}) {
149 return emitWarning(getToken().getLoc(), message);
152 InFlightDiagnostic emitWarning(SMLoc loc,
const Twine &message = {});
162 Location translateLocation(llvm::SMLoc loc) {
163 return lexer.translateLocation(loc);
168 ParseResult parseOptionalInfoLocator(LocationAttr &result);
172 ParseResult parseOptionalName(StringAttr &name);
178 ParseResult requireFeature(
FIRVersion minimum, StringRef feature) {
179 return requireFeature(minimum, feature, getToken().getLoc());
182 ParseResult requireFeature(
FIRVersion minimum, StringRef feature, SMLoc loc) {
183 if (version < minimum)
184 return emitError(loc)
185 << feature <<
" are a FIRRTL " << minimum
186 <<
"+ feature, but the specified FIRRTL version was " << version;
190 ParseResult removedFeature(
FIRVersion removedVersion, StringRef feature) {
191 return removedFeature(removedVersion, feature, getToken().getLoc());
194 ParseResult removedFeature(
FIRVersion removedVersion, StringRef feature,
196 if (version >= removedVersion)
197 return emitError(loc)
198 << feature <<
" were removed in FIRRTL " << removedVersion
199 <<
", but the specified FIRRTL version was " << version;
209 ParseResult parseOptionalAnnotations(SMLoc &loc, StringRef &result);
218 if (getToken().isNot(kind))
228 FIRToken consumedToken = getToken();
229 assert(consumedToken.
isNot(FIRToken::eof, FIRToken::error) &&
230 "shouldn't advance past EOF or errors");
232 return consumedToken;
241 FIRToken consumedToken = getToken();
242 assert(consumedToken.
is(kind) &&
"consumed an unexpected token");
244 return consumedToken;
249 ParseResult parseGetSpelling(StringRef &spelling) {
250 spelling = getTokenSpelling();
256 ParseResult parseToken(
FIRToken::Kind expectedToken,
const Twine &message);
261 const std::function<ParseResult()> &parseElement);
268 ParseResult parseIntLit(APInt &result,
const Twine &message);
269 ParseResult parseIntLit(int64_t &result,
const Twine &message);
270 ParseResult parseIntLit(int32_t &result,
const Twine &message);
273 ParseResult parseVersionLit(
const Twine &message);
276 template <
typename T>
277 ParseResult parseOptionalWidth(T &result);
280 ParseResult parseId(StringRef &result,
const Twine &message);
281 ParseResult parseId(StringAttr &result,
const Twine &message);
282 ParseResult parseFieldId(StringRef &result,
const Twine &message);
283 ParseResult parseFieldIdSeq(SmallVectorImpl<StringRef> &result,
284 const Twine &message);
285 ParseResult parseEnumType(
FIRRTLType &result);
286 ParseResult parseListType(
FIRRTLType &result);
289 ParseResult parsePropertyType(
PropertyType &result,
const Twine &message);
291 ParseResult parseRUW(RUWAttr &result);
292 ParseResult parseOptionalRUW(RUWAttr &result);
294 ParseResult parseParameter(StringAttr &resultName, TypedAttr &resultValue,
301 FIRParser(
const FIRParser &) =
delete;
302 void operator=(
const FIRParser &) =
delete;
306 SharedParserConstants &constants;
310 StringAttr locatorFilenameCache;
312 FileLineColLoc fileLineColLocCache;
321 InFlightDiagnostic FIRParser::emitError(SMLoc loc,
const Twine &message) {
322 auto diag = mlir::emitError(translateLocation(loc), message);
326 if (getToken().is(FIRToken::error))
331 InFlightDiagnostic FIRParser::emitWarning(SMLoc loc,
const Twine &message) {
332 return mlir::emitWarning(translateLocation(loc), message);
342 const Twine &message) {
343 if (consumeIf(expectedToken))
345 return emitError(message);
352 const std::function<ParseResult()> &parseElement) {
353 if (consumeIf(rightToken))
359 while (consumeIf(FIRToken::comma)) {
364 if (parseToken(rightToken,
"expected ','"))
381 : parser(parser), firLoc(firLoc) {}
388 auto result = parser->translateLocation(firLoc);
396 if (failed(parser->parseOptionalInfoLocator(loc)))
400 switch (parser->constants.options.infoLocatorHandling) {
401 case ILH::IgnoreInfo:
402 assert(0 &&
"Should not return info locations if ignoring");
404 case ILH::PreferInfo:
409 {loc, parser->translateLocation(firLoc)});
436 ParseResult FIRParser::parseOptionalInfoLocator(LocationAttr &result) {
437 if (getToken().isNot(FIRToken::fileinfo))
440 auto loc = getToken().getLoc();
442 auto spelling = getTokenSpelling();
443 consumeToken(FIRToken::fileinfo);
447 constants.options.infoLocatorHandling ==
449 locatorFilenameCache, fileLineColLocCache, getContext());
452 if (!locationPair.first) {
453 mlir::emitWarning(translateLocation(loc),
454 "ignoring unknown @ info record format");
460 if (locationPair.first && constants.options.infoLocatorHandling ==
465 result = *locationPair.second;
473 ParseResult FIRParser::parseOptionalName(StringAttr &name) {
475 if (getToken().isNot(FIRToken::colon)) {
480 consumeToken(FIRToken::colon);
482 if (parseId(nameRef,
"expected result name"))
496 ParseResult FIRParser::parseOptionalAnnotations(SMLoc &loc, StringRef &result) {
498 if (getToken().isNot(FIRToken::inlineannotation))
501 loc = getToken().getLoc();
503 result = getTokenSpelling().drop_front(2).drop_back(1);
504 consumeToken(FIRToken::inlineannotation);
522 ParseResult FIRParser::parseIntLit(APInt &result,
const Twine &message) {
523 auto spelling = getTokenSpelling();
524 bool isNegative =
false;
525 switch (getToken().getKind()) {
526 case FIRToken::signed_integer:
527 isNegative = spelling[0] ==
'-';
528 assert(spelling[0] ==
'+' || spelling[0] ==
'-');
529 spelling = spelling.drop_front();
531 case FIRToken::integer:
532 if (spelling.getAsInteger(10, result))
533 return emitError(message), failure();
537 if (result.isNegative())
538 result = result.zext(result.getBitWidth() + 1);
547 if (result.getBitWidth() > 32 && result.getSignificantBits() <= 32)
548 result = result.trunc(32);
552 case FIRToken::radix_specified_integer: {
553 if (requireFeature({2, 4, 0},
"radix-specified integer literals"))
555 if (spelling[0] ==
'-') {
557 spelling = spelling.drop_front();
559 unsigned base = llvm::StringSwitch<unsigned>(spelling.take_front(2))
564 spelling = spelling.drop_front(2);
565 if (spelling.getAsInteger(base, result))
566 return emitError(
"invalid character in integer literal"), failure();
567 if (result.isNegative())
568 result = result.zext(result.getBitWidth() + 1);
574 case FIRToken::string: {
577 "String-encoded integer literals are unsupported after FIRRTL 3.0.0");
580 assert(spelling.front() ==
'"' && spelling.back() ==
'"');
581 spelling = spelling.drop_back().drop_front();
585 switch (spelling.empty() ?
' ' : spelling.front()) {
596 return emitError(
"expected base specifier (h/o/b) in integer literal"),
599 spelling = spelling.drop_front();
602 bool isNegative =
false;
603 if (!spelling.empty() && spelling.front() ==
'+')
604 spelling = spelling.drop_front();
605 else if (!spelling.empty() && spelling.front() ==
'-') {
607 spelling = spelling.drop_front();
611 if (spelling.empty())
612 return emitError(
"expected digits in integer literal"), failure();
614 if (spelling.getAsInteger(base, result))
615 return emitError(
"invalid character in integer literal"), failure();
620 if (result.isNegative())
621 result = result.zext(result.getBitWidth() + 1);
626 consumeToken(FIRToken::string);
631 return emitError(
"expected integer literal"), failure();
635 ParseResult FIRParser::parseIntLit(int64_t &result,
const Twine &message) {
637 auto loc = getToken().getLoc();
638 if (parseIntLit(value, message))
641 result = (int64_t)value.getLimitedValue(INT64_MAX);
643 return emitError(loc,
"value is too big to handle"), failure();
647 ParseResult FIRParser::parseIntLit(int32_t &result,
const Twine &message) {
649 auto loc = getToken().getLoc();
650 if (parseIntLit(value, message))
653 result = (int32_t)value.getLimitedValue(INT32_MAX);
655 return emitError(loc,
"value is too big to handle"), failure();
661 ParseResult FIRParser::parseVersionLit(
const Twine &message) {
662 auto spelling = getTokenSpelling();
663 if (getToken().getKind() != FIRToken::version)
664 return emitError(message), failure();
666 auto [a, d] = spelling.split(
".");
667 auto [b, c] = d.split(
".");
668 APInt aInt, bInt, cInt;
669 if (a.getAsInteger(10, aInt) || b.getAsInteger(10, bInt) ||
670 c.getAsInteger(10, cInt))
671 return emitError(
"failed to parse version string"), failure();
672 version.major = aInt.getLimitedValue(UINT32_MAX);
673 version.minor = bInt.getLimitedValue(UINT32_MAX);
674 version.patch = cInt.getLimitedValue(UINT32_MAX);
675 if (version.major != aInt || version.minor != bInt || version.patch != cInt)
676 return emitError(
"integers out of range"), failure();
680 consumeToken(FIRToken::version);
687 template <
typename T>
688 ParseResult FIRParser::parseOptionalWidth(T &result) {
689 if (!consumeIf(FIRToken::less))
690 return result = -1, success();
693 auto widthLoc = getToken().getLoc();
694 if (parseIntLit(result,
"expected width") ||
695 parseToken(FIRToken::greater,
"expected >"))
699 return emitError(widthLoc,
"invalid width specifier"), failure();
708 ParseResult FIRParser::parseId(StringRef &result,
const Twine &message) {
709 switch (getToken().getKind()) {
711 case FIRToken::identifier:
712 case FIRToken::literal_identifier:
714 #define TOK_KEYWORD(spelling) case FIRToken::kw_##spelling:
715 #include "FIRTokenKinds.def"
720 if (getToken().getKind() == FIRToken::literal_identifier)
721 result = getTokenSpelling().drop_front().drop_back();
723 result = getTokenSpelling();
733 ParseResult FIRParser::parseId(StringAttr &result,
const Twine &message) {
735 if (parseId(name, message))
747 ParseResult FIRParser::parseFieldId(StringRef &result,
const Twine &message) {
749 result = getTokenSpelling();
750 if (consumeIf(FIRToken::integer))
756 if (parseId(result, message))
768 ParseResult FIRParser::parseFieldIdSeq(SmallVectorImpl<StringRef> &result,
769 const Twine &message) {
771 StringRef tmp = getTokenSpelling();
773 if (consumeIf(FIRToken::integer)) {
774 result.push_back(tmp);
778 if (consumeIf(FIRToken::floatingpoint)) {
782 auto [a, b] = tmp.split(
".");
788 if (consumeIf(FIRToken::version)) {
790 auto [a, d] = tmp.split(
".");
791 auto [b, c] = d.split(
".");
799 if (parseId(tmp, message))
801 result.push_back(tmp);
807 ParseResult FIRParser::parseEnumType(
FIRRTLType &result) {
808 if (parseToken(FIRToken::l_brace_bar,
809 "expected leading '{|' in enumeration type"))
811 SmallVector<FEnumType::EnumElement> elements;
812 if (parseListUntil(FIRToken::r_brace_bar, [&]() -> ParseResult {
813 auto fieldLoc = getToken().getLoc();
817 if (parseId(name,
"expected valid identifier for enumeration tag"))
822 if (consumeIf(FIRToken::colon)) {
824 if (
parseType(parsedType,
"expected enumeration type"))
826 type = type_dyn_cast<FIRRTLBaseType>(parsedType);
828 return emitError(fieldLoc,
"field must be a base type");
841 ParseResult FIRParser::parsePropertyType(
PropertyType &result,
842 const Twine &message) {
846 auto prop = type_dyn_cast<PropertyType>(type);
848 return emitError(
"expected property type");
854 ParseResult FIRParser::parseListType(
FIRRTLType &result) {
855 consumeToken(FIRToken::kw_List);
858 if (parseToken(FIRToken::less,
"expected '<' in List type") ||
859 parsePropertyType(
elementType,
"expected List element type") ||
860 parseToken(FIRToken::greater,
"expected '>' in List type"))
886 switch (getToken().getKind()) {
888 return emitError(message), failure();
890 case FIRToken::kw_Clock:
891 consumeToken(FIRToken::kw_Clock);
895 case FIRToken::kw_Inst: {
899 consumeToken(FIRToken::kw_Inst);
900 if (parseToken(FIRToken::less,
"expected < in Inst type"))
903 auto loc = getToken().getLoc();
905 if (parseId(
id,
"expected class name in Inst type"))
909 const auto &classMap = getConstants().classMap;
910 auto lookup = classMap.find(
id);
911 if (lookup == classMap.end())
912 return emitError(loc) <<
"unknown class '" <<
id <<
"'";
914 auto classOp = lookup->second;
916 if (parseToken(FIRToken::greater,
"expected > in Inst type"))
919 result = classOp.getInstanceType();
923 case FIRToken::kw_AnyRef: {
927 consumeToken(FIRToken::kw_AnyRef);
932 case FIRToken::kw_Reset:
933 consumeToken(FIRToken::kw_Reset);
937 case FIRToken::kw_AsyncReset:
938 consumeToken(FIRToken::kw_AsyncReset);
942 case FIRToken::kw_UInt:
943 case FIRToken::kw_SInt:
944 case FIRToken::kw_Analog: {
945 auto kind = getToken().getKind();
950 if (parseOptionalWidth(
width))
953 if (kind == FIRToken::kw_SInt)
955 else if (kind == FIRToken::kw_UInt)
958 assert(kind == FIRToken::kw_Analog);
964 case FIRToken::kw_Probe:
965 case FIRToken::kw_RWProbe: {
966 auto kind = getToken().getKind();
967 auto loc = getToken().getLoc();
972 if (parseToken(FIRToken::less,
"expected '<' in reference type") ||
973 parseType(type,
"expected probe data type"))
976 SmallVector<StringRef> layers;
977 if (consumeIf(FIRToken::comma)) {
978 if (requireFeature({3, 2, 0},
"colored probes"))
983 loc = getToken().getLoc();
984 if (parseId(layer,
"expected layer name"))
986 layers.push_back(layer);
987 }
while (consumeIf(FIRToken::period));
990 if (!consumeIf(FIRToken::greater))
991 return emitError(loc,
"expected '>' to end reference type");
993 bool forceable = kind == FIRToken::kw_RWProbe;
995 auto innerType = type_dyn_cast<FIRRTLBaseType>(type);
997 return emitError(loc,
"invalid probe inner type, must be base-type");
1000 return emitError(loc,
"probe inner type must be passive");
1002 if (forceable &&
innerType.containsConst())
1003 return emitError(loc,
"rwprobe cannot contain const");
1005 SymbolRefAttr layer;
1006 if (!layers.empty()) {
1008 llvm::map_range(ArrayRef(layers).drop_front(), [&](StringRef a) {
1012 llvm::to_vector(nestedLayers));
1019 case FIRToken::l_brace: {
1020 consumeToken(FIRToken::l_brace);
1022 SmallVector<OpenBundleType::BundleElement, 4> elements;
1023 bool bundleCompatible =
true;
1024 if (parseListUntil(FIRToken::r_brace, [&]() -> ParseResult {
1025 bool isFlipped = consumeIf(FIRToken::kw_flip);
1027 StringRef fieldName;
1029 if (parseFieldId(fieldName,
"expected bundle field name") ||
1030 parseToken(FIRToken::colon,
"expected ':' in bundle"))
1032 if (
parseType(type,
"expected bundle field type"))
1037 bundleCompatible &= isa<BundleType::ElementType>(type);
1044 if (bundleCompatible) {
1045 auto bundleElements = llvm::map_range(elements, [](
auto element) {
1046 return BundleType::BundleElement{
1047 element.name, element.isFlip,
1048 cast<BundleType::ElementType>(element.type)};
1050 result =
BundleType::get(getContext(), llvm::to_vector(bundleElements));
1056 case FIRToken::l_brace_bar: {
1057 if (parseEnumType(result))
1062 case FIRToken::identifier: {
1064 auto loc = getToken().getLoc();
1065 if (parseId(
id,
"expected a type alias name"))
1067 auto it = constants.aliasMap.find(
id);
1068 if (it == constants.aliasMap.end()) {
1069 emitError(loc) <<
"type identifier `" <<
id <<
"` is not declared";
1072 result = it->second;
1076 case FIRToken::kw_const: {
1077 consumeToken(FIRToken::kw_const);
1078 auto nextToken = getToken();
1079 auto loc = nextToken.getLoc();
1082 if (nextToken.is(FIRToken::kw_const))
1083 return emitError(loc,
"'const' can only be specified once on a type");
1088 auto baseType = type_dyn_cast<FIRRTLBaseType>(result);
1090 return emitError(loc,
"only hardware types can be 'const'");
1092 result = baseType.getConstType(
true);
1096 case FIRToken::kw_String:
1097 if (requireFeature({3, 1, 0},
"Strings"))
1099 consumeToken(FIRToken::kw_String);
1102 case FIRToken::kw_Integer:
1103 if (requireFeature({3, 1, 0},
"Integers"))
1105 consumeToken(FIRToken::kw_Integer);
1108 case FIRToken::kw_Bool:
1111 consumeToken(FIRToken::kw_Bool);
1114 case FIRToken::kw_Double:
1117 consumeToken(FIRToken::kw_Double);
1120 case FIRToken::kw_Path:
1123 consumeToken(FIRToken::kw_Path);
1126 case FIRToken::kw_List:
1127 if (requireFeature(
nextFIRVersion,
"Lists") || parseListType(result))
1133 while (consumeIf(FIRToken::l_square)) {
1134 auto sizeLoc = getToken().getLoc();
1136 if (parseIntLit(size,
"expected width") ||
1137 parseToken(FIRToken::r_square,
"expected ]"))
1141 return emitError(sizeLoc,
"invalid size specifier"), failure();
1143 auto baseType = type_dyn_cast<FIRRTLBaseType>(result);
1154 ParseResult FIRParser::parseRUW(RUWAttr &result) {
1155 switch (getToken().getKind()) {
1157 case FIRToken::kw_old:
1158 result = RUWAttr::Old;
1159 consumeToken(FIRToken::kw_old);
1161 case FIRToken::kw_new:
1162 result = RUWAttr::New;
1163 consumeToken(FIRToken::kw_new);
1165 case FIRToken::kw_undefined:
1166 result = RUWAttr::Undefined;
1167 consumeToken(FIRToken::kw_undefined);
1177 ParseResult FIRParser::parseOptionalRUW(RUWAttr &result) {
1178 switch (getToken().getKind()) {
1182 case FIRToken::kw_old:
1183 result = RUWAttr::Old;
1184 consumeToken(FIRToken::kw_old);
1186 case FIRToken::kw_new:
1187 result = RUWAttr::New;
1188 consumeToken(FIRToken::kw_new);
1190 case FIRToken::kw_undefined:
1191 result = RUWAttr::Undefined;
1192 consumeToken(FIRToken::kw_undefined);
1203 ParseResult FIRParser::parseParameter(StringAttr &resultName,
1204 TypedAttr &resultValue,
1206 mlir::Builder builder(getContext());
1208 auto loc = getToken().getLoc();
1211 if (parseId(name,
"expected parameter name") ||
1212 parseToken(FIRToken::equal,
"expected '=' in parameter"))
1216 switch (getToken().getKind()) {
1218 return emitError(
"expected parameter value"), failure();
1219 case FIRToken::integer:
1220 case FIRToken::signed_integer: {
1222 if (parseIntLit(result,
"invalid integer parameter"))
1228 if (result.getBitWidth() < 32)
1229 result = result.sext(32);
1231 value = builder.getIntegerAttr(
1232 builder.getIntegerType(result.getBitWidth(), result.isSignBitSet()),
1236 case FIRToken::string: {
1238 value = builder.getStringAttr(getToken().getStringValue());
1239 consumeToken(FIRToken::string);
1242 case FIRToken::verbatim_string: {
1244 auto text = builder.getStringAttr(getToken().getVerbatimStringValue());
1246 consumeToken(FIRToken::verbatim_string);
1249 case FIRToken::floatingpoint:
1251 if (!llvm::to_float(getTokenSpelling(), v))
1252 return emitError(
"invalid float parameter syntax"), failure();
1254 value = builder.getF64FloatAttr(v);
1255 consumeToken(FIRToken::floatingpoint);
1259 resultName = builder.getStringAttr(name);
1260 resultValue = value;
1276 llvm::StringMap<std::pair<SMLoc, SymbolValueEntry>, llvm::BumpPtrAllocator>;
1284 struct UnbundledValueRestorer {
1286 size_t startingSize;
1288 startingSize = list.size();
1290 ~UnbundledValueRestorer() { list.resize(startingSize); }
1299 struct FIRModuleContext :
public FIRParser {
1300 explicit FIRModuleContext(SharedParserConstants &constants,
FIRLexer &lexer,
1302 : FIRParser(constants, lexer, version) {}
1308 llvm::DenseMap<std::pair<Attribute, Type>, Value> constantCache;
1311 template <
typename OpTy = ConstantOp,
typename... Args>
1312 Value getCachedConstant(ImplicitLocOpBuilder &builder, Attribute attr,
1313 Type type, Args &&...args) {
1314 auto &result = constantCache[{attr, type}];
1320 OpBuilder::InsertPoint savedIP;
1322 auto *parentOp = builder.getInsertionBlock()->getParentOp();
1323 if (!isa<FModuleLike>(parentOp)) {
1324 savedIP = builder.saveInsertionPoint();
1325 while (!isa<FModuleLike>(parentOp)) {
1326 builder.setInsertionPoint(parentOp);
1327 parentOp = builder.getInsertionBlock()->getParentOp();
1331 result = builder.create<OpTy>(type, std::forward<Args>(args)...);
1333 if (savedIP.isSet())
1334 builder.setInsertionPoint(savedIP.getBlock(), savedIP.getPoint());
1345 Value &getCachedSubaccess(Value value,
unsigned index) {
1346 auto &result = subaccessCache[{value, index}];
1349 auto it = scopeMap.find(value.getParentBlock());
1350 if (it != scopeMap.end())
1351 it->second->scopedSubaccesses.push_back({result, index});
1361 ParseResult addSymbolEntry(StringRef name,
SymbolValueEntry entry, SMLoc loc,
1362 bool insertNameIntoGlobalScope =
false);
1363 ParseResult addSymbolEntry(StringRef name, Value value, SMLoc loc,
1364 bool insertNameIntoGlobalScope =
false) {
1366 insertNameIntoGlobalScope);
1371 SMLoc loc,
bool fatal =
true);
1376 StringRef field, SMLoc loc);
1384 assert(index < unbundledValues.size());
1385 return unbundledValues[index];
1395 struct ContextScope {
1396 friend struct FIRModuleContext;
1397 ContextScope(FIRModuleContext &moduleContext, Block *block)
1398 : moduleContext(moduleContext), block(block),
1399 previousScope(moduleContext.currentScope) {
1400 moduleContext.currentScope =
this;
1401 moduleContext.scopeMap[block] =
this;
1406 for (
auto *entryPtr : scopedDecls)
1407 entryPtr->second.first = SMLoc();
1410 for (
auto subaccess : scopedSubaccesses)
1411 moduleContext.subaccessCache.erase(subaccess);
1413 moduleContext.scopeMap.erase(block);
1415 moduleContext.currentScope = previousScope;
1419 void operator=(
const ContextScope &) =
delete;
1420 ContextScope(
const ContextScope &) =
delete;
1422 FIRModuleContext &moduleContext;
1424 ContextScope *previousScope;
1425 std::vector<ModuleSymbolTableEntry *> scopedDecls;
1426 std::vector<std::pair<Value, unsigned>> scopedSubaccesses;
1440 DenseMap<Block *, ContextScope *> scopeMap;
1445 ContextScope *currentScope =
nullptr;
1456 ParseResult FIRModuleContext::addSymbolEntry(StringRef name,
1458 bool insertNameIntoGlobalScope) {
1463 if (entryIt->second.first.isValid()) {
1464 emitError(loc,
"redefinition of name '" + name +
"'")
1465 .attachNote(translateLocation(entryIt->second.first))
1466 <<
"previous definition here";
1472 entryIt->second = {loc, entry};
1473 if (currentScope && !insertNameIntoGlobalScope)
1474 currentScope->scopedDecls.push_back(&*entryIt);
1482 StringRef name, SMLoc loc) {
1483 auto &entry = symbolTable[name];
1484 if (!entry.first.isValid())
1485 return emitError(loc,
"use of unknown declaration '" + name +
"'");
1486 result = entry.second;
1487 assert(result &&
"name in symbol table without definition");
1491 ParseResult FIRModuleContext::resolveSymbolEntry(Value &result,
1493 SMLoc loc,
bool fatal) {
1494 if (!entry.is<Value>()) {
1496 emitError(loc,
"bundle value should only be used from subfield");
1499 result = entry.get<Value>();
1503 ParseResult FIRModuleContext::resolveSymbolEntry(Value &result,
1505 StringRef fieldName,
1508 emitError(loc,
"value should not be used from subfield");
1514 unsigned unbundledId = entry.get<
UnbundledID>() - 1;
1515 assert(unbundledId < unbundledValues.size());
1517 for (
auto elt : ubEntry) {
1518 if (elt.first == fieldAttr) {
1519 result = elt.second;
1524 emitError(loc,
"use of invalid field name '")
1525 << fieldName <<
"' on bundle value";
1551 struct LazyLocationListener :
public OpBuilder::Listener {
1552 LazyLocationListener(OpBuilder &builder) : builder(builder) {
1553 assert(builder.getListener() ==
nullptr);
1554 builder.setListener(
this);
1557 ~LazyLocationListener() {
1558 assert(subOps.empty() &&
"didn't process parsed operations");
1559 assert(builder.getListener() ==
this);
1560 builder.setListener(
nullptr);
1563 void startStatement() {
1564 assert(!isActive &&
"Already processing a statement");
1570 void endStatement(FIRParser &parser) {
1571 assert(isActive &&
"Not parsing a statement");
1575 for (
auto opAndSMLoc : subOps) {
1579 switch (parser.getConstants().options.infoLocatorHandling) {
1580 case ILH::IgnoreInfo:
1582 opAndSMLoc.first->setLoc(parser.translateLocation(opAndSMLoc.second));
1584 case ILH::PreferInfo:
1585 opAndSMLoc.first->setLoc(infoLoc);
1587 case ILH::FusedInfo:
1589 infoLoc.getContext(),
1590 {infoLoc, parser.translateLocation(opAndSMLoc.second)}));
1597 for (
auto opAndSMLoc : subOps)
1598 opAndSMLoc.first->setLoc(parser.translateLocation(opAndSMLoc.second));
1603 infoLoc = LocationAttr();
1604 currentSMLoc = SMLoc();
1609 void setLoc(SMLoc loc) { currentSMLoc = loc; }
1612 void setInfoLoc(LocationAttr loc) {
1613 assert(!infoLoc &&
"Info location multiply specified");
1619 void notifyOperationInserted(Operation *op,
1620 mlir::IRRewriter::InsertPoint)
override {
1621 assert(currentSMLoc != SMLoc() &&
"No .fir file location specified");
1622 assert(isActive &&
"Not parsing a statement");
1623 subOps.push_back({op, currentSMLoc});
1628 bool isActive =
false;
1636 LocationAttr infoLoc;
1643 SmallVector<std::pair<Operation *, SMLoc>, 8> subOps;
1645 void operator=(
const LazyLocationListener &) =
delete;
1646 LazyLocationListener(
const LazyLocationListener &) =
delete;
1654 struct InnerSymFixups {
1656 void add(hw::InnerRefUserOpInterface user, hw::InnerSymTarget target) {
1657 fixups.push_back({user, target});
1662 LogicalResult resolve(hw::InnerSymbolNamespaceCollection &isnc);
1666 hw::InnerRefUserOpInterface innerRefUser;
1667 hw::InnerSymTarget target;
1669 SmallVector<Fixup, 0> fixups;
1674 InnerSymFixups::resolve(hw::InnerSymbolNamespaceCollection &isnc) {
1675 for (
auto &f : fixups) {
1677 f.target, [&isnc](FModuleLike module) -> hw::InnerSymbolNamespace & {
1678 return isnc.get(module);
1680 assert(ref &&
"unable to resolve inner symbol target");
1684 TypeSwitch<Operation *, LogicalResult>(f.innerRefUser.getOperation())
1685 .Case<RWProbeOp>([ref](RWProbeOp op) {
1686 op.setTargetAttr(ref);
1689 .Default([](
auto *op) {
1690 return op->emitError(
"unknown inner-ref user requiring fixup");
1701 struct FIRStmtParser :
public FIRParser {
1702 explicit FIRStmtParser(Block &blockToInsertInto,
1703 FIRModuleContext &moduleContext,
1704 InnerSymFixups &innerSymFixups,
1705 const SymbolTable &circuitSymTbl,
FIRVersion version,
1706 SymbolRefAttr layerSym = {})
1707 : FIRParser(moduleContext.getConstants(), moduleContext.getLexer(),
1710 locationProcessor(this->builder), moduleContext(moduleContext),
1711 innerSymFixups(innerSymFixups), layerSym(layerSym),
1712 circuitSymTbl(circuitSymTbl) {
1713 builder.setInsertionPointToEnd(&blockToInsertInto);
1716 ParseResult parseSimpleStmt(
unsigned stmtIndent);
1717 ParseResult parseSimpleStmtBlock(
unsigned indent);
1720 ParseResult parseSimpleStmtImpl(
unsigned stmtIndent);
1723 void emitInvalidate(Value val,
Flow flow);
1729 void emitInvalidate(Value val) { emitInvalidate(val,
foldFlow(val)); }
1732 ParseResult parseOptionalInfo() {
1734 if (failed(parseOptionalInfoLocator(loc)))
1736 locationProcessor.setInfoLoc(loc);
1741 ParseResult parseExpImpl(Value &result,
const Twine &message,
1742 bool isLeadingStmt);
1743 ParseResult parseExp(Value &result,
const Twine &message) {
1744 return parseExpImpl(result, message,
false);
1746 ParseResult parseExpLeadingStmt(Value &result,
const Twine &message) {
1747 return parseExpImpl(result, message,
true);
1749 ParseResult parseEnumExp(Value &result);
1750 ParseResult parsePathExp(Value &result);
1751 ParseResult parseRefExp(Value &result,
const Twine &message);
1752 ParseResult parseStaticRefExp(Value &result,
const Twine &message);
1753 ParseResult parseRWProbeStaticRefExp(
FieldRef &refResult, Type &type,
1754 const Twine &message);
1757 ParseResult parseIntrinsic(Value &result,
bool isStatement);
1758 ParseResult parseIntrinsicStmt() {
1760 return parseIntrinsic(unused,
true);
1762 ParseResult parseIntrinsicExp(Value &result) {
1763 return parseIntrinsic(result,
false);
1765 ParseResult parseOptionalParams(ArrayAttr &resultParameters);
1767 template <
typename subop>
1768 FailureOr<Value> emitCachedSubAccess(Value base,
1769 ArrayRef<NamedAttribute> attrs,
1770 unsigned indexNo, SMLoc loc);
1771 ParseResult parseOptionalExpPostscript(Value &result,
1772 bool allowDynamic =
true);
1773 ParseResult parsePostFixFieldId(Value &result);
1774 ParseResult parsePostFixIntSubscript(Value &result);
1775 ParseResult parsePostFixDynamicSubscript(Value &result);
1776 ParseResult parseIntegerLiteralExp(Value &result);
1777 ParseResult parseListExp(Value &result);
1778 ParseResult parseListConcatExp(Value &result);
1780 template <
typename T,
size_t M,
size_t N,
size_t... Ms,
size_t... Ns>
1781 ParseResult parsePrim(std::index_sequence<Ms...>, std::index_sequence<Ns...>,
1783 auto loc = getToken().getLoc();
1784 locationProcessor.setLoc(loc);
1787 auto vals = std::array<Value, M>();
1788 auto ints = std::array<int64_t, N>();
1792 for (
size_t i = 0; i < M; ++i) {
1794 if (parseToken(FIRToken::comma,
"expected ','"))
1796 if (parseExp(vals[i],
"expected expression in primitive operand"))
1802 for (
size_t i = 0; i < N; ++i) {
1804 if (parseToken(FIRToken::comma,
"expected ','"))
1806 if (parseIntLit(ints[i],
"expected integer in primitive operand"))
1811 if (parseToken(FIRToken::r_paren,
"expected ')'"))
1815 auto type = T::inferReturnType(cast<FIRRTLType>(vals[Ms].getType())...,
1819 T::inferReturnType(cast<FIRRTLType>(vals[Ms].getType())..., ints[Ns]...,
1820 translateLocation(loc));
1825 auto op = builder.create<T>(type, vals[Ms]..., ints[Ns]...);
1826 result = op.getResult();
1830 template <
typename T,
unsigned M,
unsigned N>
1831 ParseResult parsePrimExp(Value &result) {
1832 auto ms = std::make_index_sequence<M>();
1833 auto ns = std::make_index_sequence<N>();
1834 return parsePrim<T, M, N>(ms, ns, result);
1837 std::optional<ParseResult> parseExpWithLeadingKeyword(
FIRToken keyword);
1840 ParseResult parseSubBlock(Block &blockToInsertInto,
unsigned indent,
1841 SymbolRefAttr layerSym);
1842 ParseResult parseAttach();
1843 ParseResult parseMemPort(MemDirAttr direction);
1844 ParseResult parsePrintf();
1845 ParseResult parseSkip();
1846 ParseResult parseStop();
1847 ParseResult parseAssert();
1848 ParseResult parseAssume();
1849 ParseResult parseCover();
1850 ParseResult parseWhen(
unsigned whenIndent);
1851 ParseResult parseMatch(
unsigned matchIndent);
1852 ParseResult parseRefDefine();
1853 ParseResult parseRefForce();
1854 ParseResult parseRefForceInitial();
1855 ParseResult parseRefRelease();
1856 ParseResult parseRefReleaseInitial();
1857 ParseResult parseRefRead(Value &result);
1858 ParseResult parseProbe(Value &result);
1859 ParseResult parsePropAssign();
1860 ParseResult parseRWProbe(Value &result);
1861 ParseResult parseLeadingExpStmt(Value lhs);
1862 ParseResult parseConnect();
1863 ParseResult parseInvalidate();
1864 ParseResult parseLayerBlockOrGroup(
unsigned indent);
1867 ParseResult parseInstance();
1868 ParseResult parseInstanceChoice();
1869 ParseResult parseObject();
1870 ParseResult parseCombMem();
1871 ParseResult parseSeqMem();
1872 ParseResult parseMem(
unsigned memIndent);
1873 ParseResult parseNode();
1874 ParseResult parseWire();
1875 ParseResult parseRegister(
unsigned regIndent);
1876 ParseResult parseRegisterWithReset();
1879 FModuleLike getReferencedModule(SMLoc loc, StringRef moduleName);
1882 ImplicitLocOpBuilder builder;
1883 LazyLocationListener locationProcessor;
1886 FIRModuleContext &moduleContext;
1889 InnerSymFixups &innerSymFixups;
1893 SymbolRefAttr layerSym;
1895 const SymbolTable &circuitSymTbl;
1902 void FIRStmtParser::emitInvalidate(Value val,
Flow flow) {
1903 auto tpe = type_dyn_cast<FIRRTLBaseType>(val.getType());
1910 auto props = tpe.getRecursiveTypeProperties();
1911 if (props.isPassive && !props.containsAnalog) {
1914 emitConnect(builder, val, builder.create<InvalidValueOp>(tpe));
1925 TypeSwitch<FIRRTLType>(tpe)
1926 .Case<BundleType>([&](
auto tpe) {
1927 for (
size_t i = 0, e = tpe.getNumElements(); i < e; ++i) {
1928 auto &subfield = moduleContext.getCachedSubaccess(val, i);
1930 OpBuilder::InsertionGuard guard(builder);
1931 builder.setInsertionPointAfterValue(val);
1932 subfield = builder.create<SubfieldOp>(val, i);
1934 emitInvalidate(subfield,
1935 tpe.getElement(i).isFlip ?
swapFlow(flow) : flow);
1938 .Case<FVectorType>([&](
auto tpe) {
1939 auto tpex = tpe.getElementType();
1940 for (
size_t i = 0, e = tpe.getNumElements(); i != e; ++i) {
1941 auto &subindex = moduleContext.getCachedSubaccess(val, i);
1943 OpBuilder::InsertionGuard guard(builder);
1944 builder.setInsertionPointAfterValue(val);
1945 subindex = builder.create<SubindexOp>(tpex, val, i);
1947 emitInvalidate(subindex, flow);
1975 ParseResult FIRStmtParser::parseExpImpl(Value &result,
const Twine &message,
1976 bool isLeadingStmt) {
1977 auto token = getToken();
1978 auto kind = token.getKind();
1980 case FIRToken::lp_integer_add:
1981 case FIRToken::lp_integer_mul:
1982 case FIRToken::lp_integer_shr:
1983 case FIRToken::lp_integer_shl:
1984 if (requireFeature({4, 0, 0},
"Integer arithmetic expressions"))
1993 #define TOK_LPKEYWORD_PRIM(SPELLING, CLASS, NUMOPERANDS, NUMATTRIBUTES) \
1994 case FIRToken::lp_##SPELLING: \
1995 if (parsePrimExp<CLASS, NUMOPERANDS, NUMATTRIBUTES>(result)) \
1998 #include "FIRTokenKinds.def"
2000 case FIRToken::l_brace_bar:
2002 return emitError(
"unexpected enumeration as start of statement");
2003 if (parseEnumExp(result))
2006 case FIRToken::lp_read:
2008 return emitError(
"unexpected read() as start of statement");
2009 if (parseRefRead(result))
2012 case FIRToken::lp_probe:
2014 return emitError(
"unexpected probe() as start of statement");
2015 if (parseProbe(result))
2018 case FIRToken::lp_rwprobe:
2020 return emitError(
"unexpected rwprobe() as start of statement");
2021 if (parseRWProbe(result))
2025 case FIRToken::kw_UInt:
2026 case FIRToken::kw_SInt:
2027 if (parseIntegerLiteralExp(result))
2030 case FIRToken::kw_String: {
2031 if (requireFeature({3, 1, 0},
"Strings"))
2033 locationProcessor.setLoc(getToken().getLoc());
2034 consumeToken(FIRToken::kw_String);
2036 if (parseToken(FIRToken::l_paren,
"expected '(' in String expression") ||
2037 parseGetSpelling(spelling) ||
2038 parseToken(FIRToken::string,
2039 "expected string literal in String expression") ||
2040 parseToken(FIRToken::r_paren,
"expected ')' in String expression"))
2043 result = moduleContext.getCachedConstant<StringConstantOp>(
2044 builder, attr, builder.getType<StringType>(), attr);
2047 case FIRToken::kw_Integer: {
2048 if (requireFeature({3, 1, 0},
"Integers"))
2050 locationProcessor.setLoc(getToken().getLoc());
2051 consumeToken(FIRToken::kw_Integer);
2053 if (parseToken(FIRToken::l_paren,
"expected '(' in Integer expression") ||
2054 parseIntLit(value,
"expected integer literal in Integer expression") ||
2055 parseToken(FIRToken::r_paren,
"expected ')' in Integer expression"))
2057 APSInt apint(value,
false);
2058 result = moduleContext.getCachedConstant<FIntegerConstantOp>(
2060 builder.getType<FIntegerType>(), apint);
2063 case FIRToken::kw_Bool: {
2066 locationProcessor.setLoc(getToken().getLoc());
2067 consumeToken(FIRToken::kw_Bool);
2068 if (parseToken(FIRToken::l_paren,
"expected '(' in Bool expression"))
2071 if (consumeIf(FIRToken::kw_true))
2073 else if (consumeIf(FIRToken::kw_false))
2076 return emitError(
"expected true or false in Bool expression");
2077 if (parseToken(FIRToken::r_paren,
"expected ')' in Bool expression"))
2079 auto attr = builder.getBoolAttr(value);
2080 result = moduleContext.getCachedConstant<BoolConstantOp>(
2081 builder, attr, builder.getType<BoolType>(), value);
2084 case FIRToken::kw_Double: {
2087 locationProcessor.setLoc(getToken().getLoc());
2088 consumeToken(FIRToken::kw_Double);
2089 if (parseToken(FIRToken::l_paren,
"expected '(' in Double expression"))
2091 auto spelling = getTokenSpelling();
2092 if (parseToken(FIRToken::floatingpoint,
2093 "expected floating point in Double expression") ||
2094 parseToken(FIRToken::r_paren,
"expected ')' in Double expression"))
2099 if (!llvm::to_float(spelling, d))
2100 return emitError(
"invalid double");
2101 auto attr = builder.getF64FloatAttr(d);
2102 result = moduleContext.getCachedConstant<DoubleConstantOp>(
2103 builder, attr, builder.getType<DoubleType>(), attr);
2106 case FIRToken::kw_List: {
2110 return emitError(
"unexpected List<>() as start of statement");
2111 if (parseListExp(result))
2116 case FIRToken::lp_list_concat: {
2118 return emitError(
"unexpected list_create() as start of statement");
2120 parseListConcatExp(result))
2125 case FIRToken::lp_path:
2127 return emitError(
"unexpected path() as start of statement");
2128 if (requireFeature(
nextFIRVersion,
"paths") || parsePathExp(result))
2132 case FIRToken::lp_intrinsic:
2133 if (requireFeature({4, 0, 0},
"generic intrinsics") ||
2134 parseIntrinsicExp(result))
2140 case FIRToken::identifier:
2141 case FIRToken::literal_identifier:
2144 auto loc = getToken().getLoc();
2146 if (parseId(name, message) ||
2147 moduleContext.lookupSymbolEntry(symtabEntry, name, loc))
2151 if (!moduleContext.resolveSymbolEntry(result, symtabEntry, loc,
false))
2159 if (isLeadingStmt && consumeIf(FIRToken::kw_is)) {
2160 if (parseToken(FIRToken::kw_invalid,
"expected 'invalid'") ||
2161 parseOptionalInfo())
2164 locationProcessor.setLoc(loc);
2166 unsigned unbundledId = symtabEntry.get<
UnbundledID>() - 1;
2168 moduleContext.getUnbundledEntry(unbundledId);
2169 for (
auto elt : ubEntry)
2170 emitInvalidate(elt.second);
2178 StringRef fieldName;
2179 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
2180 parseFieldId(fieldName,
"expected field name") ||
2181 moduleContext.resolveSymbolEntry(result, symtabEntry, fieldName, loc))
2189 case FIRToken::lp_shr:
2192 if (version <
FIRVersion(4, 0, 0) && type_isa<UIntType>(result.getType()))
2193 result = builder.create<PadPrimOp>(result, 1);
2199 return parseOptionalExpPostscript(result);
2209 ParseResult FIRStmtParser::parseOptionalExpPostscript(Value &result,
2210 bool allowDynamic) {
2215 if (consumeIf(FIRToken::period)) {
2216 if (parsePostFixFieldId(result))
2223 if (consumeIf(FIRToken::l_square)) {
2224 if (getToken().isAny(FIRToken::integer, FIRToken::string)) {
2225 if (parsePostFixIntSubscript(result))
2230 return emitError(
"subaccess not allowed here");
2231 if (parsePostFixDynamicSubscript(result))
2241 template <
typename subop>
2243 FIRStmtParser::emitCachedSubAccess(Value base, ArrayRef<NamedAttribute> attrs,
2244 unsigned indexNo, SMLoc loc) {
2247 auto baseType = cast<FIRRTLType>(base.getType());
2248 auto resultType = subop::inferReturnType(baseType, indexNo, {});
2251 (void)subop::inferReturnType(baseType, indexNo, translateLocation(loc));
2256 auto &value = moduleContext.getCachedSubaccess(base, indexNo);
2262 locationProcessor.setLoc(loc);
2263 OpBuilder::InsertionGuard guard(builder);
2264 builder.setInsertionPointAfterValue(base);
2265 auto op = builder.create<subop>(resultType, base, attrs);
2268 return value = op.getResult();
2275 ParseResult FIRStmtParser::parsePostFixFieldId(Value &result) {
2276 auto loc = getToken().getLoc();
2277 SmallVector<StringRef, 3> fields;
2278 if (parseFieldIdSeq(fields,
"expected field name"))
2280 for (
auto fieldName : fields) {
2281 std::optional<unsigned> indexV;
2282 auto type = result.getType();
2283 if (
auto refTy = type_dyn_cast<RefType>(type))
2284 type = refTy.getType();
2285 if (
auto bundle = type_dyn_cast<BundleType>(type))
2286 indexV = bundle.getElementIndex(fieldName);
2287 else if (
auto bundle = type_dyn_cast<OpenBundleType>(type))
2288 indexV = bundle.getElementIndex(fieldName);
2289 else if (
auto klass = type_dyn_cast<ClassType>(type))
2290 indexV = klass.getElementIndex(fieldName);
2292 return emitError(loc,
"subfield requires bundle or object operand ");
2294 return emitError(loc,
"unknown field '" + fieldName +
"' in type ")
2295 << result.getType();
2296 auto indexNo = *indexV;
2298 FailureOr<Value> subResult;
2299 if (type_isa<RefType>(result.getType())) {
2300 NamedAttribute attrs = {getConstants().indexIdentifier,
2301 builder.getI32IntegerAttr(indexNo)};
2302 subResult = emitCachedSubAccess<RefSubOp>(result, attrs, indexNo, loc);
2303 }
else if (type_isa<ClassType>(type)) {
2304 NamedAttribute attrs = {getConstants().indexIdentifier,
2305 builder.getI32IntegerAttr(indexNo)};
2307 emitCachedSubAccess<ObjectSubfieldOp>(result, attrs, indexNo, loc);
2309 NamedAttribute attrs = {getConstants().fieldIndexIdentifier,
2310 builder.getI32IntegerAttr(indexNo)};
2311 if (type_isa<BundleType>(type))
2313 emitCachedSubAccess<SubfieldOp>(result, attrs, indexNo, loc);
2316 emitCachedSubAccess<OpenSubfieldOp>(result, attrs, indexNo, loc);
2319 if (failed(subResult))
2321 result = *subResult;
2330 ParseResult FIRStmtParser::parsePostFixIntSubscript(Value &result) {
2331 auto loc = getToken().getLoc();
2333 if (parseIntLit(indexNo,
"expected index") ||
2334 parseToken(FIRToken::r_square,
"expected ']'"))
2338 return emitError(loc,
"invalid index specifier"), failure();
2344 NamedAttribute attrs = {getConstants().indexIdentifier,
2345 builder.getI32IntegerAttr(indexNo)};
2347 FailureOr<Value> subResult;
2348 if (type_isa<RefType>(result.getType()))
2349 subResult = emitCachedSubAccess<RefSubOp>(result, attrs, indexNo, loc);
2350 else if (type_isa<FVectorType>(result.getType()))
2351 subResult = emitCachedSubAccess<SubindexOp>(result, attrs, indexNo, loc);
2354 emitCachedSubAccess<OpenSubindexOp>(result, attrs, indexNo, loc);
2356 if (failed(subResult))
2358 result = *subResult;
2366 ParseResult FIRStmtParser::parsePostFixDynamicSubscript(Value &result) {
2367 auto loc = getToken().getLoc();
2369 if (parseExp(index,
"expected subscript index expression") ||
2370 parseToken(FIRToken::r_square,
"expected ']' in subscript"))
2374 auto indexType = type_dyn_cast<FIRRTLBaseType>(index.getType());
2376 return emitError(
"expected base type for index expression");
2377 indexType = indexType.getPassiveType();
2378 locationProcessor.setLoc(loc);
2383 SubaccessOp::inferReturnType(result.getType(), index.getType(), {});
2386 (void)SubaccessOp::inferReturnType(result.getType(), index.getType(),
2387 translateLocation(loc));
2392 auto op = builder.create<SubaccessOp>(resultType, result, index);
2393 result = op.getResult();
2399 ParseResult FIRStmtParser::parseIntegerLiteralExp(Value &result) {
2400 bool isSigned = getToken().is(FIRToken::kw_SInt);
2401 auto loc = getToken().getLoc();
2407 if (parseOptionalWidth(
width) ||
2408 parseToken(FIRToken::l_paren,
"expected '(' in integer expression") ||
2409 parseIntLit(value,
"expected integer value") ||
2410 parseToken(FIRToken::r_paren,
"expected ')' in integer expression"))
2417 IntegerType::SignednessSemantics signedness =
2418 isSigned ? IntegerType::Signed : IntegerType::Unsigned;
2420 if (!value.isZero())
2421 return emitError(loc,
"zero bit constant must be zero");
2422 value = value.trunc(0);
2423 }
else if (
width != -1) {
2425 bool valueFits = isSigned ? value.isSignedIntN(
width) : value.isIntN(
width);
2427 return emitError(loc,
"initializer too wide for declared width");
2428 value = isSigned ? value.sextOrTrunc(
width) : value.zextOrTrunc(
width);
2433 auto attr = builder.getIntegerAttr(attrType, value);
2436 auto &entry = moduleContext.constantCache[{attr, type}];
2443 locationProcessor.setLoc(loc);
2444 result = moduleContext.getCachedConstant(builder, attr, type, attr);
2449 ParseResult FIRStmtParser::parseListExp(Value &result) {
2450 auto loc = getToken().getLoc();
2452 if (parseListType(type))
2454 auto listType = type_cast<ListType>(type);
2457 if (parseToken(FIRToken::l_paren,
"expected '(' in List expression"))
2460 SmallVector<Value, 3> operands;
2461 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2463 locationProcessor.setLoc(loc);
2464 if (parseExp(operand,
"expected expression in List expression"))
2468 if (!isa<AnyRefType>(elementType) ||
2469 !isa<ClassType>(operand.getType()))
2470 return emitError(loc,
"unexpected expression of type ")
2471 << operand.getType() <<
" in List expression of type "
2473 operand = builder.create<ObjectAnyRefCastOp>(operand);
2476 operands.push_back(operand);
2481 locationProcessor.setLoc(loc);
2482 result = builder.create<ListCreateOp>(listType, operands);
2487 ParseResult FIRStmtParser::parseListConcatExp(Value &result) {
2488 consumeToken(FIRToken::lp_list_concat);
2490 auto loc = getToken().getLoc();
2492 SmallVector<Value, 3> operands;
2493 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2495 locationProcessor.setLoc(loc);
2496 if (parseExp(operand,
"expected expression in List concat expression"))
2499 if (!type_isa<ListType>(operand.getType()))
2500 return emitError(loc,
"unexpected expression of type ")
2501 << operand.getType() <<
" in List concat expression";
2504 type = type_cast<ListType>(operand.getType());
2506 if (operand.getType() != type)
2507 return emitError(loc,
"unexpected expression of type ")
2508 << operand.getType() <<
" in List concat expression of type "
2511 operands.push_back(operand);
2516 if (operands.empty())
2517 return emitError(loc,
"need at least one List to concatenate");
2519 locationProcessor.setLoc(loc);
2520 result = builder.create<ListConcatOp>(type, operands);
2541 std::optional<ParseResult>
2542 FIRStmtParser::parseExpWithLeadingKeyword(
FIRToken keyword) {
2543 switch (getToken().getKind()) {
2546 return std::nullopt;
2548 case FIRToken::period:
2549 case FIRToken::l_square:
2550 case FIRToken::kw_is:
2551 case FIRToken::less_equal:
2557 auto loc = keyword.
getLoc();
2559 if (moduleContext.lookupSymbolEntry(symtabEntry, keyword.
getSpelling(), loc))
2560 return ParseResult(failure());
2566 if (moduleContext.resolveSymbolEntry(lhs, symtabEntry, loc,
false)) {
2569 if (!consumeIf(FIRToken::period))
2570 return ParseResult(failure());
2572 StringRef fieldName;
2573 if (parseFieldId(fieldName,
"expected field name") ||
2574 moduleContext.resolveSymbolEntry(lhs, symtabEntry, fieldName, loc))
2575 return ParseResult(failure());
2579 if (parseOptionalExpPostscript(lhs))
2580 return ParseResult(failure());
2582 return parseLeadingExpStmt(lhs);
2588 ParseResult FIRStmtParser::parseSimpleStmtBlock(
unsigned indent) {
2591 if (getToken().isAny(FIRToken::eof, FIRToken::error))
2594 auto subIndent = getIndentation();
2595 if (!subIndent.has_value())
2596 return emitError(
"expected statement to be on its own line"), failure();
2598 if (*subIndent <= indent)
2602 if (parseSimpleStmt(*subIndent))
2607 ParseResult FIRStmtParser::parseSimpleStmt(
unsigned stmtIndent) {
2608 locationProcessor.startStatement();
2609 auto result = parseSimpleStmtImpl(stmtIndent);
2610 locationProcessor.endStatement(*
this);
2631 ParseResult FIRStmtParser::parseSimpleStmtImpl(
unsigned stmtIndent) {
2632 auto kind = getToken().getKind();
2635 case FIRToken::kw_invalidate:
2636 case FIRToken::kw_connect:
2637 case FIRToken::kw_regreset:
2641 kind = FIRToken::identifier;
2648 case FIRToken::kw_attach:
2649 return parseAttach();
2650 case FIRToken::kw_infer:
2651 return parseMemPort(MemDirAttr::Infer);
2652 case FIRToken::kw_read:
2653 return parseMemPort(MemDirAttr::Read);
2654 case FIRToken::kw_write:
2655 return parseMemPort(MemDirAttr::Write);
2656 case FIRToken::kw_rdwr:
2657 return parseMemPort(MemDirAttr::ReadWrite);
2658 case FIRToken::kw_connect:
2659 return parseConnect();
2660 case FIRToken::kw_propassign:
2661 if (requireFeature({3, 1, 0},
"properties"))
2663 return parsePropAssign();
2664 case FIRToken::kw_invalidate:
2665 return parseInvalidate();
2666 case FIRToken::lp_printf:
2667 return parsePrintf();
2668 case FIRToken::kw_skip:
2670 case FIRToken::lp_stop:
2672 case FIRToken::lp_assert:
2673 return parseAssert();
2674 case FIRToken::lp_assume:
2675 return parseAssume();
2676 case FIRToken::lp_cover:
2677 return parseCover();
2678 case FIRToken::kw_when:
2679 return parseWhen(stmtIndent);
2680 case FIRToken::kw_match:
2681 return parseMatch(stmtIndent);
2682 case FIRToken::kw_define:
2683 return parseRefDefine();
2684 case FIRToken::lp_force:
2685 return parseRefForce();
2686 case FIRToken::lp_force_initial:
2687 return parseRefForceInitial();
2688 case FIRToken::lp_release:
2689 return parseRefRelease();
2690 case FIRToken::lp_release_initial:
2691 return parseRefReleaseInitial();
2692 case FIRToken::kw_group:
2693 if (requireFeature({3, 2, 0},
"optional groups") ||
2694 removedFeature({4, 0, 0},
"optional groups"))
2696 return parseLayerBlockOrGroup(stmtIndent);
2697 case FIRToken::kw_layerblock:
2698 if (requireFeature({4, 0, 0},
"layers"))
2700 return parseLayerBlockOrGroup(stmtIndent);
2701 case FIRToken::lp_intrinsic:
2702 if (requireFeature({4, 0, 0},
"generic intrinsics"))
2704 return parseIntrinsicStmt();
2708 if (parseExpLeadingStmt(lhs,
"unexpected token in module"))
2715 return parseLeadingExpStmt(lhs);
2719 case FIRToken::kw_inst:
2720 return parseInstance();
2721 case FIRToken::kw_instchoice:
2722 return parseInstanceChoice();
2723 case FIRToken::kw_object:
2724 return parseObject();
2725 case FIRToken::kw_cmem:
2726 return parseCombMem();
2727 case FIRToken::kw_smem:
2728 return parseSeqMem();
2729 case FIRToken::kw_mem:
2730 return parseMem(stmtIndent);
2731 case FIRToken::kw_node:
2733 case FIRToken::kw_wire:
2735 case FIRToken::kw_reg:
2736 return parseRegister(stmtIndent);
2737 case FIRToken::kw_regreset:
2738 return parseRegisterWithReset();
2742 ParseResult FIRStmtParser::parseSubBlock(Block &blockToInsertInto,
2744 SymbolRefAttr layerSym) {
2746 auto suiteScope = std::make_unique<FIRModuleContext::ContextScope>(
2747 moduleContext, &blockToInsertInto);
2752 UnbundledValueRestorer x(moduleContext.unbundledValues);
2756 auto subParser = std::make_unique<FIRStmtParser>(
2757 blockToInsertInto, moduleContext, innerSymFixups, circuitSymTbl, version,
2761 auto stmtIndent = getIndentation();
2764 if (!stmtIndent.has_value())
2765 return subParser->parseSimpleStmt(indent);
2767 if (*stmtIndent <= indent)
2768 return emitError(
"statement must be indented more than previous statement"),
2772 return subParser->parseSimpleStmtBlock(indent);
2776 ParseResult FIRStmtParser::parseAttach() {
2777 auto startTok = consumeToken(FIRToken::kw_attach);
2780 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2783 if (parseToken(FIRToken::l_paren,
"expected '(' after attach"))
2786 SmallVector<Value, 4> operands;
2787 operands.push_back({});
2788 if (parseExp(operands.back(),
"expected operand in attach"))
2791 while (consumeIf(FIRToken::comma)) {
2792 operands.push_back({});
2793 if (parseExp(operands.back(),
"expected operand in attach"))
2796 if (parseToken(FIRToken::r_paren,
"expected close paren"))
2799 if (parseOptionalInfo())
2802 locationProcessor.setLoc(startTok.getLoc());
2803 builder.create<AttachOp>(operands);
2810 ParseResult FIRStmtParser::parseMemPort(MemDirAttr direction) {
2811 auto startTok = consumeToken();
2812 auto startLoc = startTok.getLoc();
2816 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2822 Value memory, indexExp, clock;
2823 if (parseToken(FIRToken::kw_mport,
"expected 'mport' in memory port") ||
2824 parseId(
id,
"expected result name") ||
2825 parseToken(FIRToken::equal,
"expected '=' in memory port") ||
2826 parseId(memName,
"expected memory name") ||
2827 moduleContext.lookupSymbolEntry(memorySym, memName, startLoc) ||
2828 moduleContext.resolveSymbolEntry(memory, memorySym, startLoc) ||
2829 parseToken(FIRToken::l_square,
"expected '[' in memory port") ||
2830 parseExp(indexExp,
"expected index expression") ||
2831 parseToken(FIRToken::r_square,
"expected ']' in memory port") ||
2832 parseToken(FIRToken::comma,
"expected ','") ||
2833 parseExp(clock,
"expected clock expression") || parseOptionalInfo())
2836 auto memVType = type_dyn_cast<CMemoryType>(memory.getType());
2838 return emitError(startLoc,
2839 "memory port should have behavioral memory type");
2840 auto resultType = memVType.getElementType();
2842 ArrayAttr annotations = getConstants().emptyArrayAttr;
2843 locationProcessor.setLoc(startLoc);
2846 Value memoryPort, memoryData;
2848 OpBuilder::InsertionGuard guard(builder);
2849 builder.setInsertionPointAfterValue(memory);
2850 auto memoryPortOp = builder.create<MemoryPortOp>(
2853 memoryData = memoryPortOp.getResult(0);
2854 memoryPort = memoryPortOp.getResult(1);
2858 builder.create<MemoryPortAccessOp>(memoryPort, indexExp, clock);
2860 return moduleContext.addSymbolEntry(
id, memoryData, startLoc,
true);
2864 ParseResult FIRStmtParser::parsePrintf() {
2865 auto startTok = consumeToken(FIRToken::lp_printf);
2867 Value clock, condition;
2868 StringRef formatString;
2869 if (parseExp(clock,
"expected clock expression in printf") ||
2870 parseToken(FIRToken::comma,
"expected ','") ||
2871 parseExp(condition,
"expected condition in printf") ||
2872 parseToken(FIRToken::comma,
"expected ','") ||
2873 parseGetSpelling(formatString) ||
2874 parseToken(FIRToken::string,
"expected format string in printf"))
2877 SmallVector<Value, 4> operands;
2878 while (consumeIf(FIRToken::comma)) {
2879 operands.push_back({});
2880 if (parseExp(operands.back(),
"expected operand in printf"))
2883 if (parseToken(FIRToken::r_paren,
"expected ')'"))
2887 if (parseOptionalName(name))
2890 if (parseOptionalInfo())
2893 locationProcessor.setLoc(startTok.getLoc());
2896 builder.create<PrintFOp>(clock, condition,
2897 builder.getStringAttr(formatStrUnescaped), operands,
2903 ParseResult FIRStmtParser::parseSkip() {
2904 auto startTok = consumeToken(FIRToken::kw_skip);
2908 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2911 if (parseOptionalInfo())
2914 locationProcessor.setLoc(startTok.getLoc());
2915 builder.create<SkipOp>();
2920 ParseResult FIRStmtParser::parseStop() {
2921 auto startTok = consumeToken(FIRToken::lp_stop);
2923 Value clock, condition;
2926 if (parseExp(clock,
"expected clock expression in 'stop'") ||
2927 parseToken(FIRToken::comma,
"expected ','") ||
2928 parseExp(condition,
"expected condition in 'stop'") ||
2929 parseToken(FIRToken::comma,
"expected ','") ||
2930 parseIntLit(exitCode,
"expected exit code in 'stop'") ||
2931 parseToken(FIRToken::r_paren,
"expected ')' in 'stop'") ||
2932 parseOptionalName(name) || parseOptionalInfo())
2935 locationProcessor.setLoc(startTok.getLoc());
2936 builder.create<StopOp>(clock, condition, builder.getI32IntegerAttr(exitCode),
2942 ParseResult FIRStmtParser::parseAssert() {
2943 auto startTok = consumeToken(FIRToken::lp_assert);
2945 Value clock, predicate, enable;
2946 StringRef formatString;
2948 if (parseExp(clock,
"expected clock expression in 'assert'") ||
2949 parseToken(FIRToken::comma,
"expected ','") ||
2950 parseExp(predicate,
"expected predicate in 'assert'") ||
2951 parseToken(FIRToken::comma,
"expected ','") ||
2952 parseExp(enable,
"expected enable in 'assert'") ||
2953 parseToken(FIRToken::comma,
"expected ','") ||
2954 parseGetSpelling(formatString) ||
2955 parseToken(FIRToken::string,
"expected format string in 'assert'"))
2958 SmallVector<Value, 4> operands;
2959 while (!consumeIf(FIRToken::r_paren)) {
2960 operands.push_back({});
2961 if (parseToken(FIRToken::comma,
"expected ','") ||
2962 parseExp(operands.back(),
"expected operand in 'assert'"))
2966 if (parseOptionalName(name) || parseOptionalInfo())
2969 locationProcessor.setLoc(startTok.getLoc());
2971 builder.create<AssertOp>(clock, predicate, enable, formatStrUnescaped,
2972 operands, name.getValue());
2977 ParseResult FIRStmtParser::parseAssume() {
2978 auto startTok = consumeToken(FIRToken::lp_assume);
2980 Value clock, predicate, enable;
2981 StringRef formatString;
2983 if (parseExp(clock,
"expected clock expression in 'assume'") ||
2984 parseToken(FIRToken::comma,
"expected ','") ||
2985 parseExp(predicate,
"expected predicate in 'assume'") ||
2986 parseToken(FIRToken::comma,
"expected ','") ||
2987 parseExp(enable,
"expected enable in 'assume'") ||
2988 parseToken(FIRToken::comma,
"expected ','") ||
2989 parseGetSpelling(formatString) ||
2990 parseToken(FIRToken::string,
"expected format string in 'assume'"))
2993 SmallVector<Value, 4> operands;
2994 while (!consumeIf(FIRToken::r_paren)) {
2995 operands.push_back({});
2996 if (parseToken(FIRToken::comma,
"expected ','") ||
2997 parseExp(operands.back(),
"expected operand in 'assume'"))
3001 if (parseOptionalName(name) || parseOptionalInfo())
3004 locationProcessor.setLoc(startTok.getLoc());
3006 builder.create<AssumeOp>(clock, predicate, enable, formatStrUnescaped,
3007 operands, name.getValue());
3012 ParseResult FIRStmtParser::parseCover() {
3013 auto startTok = consumeToken(FIRToken::lp_cover);
3015 Value clock, predicate, enable;
3018 if (parseExp(clock,
"expected clock expression in 'cover'") ||
3019 parseToken(FIRToken::comma,
"expected ','") ||
3020 parseExp(predicate,
"expected predicate in 'cover'") ||
3021 parseToken(FIRToken::comma,
"expected ','") ||
3022 parseExp(enable,
"expected enable in 'cover'") ||
3023 parseToken(FIRToken::comma,
"expected ','") ||
3024 parseGetSpelling(message) ||
3025 parseToken(FIRToken::string,
"expected message in 'cover'") ||
3026 parseToken(FIRToken::r_paren,
"expected ')' in 'cover'") ||
3027 parseOptionalName(name) || parseOptionalInfo())
3030 locationProcessor.setLoc(startTok.getLoc());
3032 builder.create<CoverOp>(clock, predicate, enable, messageUnescaped,
3033 ValueRange{}, name.getValue());
3039 ParseResult FIRStmtParser::parseWhen(
unsigned whenIndent) {
3040 auto startTok = consumeToken(FIRToken::kw_when);
3044 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3048 if (parseExp(condition,
"expected condition in 'when'") ||
3049 parseToken(FIRToken::colon,
"expected ':' in when") ||
3050 parseOptionalInfo())
3053 locationProcessor.setLoc(startTok.getLoc());
3055 auto whenStmt = builder.create<WhenOp>(condition,
false);
3058 if (parseSubBlock(whenStmt.getThenBlock(), whenIndent, layerSym))
3062 if (getToken().isNot(FIRToken::kw_else))
3067 auto elseIndent = getIndentation();
3068 if (elseIndent && *elseIndent < whenIndent)
3071 consumeToken(FIRToken::kw_else);
3074 whenStmt.createElseRegion();
3080 if (getToken().is(FIRToken::kw_when)) {
3082 auto subParser = std::make_unique<FIRStmtParser>(
3083 whenStmt.getElseBlock(), moduleContext, innerSymFixups, circuitSymTbl,
3086 return subParser->parseSimpleStmt(whenIndent);
3090 LocationAttr elseLoc;
3091 if (parseToken(FIRToken::colon,
"expected ':' after 'else'") ||
3092 parseOptionalInfoLocator(elseLoc) ||
3093 parseSubBlock(whenStmt.getElseBlock(), whenIndent, layerSym))
3102 ParseResult FIRStmtParser::parseEnumExp(Value &value) {
3103 auto startLoc = getToken().getLoc();
3104 locationProcessor.setLoc(startLoc);
3106 if (parseEnumType(type))
3110 auto enumType = type_dyn_cast<FEnumType>(type);
3112 return emitError(startLoc,
3113 "expected enumeration type in enumeration expression");
3116 if (parseToken(FIRToken::l_paren,
"expected '(' in enumeration expression") ||
3117 parseId(tag,
"expected enumeration tag"))
3121 if (consumeIf(FIRToken::r_paren)) {
3124 auto type =
IntType::get(builder.getContext(),
false, 0,
true);
3126 auto attr = builder.getIntegerAttr(attrType, APInt(0, 0,
false));
3127 input = builder.create<ConstantOp>(type, attr);
3130 if (parseToken(FIRToken::comma,
"expected ','") ||
3131 parseExp(input,
"expected expression in enumeration value") ||
3132 parseToken(FIRToken::r_paren,
"expected closing ')'"))
3136 value = builder.create<FEnumCreateOp>(enumType, tag, input);
3144 ParseResult FIRStmtParser::parseMatch(
unsigned matchIndent) {
3145 auto startTok = consumeToken(FIRToken::kw_match);
3147 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3151 if (parseExp(input,
"expected expression in 'match'") ||
3152 parseToken(FIRToken::colon,
"expected ':' in 'match'") ||
3153 parseOptionalInfo())
3156 auto enumType = type_dyn_cast<FEnumType>(input.getType());
3158 return mlir::emitError(
3160 "expected enumeration type for 'match' statement, but got ")
3163 locationProcessor.setLoc(startTok.getLoc());
3165 SmallVector<Attribute> tags;
3166 SmallVector<std::unique_ptr<Region>> regions;
3168 auto tagLoc = getToken().getLoc();
3171 auto caseIndent = getIndentation();
3172 if (!caseIndent || *caseIndent <= matchIndent)
3176 StringRef tagSpelling;
3177 if (parseId(tagSpelling,
"expected enumeration tag in match statement"))
3179 auto tagIndex = enumType.getElementIndex(tagSpelling);
3181 return emitError(tagLoc,
"tag ")
3182 << tagSpelling <<
" not a member of enumeration " << enumType;
3184 tags.push_back(tag);
3187 auto *caseBlock = ®ions.emplace_back(
new Region)->emplaceBlock();
3190 FIRModuleContext::ContextScope scope(moduleContext, caseBlock);
3195 UnbundledValueRestorer x(moduleContext.unbundledValues);
3198 if (consumeIf(FIRToken::l_paren)) {
3199 StringAttr identifier;
3200 if (parseId(identifier,
"expected identifier for 'case' binding"))
3204 auto dataType = enumType.getElementType(*tagIndex);
3205 caseBlock->addArgument(dataType, LocWithInfo(tagLoc,
this).getLoc());
3207 if (moduleContext.addSymbolEntry(identifier, caseBlock->getArgument(0),
3211 if (parseToken(FIRToken::r_paren,
"expected ')' in match statement case"))
3215 auto dataType =
IntType::get(builder.getContext(),
false, 0);
3216 caseBlock->addArgument(dataType, LocWithInfo(tagLoc,
this).getLoc());
3219 if (parseToken(FIRToken::colon,
"expected ':' in match statement case"))
3223 auto subParser = std::make_unique<FIRStmtParser>(
3224 *caseBlock, moduleContext, innerSymFixups, circuitSymTbl, version,
3226 if (subParser->parseSimpleStmtBlock(*caseIndent))
3230 builder.create<MatchOp>(input,
ArrayAttr::get(getContext(), tags), regions);
3236 ParseResult FIRStmtParser::parseRefExp(Value &result,
const Twine &message) {
3237 auto token = getToken().getKind();
3238 if (token == FIRToken::lp_probe)
3239 return parseProbe(result);
3240 if (token == FIRToken::lp_rwprobe)
3241 return parseRWProbe(result);
3246 return parseStaticRefExp(result, message);
3253 ParseResult FIRStmtParser::parseStaticRefExp(Value &result,
3254 const Twine &message) {
3255 auto parseIdOrInstance = [&]() -> ParseResult {
3257 auto loc = getToken().getLoc();
3259 if (parseId(
id, message) ||
3260 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
3264 if (!moduleContext.resolveSymbolEntry(result, symtabEntry, loc,
false))
3270 StringRef fieldName;
3272 parseToken(FIRToken::period,
"expected '.' in field reference") ||
3273 parseFieldId(fieldName,
"expected field name") ||
3274 moduleContext.resolveSymbolEntry(result, symtabEntry, fieldName, loc));
3276 return failure(parseIdOrInstance() ||
3277 parseOptionalExpPostscript(result,
false));
3288 ParseResult FIRStmtParser::parseRWProbeStaticRefExp(
FieldRef &refResult,
3290 const Twine &message) {
3291 auto loc = getToken().getLoc();
3295 if (parseId(
id, message) ||
3296 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
3308 if (
auto unbundledId = dyn_cast<UnbundledID>(symtabEntry)) {
3310 auto &ubEntry = moduleContext.getUnbundledEntry(unbundledId - 1);
3312 StringRef fieldName;
3313 auto loc = getToken().getLoc();
3314 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
3315 parseFieldId(fieldName,
"expected field name"))
3321 for (
auto &elt : ubEntry) {
3322 if (elt.first == fieldAttr) {
3325 auto &instResult = elt.second;
3328 auto *defining = instResult.getDefiningOp();
3330 if (isa<WireOp>(defining)) {
3331 result = instResult;
3336 auto type = instResult.getType();
3340 bool forceable =
static_cast<bool>(
3343 return emitError(loc,
"unable to force instance result of type ")
3347 auto annotations = getConstants().emptyArrayAttr;
3348 StringAttr sym = {};
3349 SmallString<64> name;
3350 (
id +
"_" + fieldName +
"_bounce").
toVector(name);
3351 locationProcessor.setLoc(loc);
3352 OpBuilder::InsertionGuard guard(builder);
3353 builder.setInsertionPoint(defining);
3354 auto bounce = builder.create<WireOp>(
3355 type, name, NameKindEnum::InterestingName, annotations, sym);
3356 auto bounceVal = bounce.getData();
3359 instResult.replaceAllUsesWith(bounceVal);
3362 builder.setInsertionPointAfter(defining);
3370 result = instResult = bounce.getDataRaw();
3376 emitError(loc,
"use of invalid field name '")
3377 << fieldName <<
"' on bundle value";
3382 result = symtabEntry.get<Value>();
3386 assert(isa<BlockArgument>(result) ||
3387 result.getDefiningOp<hw::InnerSymbolOpInterface>());
3393 type = result.getType();
3395 if (consumeIf(FIRToken::period)) {
3396 SmallVector<StringRef, 3> fields;
3397 if (parseFieldIdSeq(fields,
"expected field name"))
3399 for (
auto fieldName : fields) {
3400 if (
auto bundle = type_dyn_cast<BundleType>(type)) {
3401 if (
auto index = bundle.getElementIndex(fieldName)) {
3402 refResult = refResult.
getSubField(bundle.getFieldID(*index));
3403 type = bundle.getElementTypePreservingConst(*index);
3406 }
else if (
auto bundle = type_dyn_cast<OpenBundleType>(type)) {
3407 if (
auto index = bundle.getElementIndex(fieldName)) {
3408 refResult = refResult.
getSubField(bundle.getFieldID(*index));
3409 type = bundle.getElementTypePreservingConst(*index);
3413 return emitError(loc,
"subfield requires bundle operand")
3414 <<
"got " << type <<
"\n";
3416 return emitError(loc,
3417 "unknown field '" + fieldName +
"' in bundle type ")
3422 if (consumeIf(FIRToken::l_square)) {
3423 auto loc = getToken().
getLoc();
3425 if (parseIntLit(index,
"expected index") ||
3426 parseToken(FIRToken::r_square,
"expected ']'"))
3430 return emitError(loc,
"invalid index specifier");
3432 if (
auto vector = type_dyn_cast<FVectorType>(type)) {
3433 if ((
unsigned)index < vector.getNumElements()) {
3434 refResult = refResult.
getSubField(vector.getFieldID(index));
3435 type = vector.getElementTypePreservingConst();
3438 }
else if (
auto vector = type_dyn_cast<OpenVectorType>(type)) {
3439 if ((
unsigned)index < vector.getNumElements()) {
3440 refResult = refResult.
getSubField(vector.getFieldID(index));
3441 type = vector.getElementTypePreservingConst();
3445 return emitError(loc,
"subindex requires vector operand");
3447 return emitError(loc,
"out of range index '")
3448 << index <<
"' for vector type " << type;
3456 ParseResult FIRStmtParser::parseIntrinsic(Value &result,
bool isStatement) {
3457 auto startTok = consumeToken(FIRToken::lp_intrinsic);
3458 StringRef intrinsic;
3459 ArrayAttr parameters;
3462 if (parseId(intrinsic,
"expected intrinsic identifier") ||
3463 parseOptionalParams(parameters))
3466 if (consumeIf(FIRToken::colon)) {
3467 if (
parseType(type,
"expected intrinsic return type"))
3469 }
else if (!isStatement)
3470 return emitError(
"expected ':' in intrinsic expression");
3472 SmallVector<Value> operands;
3473 auto loc = startTok.getLoc();
3474 if (consumeIf(FIRToken::comma)) {
3475 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
3477 if (parseExp(operand,
"expected operand in intrinsic"))
3479 operands.push_back(operand);
3480 locationProcessor.setLoc(loc);
3485 if (parseToken(FIRToken::r_paren,
"expected ')' in intrinsic"))
3490 if (parseOptionalInfo())
3493 locationProcessor.setLoc(loc);
3495 auto op = builder.create<GenericIntrinsicOp>(
3496 type, builder.getStringAttr(intrinsic), operands, parameters);
3498 result = op.getResult();
3503 ParseResult FIRStmtParser::parseOptionalParams(ArrayAttr &resultParameters) {
3504 if (!consumeIf(FIRToken::less))
3507 SmallVector<Attribute, 8> parameters;
3508 SmallPtrSet<StringAttr, 8> seen;
3509 if (parseListUntil(FIRToken::greater, [&]() -> ParseResult {
3513 if (parseParameter(name, value, loc))
3515 if (!seen.insert(name).second)
3516 return emitError(loc,
"redefinition of parameter '" +
3517 name.getValue() +
"'");
3529 ParseResult FIRStmtParser::parsePathExp(Value &result) {
3530 auto startTok = consumeToken(FIRToken::lp_path);
3531 locationProcessor.setLoc(startTok.getLoc());
3533 if (parseGetSpelling(target) ||
3534 parseToken(FIRToken::string,
3535 "expected target string in path expression") ||
3536 parseToken(FIRToken::r_paren,
"expected ')' in path expression"))
3538 result = builder.create<UnresolvedPathOp>(
3544 ParseResult FIRStmtParser::parseRefDefine() {
3545 auto startTok = consumeToken(FIRToken::kw_define);
3548 if (parseStaticRefExp(target,
3549 "expected static reference expression in 'define'") ||
3550 parseToken(FIRToken::equal,
3551 "expected '=' after define reference expression") ||
3552 parseRefExp(src,
"expected reference expression in 'define'") ||
3553 parseOptionalInfo())
3557 if (!type_isa<RefType>(target.getType()))
3558 return emitError(startTok.getLoc(),
"expected reference-type expression in "
3559 "'define' target (LHS), got ")
3560 << target.getType();
3561 if (!type_isa<RefType>(src.getType()))
3562 return emitError(startTok.getLoc(),
"expected reference-type expression in "
3563 "'define' source (RHS), got ")
3568 if (isa_and_nonnull<RefSubOp>(target.getDefiningOp()))
3569 return emitError(startTok.getLoc(),
3570 "cannot define into a sub-element of a reference");
3572 locationProcessor.setLoc(startTok.getLoc());
3575 return emitError(startTok.getLoc(),
"cannot define reference of type ")
3576 << target.getType() <<
" with incompatible reference of type "
3586 ParseResult FIRStmtParser::parseRefRead(Value &result) {
3587 auto startTok = consumeToken(FIRToken::lp_read);
3590 if (parseRefExp(ref,
"expected reference expression in 'read'") ||
3591 parseToken(FIRToken::r_paren,
"expected ')' in 'read'"))
3594 locationProcessor.setLoc(startTok.getLoc());
3597 if (!type_isa<RefType>(ref.getType()))
3598 return emitError(startTok.getLoc(),
3599 "expected reference-type expression in 'read', got ")
3602 result = builder.create<RefResolveOp>(ref);
3608 ParseResult FIRStmtParser::parseProbe(Value &result) {
3609 auto startTok = consumeToken(FIRToken::lp_probe);
3612 if (parseStaticRefExp(staticRef,
3613 "expected static reference expression in 'probe'") ||
3614 parseToken(FIRToken::r_paren,
"expected ')' in 'probe'"))
3617 locationProcessor.setLoc(startTok.getLoc());
3620 if (!type_isa<FIRRTLBaseType>(staticRef.getType()))
3621 return emitError(startTok.getLoc(),
3622 "expected base-type expression in 'probe', got ")
3623 << staticRef.getType();
3627 if (isa_and_nonnull<MemOp, CombMemOp, SeqMemOp, MemoryPortOp,
3628 MemoryDebugPortOp, MemoryPortAccessOp>(
3629 staticRef.getDefiningOp()))
3630 return emitError(startTok.getLoc(),
"cannot probe memories or their ports");
3632 result = builder.create<RefSendOp>(staticRef);
3638 ParseResult FIRStmtParser::parseRWProbe(Value &result) {
3639 auto startTok = consumeToken(FIRToken::lp_rwprobe);
3642 Type parsedTargetType;
3643 if (parseRWProbeStaticRefExp(
3644 staticRef, parsedTargetType,
3645 "expected static reference expression in 'rwprobe'") ||
3646 parseToken(FIRToken::r_paren,
"expected ')' in 'rwprobe'"))
3649 locationProcessor.setLoc(startTok.getLoc());
3655 auto targetType = type_dyn_cast<FIRRTLBaseType>(parsedTargetType);
3657 return emitError(startTok.getLoc(),
3658 "expected base-type expression in 'rwprobe', got ")
3659 << parsedTargetType;
3662 auto *definingOp = root.getDefiningOp();
3664 if (isa_and_nonnull<MemOp, CombMemOp, SeqMemOp, MemoryPortOp,
3665 MemoryDebugPortOp, MemoryPortAccessOp>(definingOp))
3666 return emitError(startTok.getLoc(),
"cannot probe memories or their ports");
3670 return emitError(startTok.getLoc(),
"cannot force target of type ")
3674 auto op = builder.create<RWProbeOp>(forceableType,
3675 getConstants().placeholderInnerRef);
3682 ParseResult FIRStmtParser::parseRefForce() {
3683 auto startTok = consumeToken(FIRToken::lp_force);
3685 Value clock, pred, dest, src;
3686 if (parseExp(clock,
"expected clock expression in force") ||
3687 parseToken(FIRToken::comma,
"expected ','") ||
3688 parseExp(pred,
"expected predicate expression in force") ||
3689 parseToken(FIRToken::comma,
"expected ','") ||
3690 parseRefExp(dest,
"expected destination reference expression in force") ||
3691 parseToken(FIRToken::comma,
"expected ','") ||
3692 parseExp(src,
"expected source expression in force") ||
3693 parseToken(FIRToken::r_paren,
"expected ')' in force") ||
3694 parseOptionalInfo())
3698 auto ref = type_dyn_cast<RefType>(dest.getType());
3699 if (!ref || !ref.getForceable())
3702 "expected rwprobe-type expression for force destination, got ")
3704 auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(src.getType());
3706 return emitError(startTok.getLoc(),
3707 "expected base-type for force source, got ")
3709 if (!srcBaseType.isPassive())
3710 return emitError(startTok.getLoc(),
3711 "expected passive value for force source, got ")
3714 locationProcessor.setLoc(startTok.getLoc());
3717 auto noConstSrcType = srcBaseType.getAllConstDroppedType();
3718 if (noConstSrcType != ref.getType()) {
3720 auto compatibleRWProbe =
RefType::get(noConstSrcType,
true, ref.getLayer());
3722 dest = builder.create<RefCastOp>(compatibleRWProbe, dest);
3724 return emitError(startTok.getLoc(),
"incompatible force source of type ")
3725 << src.getType() <<
" cannot target destination "
3729 builder.create<RefForceOp>(clock, pred, dest, src);
3735 ParseResult FIRStmtParser::parseRefForceInitial() {
3736 auto startTok = consumeToken(FIRToken::lp_force_initial);
3740 dest,
"expected destination reference expression in force_initial") ||
3741 parseToken(FIRToken::comma,
"expected ','") ||
3742 parseExp(src,
"expected source expression in force_initial") ||
3743 parseToken(FIRToken::r_paren,
"expected ')' in force_initial") ||
3744 parseOptionalInfo())
3748 auto ref = type_dyn_cast<RefType>(dest.getType());
3749 if (!ref || !ref.getForceable())
3750 return emitError(startTok.getLoc(),
"expected rwprobe-type expression for "
3751 "force_initial destination, got ")
3753 auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(src.getType());
3755 return emitError(startTok.getLoc(),
3756 "expected base-type expression for force_initial "
3759 if (!srcBaseType.isPassive())
3760 return emitError(startTok.getLoc(),
3761 "expected passive value for force_initial source, got ")
3764 locationProcessor.setLoc(startTok.getLoc());
3767 auto noConstSrcType = srcBaseType.getAllConstDroppedType();
3768 if (noConstSrcType != ref.getType()) {
3770 auto compatibleRWProbe =
RefType::get(noConstSrcType,
true, ref.getLayer());
3772 dest = builder.create<RefCastOp>(compatibleRWProbe, dest);
3774 return emitError(startTok.getLoc(),
3775 "incompatible force_initial source of type ")
3776 << src.getType() <<
" cannot target destination "
3780 auto value = APInt::getAllOnes(1);
3783 value.getBitWidth(),
3784 IntegerType::Unsigned),
3786 auto pred = moduleContext.getCachedConstant(builder, attr, type, attr);
3787 builder.create<RefForceInitialOp>(pred, dest, src);
3793 ParseResult FIRStmtParser::parseRefRelease() {
3794 auto startTok = consumeToken(FIRToken::lp_release);
3796 Value clock, pred, dest;
3797 if (parseExp(clock,
"expected clock expression in release") ||
3798 parseToken(FIRToken::comma,
"expected ','") ||
3799 parseExp(pred,
"expected predicate expression in release") ||
3800 parseToken(FIRToken::comma,
"expected ','") ||
3802 "expected destination reference expression in release") ||
3803 parseToken(FIRToken::r_paren,
"expected ')' in release") ||
3804 parseOptionalInfo())
3808 if (
auto ref = type_dyn_cast<RefType>(dest.getType());
3809 !ref || !ref.getForceable())
3812 "expected rwprobe-type expression for release destination, got ")
3815 locationProcessor.setLoc(startTok.getLoc());
3817 builder.create<RefReleaseOp>(clock, pred, dest);
3823 ParseResult FIRStmtParser::parseRefReleaseInitial() {
3824 auto startTok = consumeToken(FIRToken::lp_release_initial);
3829 "expected destination reference expression in release_initial") ||
3830 parseToken(FIRToken::r_paren,
"expected ')' in release_initial") ||
3831 parseOptionalInfo())
3835 if (
auto ref = type_dyn_cast<RefType>(dest.getType());
3836 !ref || !ref.getForceable())
3837 return emitError(startTok.getLoc(),
"expected rwprobe-type expression for "
3838 "release_initial destination, got ")
3841 locationProcessor.setLoc(startTok.getLoc());
3843 auto value = APInt::getAllOnes(1);
3846 value.getBitWidth(),
3847 IntegerType::Unsigned),
3849 auto pred = moduleContext.getCachedConstant(builder, attr, type, attr);
3850 builder.create<RefReleaseInitialOp>(pred, dest);
3856 ParseResult FIRStmtParser::parseConnect() {
3857 auto startTok = consumeToken(FIRToken::kw_connect);
3858 auto loc = startTok.getLoc();
3861 if (parseExp(lhs,
"expected connect expression") ||
3862 parseToken(FIRToken::comma,
"expected ','") ||
3863 parseExp(rhs,
"expected connect expression") || parseOptionalInfo())
3866 auto lhsType = type_dyn_cast<FIRRTLBaseType>(lhs.getType());
3867 auto rhsType = type_dyn_cast<FIRRTLBaseType>(rhs.getType());
3868 if (!lhsType || !rhsType)
3869 return emitError(loc,
"cannot connect reference or property types");
3871 if (lhsType.containsReference() || rhsType.containsReference())
3872 return emitError(loc,
"cannot connect types containing references");
3875 return emitError(loc,
"cannot connect non-equivalent type ")
3876 << rhsType <<
" to " << lhsType;
3878 locationProcessor.setLoc(loc);
3884 ParseResult FIRStmtParser::parsePropAssign() {
3885 auto startTok = consumeToken(FIRToken::kw_propassign);
3886 auto loc = startTok.getLoc();
3889 if (parseExp(lhs,
"expected propassign expression") ||
3890 parseToken(FIRToken::comma,
"expected ','") ||
3891 parseExp(rhs,
"expected propassign expression") || parseOptionalInfo())
3894 auto lhsType = type_dyn_cast<PropertyType>(lhs.getType());
3895 auto rhsType = type_dyn_cast<PropertyType>(rhs.getType());
3896 if (!lhsType || !rhsType)
3897 return emitError(loc,
"can only propassign property types");
3898 locationProcessor.setLoc(loc);
3899 if (lhsType != rhsType) {
3901 if (isa<AnyRefType>(lhsType) && isa<ClassType>(rhsType))
3902 rhs = builder.create<ObjectAnyRefCastOp>(rhs);
3904 return emitError(loc,
"cannot propassign non-equivalent type ")
3905 << rhsType <<
" to " << lhsType;
3907 builder.create<PropAssignOp>(lhs, rhs);
3912 ParseResult FIRStmtParser::parseInvalidate() {
3913 auto startTok = consumeToken(FIRToken::kw_invalidate);
3918 auto loc = getToken().getLoc();
3920 if (parseId(
id,
"expected static reference expression") ||
3921 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
3926 if (!moduleContext.resolveSymbolEntry(lhs, symtabEntry, loc,
false)) {
3927 if (parseOptionalExpPostscript(lhs,
false) ||
3928 parseOptionalInfo())
3931 locationProcessor.setLoc(startTok.getLoc());
3932 emitInvalidate(lhs);
3941 if (getToken().isNot(FIRToken::period)) {
3942 locationProcessor.setLoc(loc);
3944 unsigned unbundledId = symtabEntry.get<
UnbundledID>() - 1;
3946 for (
auto elt : ubEntry)
3947 emitInvalidate(elt.second);
3953 StringRef fieldName;
3954 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
3955 parseFieldId(fieldName,
"expected field name") ||
3956 moduleContext.resolveSymbolEntry(lhs, symtabEntry, fieldName, loc))
3960 if (parseOptionalExpPostscript(lhs,
false) ||
3961 parseOptionalInfo())
3964 locationProcessor.setLoc(startTok.getLoc());
3965 emitInvalidate(lhs);
3969 ParseResult FIRStmtParser::parseLayerBlockOrGroup(
unsigned indent) {
3971 auto startTok = consumeToken();
3972 assert(startTok.isAny(FIRToken::kw_layerblock, FIRToken::kw_group) &&
3973 "consumed an unexpected token");
3974 auto loc = startTok.getLoc();
3977 if (parseId(
id,
"expected layer identifer") ||
3978 parseToken(FIRToken::colon,
"expected ':' at end of layer block") ||
3979 parseOptionalInfo())
3982 locationProcessor.setLoc(loc);
3984 StringRef rootLayer;
3985 SmallVector<FlatSymbolRefAttr> nestedLayers;
3989 rootLayer = layerSym.getRootReference();
3990 auto nestedRefs = layerSym.getNestedReferences();
3991 nestedLayers.append(nestedRefs.begin(), nestedRefs.end());
3995 auto layerBlockOp = builder.create<LayerBlockOp>(
3997 layerBlockOp->getRegion(0).push_back(
new Block());
3999 if (getIndentation() > indent)
4000 if (parseSubBlock(layerBlockOp.getRegion().front(), indent,
4001 layerBlockOp.getLayerName()))
4009 ParseResult FIRStmtParser::parseLeadingExpStmt(Value lhs) {
4010 auto loc = getToken().getLoc();
4013 if (consumeIf(FIRToken::kw_is)) {
4014 if (parseToken(FIRToken::kw_invalid,
"expected 'invalid'") ||
4015 parseOptionalInfo())
4018 if (removedFeature({3, 0, 0},
"'is invalid' statements", loc))
4021 locationProcessor.setLoc(loc);
4022 emitInvalidate(lhs);
4026 if (parseToken(FIRToken::less_equal,
"expected '<=' in statement"))
4029 if (removedFeature({3, 0, 0},
"'<=' connections", loc))
4033 if (parseExp(rhs,
"unexpected token in statement") || parseOptionalInfo())
4036 locationProcessor.setLoc(loc);
4038 auto lhsType = type_dyn_cast<FIRRTLBaseType>(lhs.getType());
4039 auto rhsType = type_dyn_cast<FIRRTLBaseType>(rhs.getType());
4040 if (!lhsType || !rhsType)
4041 return emitError(loc,
"cannot connect reference or property types");
4043 if (lhsType.containsReference() || rhsType.containsReference())
4044 return emitError(loc,
"cannot connect types containing references");
4047 return emitError(loc,
"cannot connect non-equivalent type ")
4048 << rhsType <<
" to " << lhsType;
4057 ParseResult FIRStmtParser::parseInstance() {
4058 auto startTok = consumeToken(FIRToken::kw_inst);
4062 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4066 StringRef moduleName;
4067 if (parseId(
id,
"expected instance name") ||
4068 parseToken(FIRToken::kw_of,
"expected 'of' in instance") ||
4069 parseId(moduleName,
"expected module name") || parseOptionalInfo())
4072 locationProcessor.setLoc(startTok.getLoc());
4075 auto referencedModule = getReferencedModule(startTok.getLoc(), moduleName);
4076 if (!referencedModule)
4079 SmallVector<PortInfo> modulePorts = referencedModule.getPorts();
4081 auto annotations = getConstants().emptyArrayAttr;
4082 SmallVector<Attribute, 4> portAnnotations(modulePorts.size(), annotations);
4084 hw::InnerSymAttr sym = {};
4085 auto result = builder.create<InstanceOp>(
4086 referencedModule, id, NameKindEnum::InterestingName,
4087 annotations.getValue(), portAnnotations,
false, sym);
4093 unbundledValueEntry.reserve(modulePorts.size());
4094 for (
size_t i = 0, e = modulePorts.size(); i != e; ++i)
4095 unbundledValueEntry.push_back({modulePorts[i].name, result.getResult(i)});
4099 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4100 auto entryId =
UnbundledID(moduleContext.unbundledValues.size());
4101 return moduleContext.addSymbolEntry(
id, entryId, startTok.getLoc());
4106 ParseResult FIRStmtParser::parseInstanceChoice() {
4107 auto startTok = consumeToken(FIRToken::kw_instchoice);
4108 SMLoc loc = startTok.getLoc();
4111 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4114 if (requireFeature({4, 0, 0},
"option groups/instance choices"))
4118 StringRef defaultModuleName;
4119 StringRef optionGroupName;
4120 if (parseId(
id,
"expected instance name") ||
4121 parseToken(FIRToken::kw_of,
"expected 'of' in instance") ||
4122 parseId(defaultModuleName,
"expected module name") ||
4123 parseToken(FIRToken::comma,
"expected ','") ||
4124 parseId(optionGroupName,
"expected option group name") ||
4125 parseToken(FIRToken::colon,
"expected ':' after instchoice") ||
4126 parseOptionalInfo())
4129 locationProcessor.setLoc(startTok.getLoc());
4133 auto defaultModule = getReferencedModule(loc, defaultModuleName);
4137 SmallVector<PortInfo> modulePorts = defaultModule.getPorts();
4140 auto optionGroup = circuitSymTbl.lookup<OptionOp>(optionGroupName);
4142 return emitError(loc,
4143 "use of undefined option group '" + optionGroupName +
"'");
4145 auto baseIndent = getIndentation();
4146 SmallVector<std::pair<OptionCaseOp, FModuleLike>> caseModules;
4147 while (getIndentation() == baseIndent) {
4149 StringRef caseModuleName;
4150 if (parseId(caseId,
"expected a case identifier") ||
4151 parseToken(FIRToken::equal_greater,
4152 "expected '=> in instance choice definition") ||
4153 parseId(caseModuleName,
"expected module name"))
4156 auto caseModule = getReferencedModule(loc, caseModuleName);
4160 for (
const auto &[defaultPort, casePort] :
4161 llvm::zip(modulePorts, caseModule.getPorts())) {
4162 if (defaultPort.name != casePort.name)
4163 return emitError(loc,
"instance case module port '")
4164 << casePort.name.getValue()
4165 <<
"' does not match the default module port '"
4166 << defaultPort.name.getValue() <<
"'";
4167 if (defaultPort.type != casePort.type)
4168 return emitError(loc,
"instance case port '")
4169 << casePort.name.getValue()
4170 <<
"' type does not match the default module port";
4174 dyn_cast_or_null<OptionCaseOp>(optionGroup.lookupSymbol(caseId));
4176 return emitError(loc,
"use of undefined option case '" + caseId +
"'");
4177 caseModules.emplace_back(optionCase, caseModule);
4180 auto annotations = getConstants().emptyArrayAttr;
4181 SmallVector<Attribute, 4> portAnnotations(modulePorts.size(), annotations);
4185 auto result = builder.create<InstanceChoiceOp>(
4186 defaultModule, caseModules, id, NameKindEnum::InterestingName,
4187 annotations.getValue(), portAnnotations, sym);
4191 unbundledValueEntry.reserve(modulePorts.size());
4192 for (
size_t i = 0, e = modulePorts.size(); i != e; ++i)
4193 unbundledValueEntry.push_back({modulePorts[i].name, result.getResult(i)});
4195 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4196 auto entryId =
UnbundledID(moduleContext.unbundledValues.size());
4197 return moduleContext.addSymbolEntry(
id, entryId, startTok.getLoc());
4200 FModuleLike FIRStmtParser::getReferencedModule(SMLoc loc,
4201 StringRef moduleName) {
4202 auto referencedModule = circuitSymTbl.lookup<FModuleLike>(moduleName);
4203 if (!referencedModule) {
4205 "use of undefined module name '" + moduleName +
"' in instance");
4208 if (isa<ClassOp /* ClassLike */>(referencedModule)) {
4209 emitError(loc,
"cannot create instance of class '" + moduleName +
4210 "', did you mean object?");
4213 return referencedModule;
4217 ParseResult FIRStmtParser::parseObject() {
4218 auto startTok = consumeToken(FIRToken::kw_object);
4222 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4229 StringRef className;
4230 if (parseId(
id,
"expected object name") ||
4231 parseToken(FIRToken::kw_of,
"expected 'of' in object") ||
4232 parseId(className,
"expected class name") || parseOptionalInfo())
4235 locationProcessor.setLoc(startTok.getLoc());
4238 const auto &classMap = getConstants().classMap;
4239 auto lookup = classMap.find(className);
4240 if (lookup == classMap.end())
4241 return emitError(startTok.getLoc(),
"use of undefined class name '" +
4242 className +
"' in object");
4243 auto referencedClass = lookup->getSecond();
4244 auto result = builder.create<ObjectOp>(referencedClass, id);
4245 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4249 ParseResult FIRStmtParser::parseCombMem() {
4251 auto startTok = consumeToken(FIRToken::kw_cmem);
4255 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4260 if (parseId(
id,
"expected cmem name") ||
4261 parseToken(FIRToken::colon,
"expected ':' in cmem") ||
4262 parseType(type,
"expected cmem type") || parseOptionalInfo())
4265 locationProcessor.setLoc(startTok.getLoc());
4268 auto vectorType = type_dyn_cast<FVectorType>(type);
4270 return emitError(
"cmem requires vector type");
4272 auto annotations = getConstants().emptyArrayAttr;
4273 StringAttr sym = {};
4274 auto result = builder.create<CombMemOp>(
4275 vectorType.getElementType(), vectorType.getNumElements(), id,
4276 NameKindEnum::InterestingName, annotations, sym);
4277 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4281 ParseResult FIRStmtParser::parseSeqMem() {
4283 auto startTok = consumeToken(FIRToken::kw_smem);
4287 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4292 RUWAttr ruw = RUWAttr::Undefined;
4294 if (parseId(
id,
"expected smem name") ||
4295 parseToken(FIRToken::colon,
"expected ':' in smem") ||
4299 if (consumeIf(FIRToken::comma)) {
4304 if (parseOptionalInfo()) {
4308 locationProcessor.setLoc(startTok.getLoc());
4311 auto vectorType = type_dyn_cast<FVectorType>(type);
4313 return emitError(
"smem requires vector type");
4315 auto annotations = getConstants().emptyArrayAttr;
4316 StringAttr sym = {};
4317 auto result = builder.create<SeqMemOp>(
4318 vectorType.getElementType(), vectorType.getNumElements(), ruw, id,
4319 NameKindEnum::InterestingName, annotations, sym);
4320 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4332 ParseResult FIRStmtParser::parseMem(
unsigned memIndent) {
4333 auto startTok = consumeToken(FIRToken::kw_mem);
4337 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4341 if (parseId(
id,
"expected mem name") ||
4342 parseToken(FIRToken::colon,
"expected ':' in mem") || parseOptionalInfo())
4346 int64_t depth = -1, readLatency = -1, writeLatency = -1;
4347 RUWAttr ruw = RUWAttr::Undefined;
4349 SmallVector<std::pair<StringAttr, Type>, 4> ports;
4353 auto nextIndent = getIndentation();
4354 if (!nextIndent || *nextIndent <= memIndent)
4357 auto spelling = getTokenSpelling();
4358 if (parseToken(FIRToken::identifier,
"unexpected token in 'mem'") ||
4359 parseToken(FIRToken::equal_greater,
"expected '=>' in 'mem'"))
4362 if (spelling ==
"data-type") {
4364 return emitError(
"'mem' type specified multiple times"), failure();
4366 if (
parseType(type,
"expected type in data-type declaration"))
4370 if (spelling ==
"depth") {
4371 if (parseIntLit(depth,
"expected integer in depth specification"))
4375 if (spelling ==
"read-latency") {
4376 if (parseIntLit(readLatency,
"expected integer latency"))
4380 if (spelling ==
"write-latency") {
4381 if (parseIntLit(writeLatency,
"expected integer latency"))
4385 if (spelling ==
"read-under-write") {
4386 if (getToken().isNot(FIRToken::kw_old, FIRToken::kw_new,
4387 FIRToken::kw_undefined))
4388 return emitError(
"expected specifier"), failure();
4390 if (parseOptionalRUW(ruw))
4395 MemOp::PortKind portKind;
4396 if (spelling ==
"reader")
4397 portKind = MemOp::PortKind::Read;
4398 else if (spelling ==
"writer")
4399 portKind = MemOp::PortKind::Write;
4400 else if (spelling ==
"readwriter")
4401 portKind = MemOp::PortKind::ReadWrite;
4403 return emitError(
"unexpected field in 'mem' declaration"), failure();
4406 if (parseId(portName,
"expected port name"))
4408 auto baseType = type_dyn_cast<FIRRTLBaseType>(type);
4410 return emitError(
"unexpected type, must be base type");
4411 ports.push_back({builder.getStringAttr(portName),
4412 MemOp::getTypeForPort(depth, baseType, portKind)});
4414 while (!getIndentation().has_value()) {
4415 if (parseId(portName,
"expected port name"))
4417 ports.push_back({builder.getStringAttr(portName),
4418 MemOp::getTypeForPort(depth, baseType, portKind)});
4429 llvm::array_pod_sort(ports.begin(), ports.end(),
4430 [](
const std::pair<StringAttr, Type> *lhs,
4431 const std::pair<StringAttr, Type> *rhs) ->
int {
4432 return lhs->first.getValue().compare(
4433 rhs->first.getValue());
4436 auto annotations = getConstants().emptyArrayAttr;
4437 SmallVector<Attribute, 4> resultNames;
4438 SmallVector<Type, 4> resultTypes;
4439 SmallVector<Attribute, 4> resultAnnotations;
4440 for (
auto p : ports) {
4441 resultNames.push_back(p.first);
4442 resultTypes.push_back(p.second);
4443 resultAnnotations.push_back(annotations);
4446 locationProcessor.setLoc(startTok.getLoc());
4448 auto result = builder.create<MemOp>(
4449 resultTypes, readLatency, writeLatency, depth, ruw,
4450 builder.getArrayAttr(resultNames), id, NameKindEnum::InterestingName,
4451 annotations, builder.getArrayAttr(resultAnnotations), hw::InnerSymAttr(),
4452 MemoryInitAttr(), StringAttr());
4455 unbundledValueEntry.reserve(result.getNumResults());
4456 for (
size_t i = 0, e = result.getNumResults(); i != e; ++i)
4457 unbundledValueEntry.push_back({resultNames[i], result.getResult(i)});
4459 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4460 auto entryID =
UnbundledID(moduleContext.unbundledValues.size());
4461 return moduleContext.addSymbolEntry(
id, entryID, startTok.getLoc());
4465 ParseResult FIRStmtParser::parseNode() {
4466 auto startTok = consumeToken(FIRToken::kw_node);
4470 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4475 if (parseId(
id,
"expected node name") ||
4476 parseToken(FIRToken::equal,
"expected '=' in node") ||
4477 parseExp(initializer,
"expected expression for node") ||
4478 parseOptionalInfo())
4481 locationProcessor.setLoc(startTok.getLoc());
4493 auto initializerType = type_cast<FIRRTLType>(initializer.getType());
4494 auto initializerBaseType =
4495 type_dyn_cast<FIRRTLBaseType>(initializer.getType());
4496 if (type_isa<AnalogType>(initializerType) ||
4497 !(initializerBaseType && initializerBaseType.isPassive())) {
4498 emitError(startTok.getLoc())
4499 <<
"Node cannot be analog and must be passive or passive under a flip "
4500 << initializer.getType();
4504 auto annotations = getConstants().emptyArrayAttr;
4505 StringAttr sym = {};
4507 auto result = builder.create<NodeOp>(
4508 initializer, id, NameKindEnum::InterestingName, annotations, sym);
4509 return moduleContext.addSymbolEntry(
id, result.getResult(),
4514 ParseResult FIRStmtParser::parseWire() {
4515 auto startTok = consumeToken(FIRToken::kw_wire);
4519 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4524 if (parseId(
id,
"expected wire name") ||
4525 parseToken(FIRToken::colon,
"expected ':' in wire") ||
4526 parseType(type,
"expected wire type") || parseOptionalInfo())
4529 locationProcessor.setLoc(startTok.getLoc());
4531 auto annotations = getConstants().emptyArrayAttr;
4532 StringAttr sym = {};
4535 auto namekind = isa<PropertyType, RefType>(type)
4536 ? NameKindEnum::DroppableName
4537 : NameKindEnum::InterestingName;
4539 auto result = builder.create<WireOp>(type, id, namekind, annotations, sym);
4540 return moduleContext.addSymbolEntry(
id, result.getResult(),
4554 ParseResult FIRStmtParser::parseRegister(
unsigned regIndent) {
4555 auto startTok = consumeToken(FIRToken::kw_reg);
4559 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4568 if (parseId(
id,
"expected reg name") ||
4569 parseToken(FIRToken::colon,
"expected ':' in reg") ||
4571 parseToken(FIRToken::comma,
"expected ','") ||
4572 parseExp(clock,
"expected expression for register clock"))
4575 if (!type_isa<FIRRTLBaseType>(type))
4576 return emitError(startTok.getLoc(),
"register must have base type");
4579 Value resetSignal, resetValue;
4580 if (consumeIf(FIRToken::kw_with)) {
4581 if (removedFeature({3, 0, 0},
"'reg with' registers"))
4584 if (parseToken(FIRToken::colon,
"expected ':' in reg"))
4592 bool hasExtraLParen = consumeIf(FIRToken::l_paren);
4594 auto indent = getIndentation();
4595 if (!indent || *indent <= regIndent)
4596 if (!hasExtraLParen)
4597 return emitError(
"expected indented reset specifier in reg"), failure();
4599 if (parseToken(FIRToken::kw_reset,
"expected 'reset' in reg") ||
4600 parseToken(FIRToken::equal_greater,
"expected => in reset specifier") ||
4601 parseToken(FIRToken::l_paren,
"expected '(' in reset specifier") ||
4602 parseExp(resetSignal,
"expected expression for reset signal") ||
4603 parseToken(FIRToken::comma,
"expected ','"))
4611 if (getTokenSpelling() ==
id) {
4613 if (parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4615 resetSignal = Value();
4617 if (parseExp(resetValue,
"expected expression for reset value") ||
4618 parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4622 if (hasExtraLParen &&
4623 parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4629 if (parseOptionalInfo())
4632 locationProcessor.setLoc(startTok.getLoc());
4634 ArrayAttr annotations = getConstants().emptyArrayAttr;
4636 StringAttr sym = {};
4640 .create<RegResetOp>(type, clock, resetSignal, resetValue, id,
4641 NameKindEnum::InterestingName, annotations, sym)
4645 .create<RegOp>(type, clock, id, NameKindEnum::InterestingName,
4648 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4656 ParseResult FIRStmtParser::parseRegisterWithReset() {
4657 auto startTok = consumeToken(FIRToken::kw_regreset);
4661 Value clock, resetSignal, resetValue;
4663 if (parseId(
id,
"expected reg name") ||
4664 parseToken(FIRToken::colon,
"expected ':' in reg") ||
4666 parseToken(FIRToken::comma,
"expected ','") ||
4667 parseExp(clock,
"expected expression for register clock") ||
4668 parseToken(FIRToken::comma,
"expected ','") ||
4669 parseExp(resetSignal,
"expected expression for register reset") ||
4670 parseToken(FIRToken::comma,
"expected ','") ||
4671 parseExp(resetValue,
"expected expression for register reset value") ||
4672 parseOptionalInfo())
4675 if (!type_isa<FIRRTLBaseType>(type))
4676 return emitError(startTok.getLoc(),
"register must have base type");
4678 locationProcessor.setLoc(startTok.getLoc());
4682 .create<RegResetOp>(type, clock, resetSignal, resetValue, id,
4683 NameKindEnum::InterestingName,
4684 getConstants().emptyArrayAttr, StringAttr{})
4687 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4697 struct FIRCircuitParser :
public FIRParser {
4698 explicit FIRCircuitParser(SharedParserConstants &state,
FIRLexer &lexer,
4700 : FIRParser(state, lexer, version), mlirModule(mlirModule) {}
4703 parseCircuit(SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBuf,
4704 SmallVectorImpl<const llvm::MemoryBuffer *> &omirBuf,
4705 mlir::TimingScope &ts);
4710 ParseResult importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
4711 SmallVectorImpl<Attribute> &attrs);
4715 ParseResult importOMIR(CircuitOp circuit, SMLoc loc, StringRef annotationStr,
4716 SmallVectorImpl<Attribute> &attrs);
4718 ParseResult parseToplevelDefinition(CircuitOp circuit,
unsigned indent);
4720 ParseResult parseClass(CircuitOp circuit,
unsigned indent);
4721 ParseResult parseExtClass(CircuitOp circuit,
unsigned indent);
4722 ParseResult parseExtModule(CircuitOp circuit,
unsigned indent);
4723 ParseResult parseIntModule(CircuitOp circuit,
unsigned indent);
4724 ParseResult parseModule(CircuitOp circuit,
bool isPublic,
unsigned indent);
4725 ParseResult parseFormal(CircuitOp circuit,
unsigned indent);
4727 ParseResult parseLayerName(SymbolRefAttr &result);
4728 ParseResult parseOptionalEnabledLayers(ArrayAttr &result);
4729 ParseResult
parsePortList(SmallVectorImpl<PortInfo> &resultPorts,
4730 SmallVectorImpl<SMLoc> &resultPortLocs,
4733 ParseResult parseRefList(ArrayRef<PortInfo> portList,
4734 ArrayAttr &internalPathsResult);
4736 ParseResult skipToModuleEnd(
unsigned indent);
4738 ParseResult parseTypeDecl();
4740 ParseResult parseOptionDecl(CircuitOp circuit);
4742 ParseResult parseLayer(CircuitOp circuit);
4744 struct DeferredModuleToParse {
4745 FModuleLike moduleOp;
4746 SmallVector<SMLoc> portLocs;
4751 ParseResult parseModuleBody(
const SymbolTable &circuitSymTbl,
4752 DeferredModuleToParse &deferredModule,
4753 InnerSymFixups &fixups);
4755 SmallVector<DeferredModuleToParse, 0> deferredModules;
4757 SmallVector<InnerSymFixups, 0> moduleFixups;
4759 hw::InnerSymbolNamespaceCollection innerSymbolNamespaces;
4761 ModuleOp mlirModule;
4766 FIRCircuitParser::importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
4767 SmallVectorImpl<Attribute> &attrs) {
4769 auto annotations = json::parse(annotationsStr);
4770 if (
auto err = annotations.takeError()) {
4771 handleAllErrors(std::move(err), [&](
const json::ParseError &a) {
4772 auto diag = emitError(loc,
"Failed to parse JSON Annotations");
4773 diag.attachNote() << a.message();
4778 json::Path::Root root;
4779 llvm::StringMap<ArrayAttr> thisAnnotationMap;
4782 auto diag = emitError(loc,
"Invalid/unsupported annotation format");
4783 std::string jsonErrorMessage =
4784 "See inline comments for problem area in JSON:\n";
4785 llvm::raw_string_ostream s(jsonErrorMessage);
4786 root.printErrorContext(annotations.get(), s);
4787 diag.attachNote() << jsonErrorMessage;
4794 ParseResult FIRCircuitParser::importOMIR(CircuitOp circuit, SMLoc loc,
4795 StringRef annotationsStr,
4796 SmallVectorImpl<Attribute> &annos) {
4798 auto annotations = json::parse(annotationsStr);
4799 if (
auto err = annotations.takeError()) {
4800 handleAllErrors(std::move(err), [&](
const json::ParseError &a) {
4801 auto diag = emitError(loc,
"Failed to parse OMIR file");
4802 diag.attachNote() << a.message();
4807 json::Path::Root root;
4808 if (!
fromOMIRJSON(annotations.get(), annos, root, circuit.getContext())) {
4809 auto diag = emitError(loc,
"Invalid/unsupported OMIR format");
4810 std::string jsonErrorMessage =
4811 "See inline comments for problem area in JSON:\n";
4812 llvm::raw_string_ostream s(jsonErrorMessage);
4813 root.printErrorContext(annotations.get(), s);
4814 diag.attachNote() << jsonErrorMessage;
4821 ParseResult FIRCircuitParser::parseLayerName(SymbolRefAttr &result) {
4822 auto *context = getContext();
4823 SmallVector<StringRef> strings;
4826 if (parseId(name,
"expected layer name"))
4828 strings.push_back(name);
4829 }
while (consumeIf(FIRToken::period));
4831 SmallVector<FlatSymbolRefAttr> nested;
4832 nested.reserve(strings.size() - 1);
4833 for (
unsigned i = 1, e = strings.size(); i < e; ++i)
4840 ParseResult FIRCircuitParser::parseOptionalEnabledLayers(ArrayAttr &result) {
4841 if (getToken().getKind() != FIRToken::kw_enablelayer) {
4846 if (requireFeature({4, 0, 0},
"modules with layers enabled"))
4849 SmallVector<Attribute> layers;
4851 SymbolRefAttr layer;
4853 if (parseLayerName(layer))
4855 layers.push_back(layer);
4856 }
while (getToken().getKind() == FIRToken::kw_enablelayer);
4867 SmallVectorImpl<SMLoc> &resultPortLocs,
4870 while (getToken().isAny(FIRToken::kw_input, FIRToken::kw_output) &&
4872 getIndentation() > indent) {
4878 auto backtrackState = getLexer().getCursor();
4880 bool isOutput = getToken().is(FIRToken::kw_output);
4885 if (!getToken().isAny(FIRToken::identifier, FIRToken::literal_identifier) &&
4886 !getToken().isKeyword()) {
4887 backtrackState.restore(getLexer());
4893 LocWithInfo info(getToken().getLoc(),
this);
4894 if (parseId(name,
"expected port name") ||
4895 parseToken(FIRToken::colon,
"expected ':' in port definition") ||
4896 parseType(type,
"expected a type in port declaration") ||
4897 info.parseOptionalInfo())
4900 StringAttr innerSym = {};
4901 resultPorts.push_back(
4902 {name, type,
direction::get(isOutput), innerSym, info.getLoc()});
4903 resultPortLocs.push_back(info.getFIRLoc());
4908 for (
auto portAndLoc : llvm::zip(resultPorts, resultPortLocs)) {
4909 PortInfo &port = std::get<0>(portAndLoc);
4910 auto &entry = portIds[port.
name];
4911 if (!entry.isValid()) {
4912 entry = std::get<1>(portAndLoc);
4916 emitError(std::get<1>(portAndLoc),
4917 "redefinition of name '" + port.
getName() +
"'")
4918 .attachNote(translateLocation(entry))
4919 <<
"previous definition here";
4928 ParseResult FIRCircuitParser::parseRefList(ArrayRef<PortInfo> portList,
4929 ArrayAttr &internalPathsResult) {
4930 struct RefStatementInfo {
4932 InternalPathAttr resolvedPath;
4936 SmallVector<RefStatementInfo> refStatements;
4937 SmallPtrSet<StringAttr, 8> seenNames;
4938 SmallPtrSet<StringAttr, 8> seenRefs;
4941 if (getToken().is(FIRToken::kw_ref) &&
4942 removedFeature({4, 0, 0},
"ref statements"))
4946 while (consumeIf(FIRToken::kw_ref)) {
4947 auto loc = getToken().getLoc();
4951 if (parseId(refName,
"expected ref name"))
4953 if (consumeIf(FIRToken::period) || consumeIf(FIRToken::l_square))
4955 loc,
"ref statements for aggregate elements not yet supported");
4956 if (parseToken(FIRToken::kw_is,
"expected 'is' in ref statement"))
4959 if (!seenRefs.insert(refName).second)
4960 return emitError(loc,
"duplicate ref statement for '" + refName.strref() +
4963 auto kind = getToken().getKind();
4964 if (kind != FIRToken::string)
4965 return emitError(loc,
"expected string in ref statement");
4969 consumeToken(FIRToken::string);
4971 refStatements.push_back(RefStatementInfo{refName, resolved, loc});
4975 SmallVector<Attribute> internalPaths(portList.size(),
4978 llvm::SmallBitVector usedRefs(refStatements.size());
4979 size_t matchedPaths = 0;
4980 for (
auto [idx, port] : llvm::enumerate(portList)) {
4981 if (!type_isa<RefType>(port.
type))
4987 return mlir::emitError(
4989 "references in ports must be output on extmodule and intmodule");
4991 llvm::find_if(refStatements, [pname = port.
name](
const auto &r) {
4992 return r.refName == pname;
4995 if (refStmtIt == refStatements.end()) {
4996 if (!refStatements.empty())
4997 return mlir::emitError(port.
loc,
"no ref statement found for ref port ")
5002 usedRefs.set(std::distance(refStatements.begin(), refStmtIt));
5003 internalPaths[idx] = refStmtIt->resolvedPath;
5007 if (!refStatements.empty() && matchedPaths != refStatements.size()) {
5008 assert(matchedPaths < refStatements.size());
5010 auto idx = usedRefs.find_first_unset();
5012 return emitError(refStatements[idx].loc,
"unused ref statement");
5016 internalPathsResult =
ArrayAttr::get(getContext(), internalPaths);
5022 ParseResult FIRCircuitParser::skipToModuleEnd(
unsigned indent) {
5024 switch (getToken().getKind()) {
5028 case FIRToken::error:
5032 case FIRToken::kw_class:
5033 case FIRToken::kw_declgroup:
5034 case FIRToken::kw_extclass:
5035 case FIRToken::kw_extmodule:
5036 case FIRToken::kw_intmodule:
5037 case FIRToken::kw_formal:
5038 case FIRToken::kw_module:
5039 case FIRToken::kw_public:
5040 case FIRToken::kw_layer:
5041 case FIRToken::kw_option:
5042 case FIRToken::kw_type:
5046 if (getIndentation() == indent)
5059 SmallVector<Attribute, 8> parameters;
5060 SmallPtrSet<StringAttr, 8> seen;
5061 while (consumeIf(FIRToken::kw_parameter)) {
5065 if (parseParameter(name, value, loc))
5067 if (!seen.insert(name).second)
5068 return emitError(loc,
5069 "redefinition of parameter '" + name.getValue() +
"'");
5077 ParseResult FIRCircuitParser::parseClass(CircuitOp circuit,
unsigned indent) {
5079 SmallVector<PortInfo, 8> portList;
5080 SmallVector<SMLoc> portLocs;
5081 LocWithInfo info(getToken().getLoc(),
this);
5086 consumeToken(FIRToken::kw_class);
5087 if (parseId(name,
"expected class name") ||
5088 parseToken(FIRToken::colon,
"expected ':' in class definition") ||
5089 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5092 if (name == circuit.getName())
5093 return mlir::emitError(info.getLoc(),
5094 "class cannot be the top of a circuit");
5096 for (
auto &portInfo : portList)
5097 if (!isa<PropertyType>(portInfo.type))
5098 return mlir::emitError(portInfo.loc,
5099 "ports on classes must be properties");
5102 auto builder = circuit.getBodyBuilder();
5103 auto classOp = builder.create<ClassOp>(info.getLoc(), name, portList);
5104 classOp.setPrivate();
5105 deferredModules.emplace_back(
5106 DeferredModuleToParse{classOp, portLocs, getLexer().getCursor(), indent});
5109 getConstants().classMap[name.getValue()] = classOp;
5110 return skipToModuleEnd(indent);
5114 ParseResult FIRCircuitParser::parseExtClass(CircuitOp circuit,
5117 SmallVector<PortInfo, 8> portList;
5118 SmallVector<SMLoc> portLocs;
5119 LocWithInfo info(getToken().getLoc(),
this);
5124 consumeToken(FIRToken::kw_extclass);
5125 if (parseId(name,
"expected extclass name") ||
5126 parseToken(FIRToken::colon,
"expected ':' in extclass definition") ||
5127 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5130 if (name == circuit.getName())
5131 return mlir::emitError(info.getLoc(),
5132 "extclass cannot be the top of a circuit");
5134 for (
auto &portInfo : portList)
5135 if (!isa<PropertyType>(portInfo.type))
5136 return mlir::emitError(portInfo.loc,
5137 "ports on extclasses must be properties");
5140 auto builder = circuit.getBodyBuilder();
5141 auto extClassOp = builder.create<ExtClassOp>(info.getLoc(), name, portList);
5144 getConstants().classMap[name.getValue()] = extClassOp;
5145 return skipToModuleEnd(indent);
5152 ParseResult FIRCircuitParser::parseExtModule(CircuitOp circuit,
5156 SmallVector<PortInfo, 8> portList;
5157 SmallVector<SMLoc> portLocs;
5158 LocWithInfo info(getToken().getLoc(),
this);
5159 consumeToken(FIRToken::kw_extmodule);
5160 if (parseId(name,
"expected extmodule name") ||
5161 parseOptionalEnabledLayers(layers) ||
5162 parseToken(FIRToken::colon,
"expected ':' in extmodule definition") ||
5163 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5167 if (consumeIf(FIRToken::kw_defname)) {
5168 if (parseToken(FIRToken::equal,
"expected '=' in defname") ||
5169 parseId(defName,
"expected defname name"))
5173 ArrayAttr parameters;
5174 ArrayAttr internalPaths;
5179 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
5180 if (
auto ftype = type_dyn_cast<FIRRTLType>(pi.type)) {
5181 if (ftype.hasUninferredWidth())
5182 return emitError(loc,
"extmodule port must have known width");
5187 auto builder = circuit.getBodyBuilder();
5188 auto isMainModule = (name == circuit.getName());
5190 (isMainModule && getConstants().options.scalarizePublicModules) ||
5191 getConstants().options.scalarizeExtModules
5192 ? Convention::Scalarized
5193 : Convention::Internal;
5196 auto extModuleOp = builder.create<FExtModuleOp>(
5197 info.getLoc(), name, conventionAttr, portList, defName, annotations,
5198 parameters, internalPaths, layers);
5199 auto visibility = isMainModule ? SymbolTable::Visibility::Public
5200 : SymbolTable::Visibility::Private;
5201 SymbolTable::setSymbolVisibility(extModuleOp, visibility);
5209 ParseResult FIRCircuitParser::parseIntModule(CircuitOp circuit,
5214 SmallVector<PortInfo, 8> portList;
5215 SmallVector<SMLoc> portLocs;
5216 LocWithInfo info(getToken().getLoc(),
this);
5217 consumeToken(FIRToken::kw_intmodule);
5218 if (parseId(name,
"expected intmodule name") ||
5219 parseOptionalEnabledLayers(layers) ||
5220 parseToken(FIRToken::colon,
"expected ':' in intmodule definition") ||
5221 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent) ||
5222 parseToken(FIRToken::kw_intrinsic,
"expected 'intrinsic'") ||
5223 parseToken(FIRToken::equal,
"expected '=' in intrinsic") ||
5224 parseId(intName,
"expected intrinsic name"))
5227 ArrayAttr parameters;
5228 ArrayAttr internalPaths;
5232 ArrayAttr annotations = getConstants().emptyArrayAttr;
5233 auto builder = circuit.getBodyBuilder();
5235 .create<FIntModuleOp>(info.getLoc(), name, portList, intName, annotations,
5236 parameters, internalPaths, layers)
5242 ParseResult FIRCircuitParser::parseModule(CircuitOp circuit,
bool isPublic,
5245 SmallVector<PortInfo, 8> portList;
5246 SmallVector<SMLoc> portLocs;
5248 auto modLoc = getToken().getLoc();
5249 LocWithInfo info(modLoc,
this);
5250 consumeToken(FIRToken::kw_module);
5251 if (parseId(name,
"expected module name") ||
5252 parseOptionalEnabledLayers(layers) ||
5253 parseToken(FIRToken::colon,
"expected ':' in module definition") ||
5254 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5258 if (name == circuit.getName()) {
5259 if (!isPublic && removedFeature({4, 0, 0},
"private main modules", modLoc))
5264 if (isPublic && version >=
FIRVersion{4, 0, 0}) {
5265 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
5266 if (
auto ftype = type_dyn_cast<FIRRTLType>(pi.type)) {
5267 if (ftype.hasUninferredWidth())
5268 return emitError(loc,
"public module port must have known width");
5269 if (ftype.hasUninferredReset())
5270 return emitError(loc,
5271 "public module port must have concrete reset type");
5276 ArrayAttr annotations = getConstants().emptyArrayAttr;
5277 auto convention = Convention::Internal;
5278 if (isPublic && getConstants().options.scalarizePublicModules)
5279 convention = Convention::Scalarized;
5280 if (!isPublic && getConstants().options.scalarizeInternalModules)
5281 convention = Convention::Scalarized;
5283 auto builder = circuit.getBodyBuilder();
5284 auto moduleOp = builder.create<FModuleOp>(info.getLoc(), name, conventionAttr,
5285 portList, annotations, layers);
5287 auto visibility = isPublic ? SymbolTable::Visibility::Public
5288 : SymbolTable::Visibility::Private;
5289 SymbolTable::setSymbolVisibility(moduleOp, visibility);
5293 deferredModules.emplace_back(DeferredModuleToParse{
5294 moduleOp, portLocs, getLexer().getCursor(), indent});
5296 if (skipToModuleEnd(indent))
5301 ParseResult FIRCircuitParser::parseFormal(CircuitOp circuit,
unsigned indent) {
5302 consumeToken(FIRToken::kw_formal);
5303 StringRef id, moduleName, boundSpelling;
5305 LocWithInfo info(getToken().getLoc(),
this);
5308 if (parseId(
id,
"expected a formal test name") ||
5309 parseToken(FIRToken::kw_of,
5310 "expected keyword 'of' after formal test name") ||
5311 parseId(moduleName,
"expected the name of a module") ||
5312 parseToken(FIRToken::comma,
"expected ','") ||
5313 parseGetSpelling(boundSpelling) ||
5314 parseToken(FIRToken::identifier,
5315 "expected parameter 'bound' after ','") ||
5316 parseToken(FIRToken::equal,
"expected '=' after 'bound'") ||
5317 parseIntLit(bound,
"expected integer in bound specification") ||
5318 info.parseOptionalInfo())
5322 if (boundSpelling !=
"bound" || bound <= 0)
5323 return emitError(
"Invalid parameter given to formal test: ")
5324 << boundSpelling <<
" = " << bound,
5328 auto builder = circuit.getBodyBuilder();
5329 builder.create<firrtl::FormalOp>(info.getLoc(), id, moduleName, bound);
5334 ParseResult FIRCircuitParser::parseToplevelDefinition(CircuitOp circuit,
5336 switch (getToken().getKind()) {
5337 case FIRToken::kw_class:
5338 return parseClass(circuit, indent);
5339 case FIRToken::kw_declgroup:
5340 if (requireFeature({3, 2, 0},
"optional groups") ||
5341 removedFeature({4, 0, 0},
"optional groups"))
5343 return parseLayer(circuit);
5344 case FIRToken::kw_extclass:
5345 return parseExtClass(circuit, indent);
5346 case FIRToken::kw_extmodule:
5347 return parseExtModule(circuit, indent);
5348 case FIRToken::kw_formal:
5349 if (requireFeature({4, 0, 0},
"inline formal tests"))
5351 return parseFormal(circuit, indent);
5352 case FIRToken::kw_intmodule:
5353 if (removedFeature({4, 0, 0},
"intrinsic modules"))
5355 return parseIntModule(circuit, indent);
5356 case FIRToken::kw_layer:
5357 if (requireFeature({4, 0, 0},
"layers"))
5359 return parseLayer(circuit);
5360 case FIRToken::kw_module:
5361 return parseModule(circuit,
false, indent);
5362 case FIRToken::kw_public:
5363 if (requireFeature({4, 0, 0},
"public modules"))
5366 if (getToken().getKind() == FIRToken::kw_module)
5367 return parseModule(circuit,
true, indent);
5368 return emitError(getToken().getLoc(),
"only modules may be public");
5369 case FIRToken::kw_type:
5370 return parseTypeDecl();
5371 case FIRToken::kw_option:
5372 if (requireFeature({4, 0, 0},
"option groups/instance choices"))
5374 return parseOptionDecl(circuit);
5376 return emitError(getToken().getLoc(),
"unknown toplevel definition");
5381 ParseResult FIRCircuitParser::parseTypeDecl() {
5385 auto loc = getToken().getLoc();
5387 if (getToken().isKeyword())
5388 return emitError(loc) <<
"cannot use keyword '" << getToken().getSpelling()
5389 <<
"' for type alias name";
5391 if (parseId(
id,
"expected type name") ||
5392 parseToken(FIRToken::equal,
"expected '=' in type decl") ||
5398 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type))
5402 <<
"type alias for non-base type " << type
5403 <<
" is currently not supported. Type alias is stripped immediately";
5405 if (!getConstants().aliasMap.insert({id, type}).second)
5406 return emitError(loc) <<
"type alias `" << name.getValue()
5407 <<
"` is already defined";
5412 ParseResult FIRCircuitParser::parseOptionDecl(CircuitOp circuit) {
5415 auto loc = getToken().getLoc();
5417 LocWithInfo info(getToken().getLoc(),
this);
5418 if (parseId(
id,
"expected an option group name") ||
5419 parseToken(FIRToken::colon,
5420 "expected ':' after option group definition") ||
5421 info.parseOptionalInfo())
5424 auto builder = OpBuilder::atBlockEnd(circuit.getBodyBlock());
5425 auto optionOp = builder.create<OptionOp>(info.getLoc(), id);
5426 auto *block =
new Block;
5427 optionOp.getBody().push_back(block);
5428 builder.setInsertionPointToEnd(block);
5430 auto baseIndent = getIndentation();
5432 while (getIndentation() == baseIndent) {
5434 LocWithInfo caseInfo(getToken().getLoc(),
this);
5435 if (parseId(
id,
"expected an option case ID") ||
5436 caseInfo.parseOptionalInfo())
5439 if (!cases.insert(
id).second)
5440 return emitError(loc)
5441 <<
"duplicate option case definition '" <<
id <<
"'";
5443 builder.create<OptionCaseOp>(caseInfo.getLoc(), id);
5450 ParseResult FIRCircuitParser::parseLayer(CircuitOp circuit) {
5451 auto baseIndent = getIndentation();
5454 SmallVector<std::pair<std::optional<unsigned>, LayerOp>> layerStack;
5457 auto parseOne = [&](
Block *block) -> ParseResult {
5458 auto indent = getIndentation();
5459 StringRef id, convention;
5460 LocWithInfo info(getToken().getLoc(),
this);
5462 if (parseId(
id,
"expected layer name") ||
5463 parseToken(FIRToken::comma,
"expected ','") ||
5464 parseGetSpelling(convention))
5467 auto layerConvention = symbolizeLayerConvention(convention);
5468 if (!layerConvention) {
5469 emitError() <<
"unknown convention '" << convention
5470 <<
"' (did you misspell it?)";
5475 hw::OutputFileAttr outputDir;
5476 if (consumeIf(FIRToken::comma)) {
5477 if (getToken().getKind() == FIRToken::string) {
5478 auto text = getToken().getStringValue();
5480 return emitError() <<
"output directory must not be blank";
5481 outputDir = hw::OutputFileAttr::getAsDirectory(getContext(), text);
5482 consumeToken(FIRToken::string);
5486 if (parseToken(FIRToken::colon,
"expected ':' after layer definition") ||
5487 info.parseOptionalInfo())
5489 auto builder = OpBuilder::atBlockEnd(block);
5491 auto layerOp = builder.create<LayerOp>(info.getLoc(), id, *layerConvention);
5492 layerOp->getRegion(0).push_back(
new Block());
5494 layerOp->setAttr(
"output_file", outputDir);
5495 layerStack.push_back({indent, layerOp});
5499 if (parseOne(circuit.getBodyBlock()))
5503 while (getIndentation() > baseIndent) {
5504 switch (getToken().getKind()) {
5505 case FIRToken::kw_declgroup:
5506 case FIRToken::kw_layer: {
5509 while (layerStack.back().first >= getIndentation())
5510 layerStack.pop_back();
5511 auto parentLayer = layerStack.back().second;
5512 if (parseOne(&parentLayer.getBody().front()))
5517 return emitError(
"expected 'layer'"), failure();
5526 FIRCircuitParser::parseModuleBody(
const SymbolTable &circuitSymTbl,
5527 DeferredModuleToParse &deferredModule,
5528 InnerSymFixups &fixups) {
5529 FModuleLike moduleOp = deferredModule.moduleOp;
5530 auto &body = moduleOp->getRegion(0).front();
5531 auto &portLocs = deferredModule.portLocs;
5535 FIRLexer moduleBodyLexer(getLexer().getSourceMgr(), getContext());
5538 deferredModule.lexerCursor.restore(moduleBodyLexer);
5540 FIRModuleContext moduleContext(getConstants(), moduleBodyLexer, version);
5544 auto portList = moduleOp.getPorts();
5545 auto portArgs = body.getArguments();
5546 for (
auto tuple : llvm::zip(portList, portLocs, portArgs)) {
5547 PortInfo &port = std::get<0>(tuple);
5548 llvm::SMLoc loc = std::get<1>(tuple);
5549 BlockArgument portArg = std::get<2>(tuple);
5551 if (moduleContext.addSymbolEntry(port.
getName(), portArg, loc))
5555 FIRStmtParser stmtParser(body, moduleContext, fixups, circuitSymTbl, version);
5558 auto result = stmtParser.parseSimpleStmtBlock(deferredModule.indent);
5564 size_t numVerifPrintfs = 0;
5565 std::optional<Location> printfLoc;
5567 deferredModule.moduleOp.walk([&](PrintFOp printFOp) {
5572 printfLoc = printFOp.getLoc();
5575 if (numVerifPrintfs > 0) {
5577 mlir::emitError(deferredModule.moduleOp.getLoc(),
"module contains ")
5579 <<
" printf-encoded verification operation(s), which are no longer "
5581 diag.attachNote(*printfLoc)
5582 <<
"example printf here, this is now just a printf and nothing more";
5583 diag.attachNote() <<
"For more information, see "
5584 "https://github.com/llvm/circt/issues/6970";
5600 ParseResult FIRCircuitParser::parseCircuit(
5601 SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBufs,
5602 SmallVectorImpl<const llvm::MemoryBuffer *> &omirBufs,
5603 mlir::TimingScope &ts) {
5605 auto indent = getIndentation();
5606 if (parseToken(FIRToken::kw_FIRRTL,
"expected 'FIRRTL'"))
5608 if (!indent.has_value())
5609 return emitError(
"'FIRRTL' must be first token on its line");
5610 if (parseToken(FIRToken::kw_version,
"expected version after 'FIRRTL'") ||
5611 parseVersionLit(
"expected version literal"))
5613 indent = getIndentation();
5615 if (!indent.has_value())
5616 return emitError(
"'circuit' must be first token on its line");
5617 unsigned circuitIndent = *indent;
5619 LocWithInfo info(getToken().getLoc(),
this);
5621 SMLoc inlineAnnotationsLoc;
5622 StringRef inlineAnnotations;
5625 if (parseToken(FIRToken::kw_circuit,
5626 "expected a top-level 'circuit' definition") ||
5627 parseId(name,
"expected circuit name") ||
5628 parseToken(FIRToken::colon,
"expected ':' in circuit definition") ||
5629 parseOptionalAnnotations(inlineAnnotationsLoc, inlineAnnotations) ||
5630 info.parseOptionalInfo())
5634 OpBuilder b(mlirModule.getBodyRegion());
5635 auto circuit = b.create<CircuitOp>(info.getLoc(), name);
5638 auto parseAnnotationTimer = ts.nest(
"Parse annotations");
5644 SmallVector<Attribute> annos;
5645 if (!inlineAnnotations.empty())
5646 if (importAnnotationsRaw(inlineAnnotationsLoc, inlineAnnotations, annos))
5650 for (
auto *annotationsBuf : annotationsBufs)
5651 if (importAnnotationsRaw(info.getFIRLoc(), annotationsBuf->getBuffer(),
5655 parseAnnotationTimer.stop();
5656 auto parseOMIRTimer = ts.nest(
"Parse OMIR");
5660 for (
auto *omirBuf : omirBufs)
5661 if (importOMIR(circuit, info.getFIRLoc(), omirBuf->getBuffer(), annos))
5664 parseOMIRTimer.stop();
5672 auto parseTimer = ts.nest(
"Parse modules");
5673 deferredModules.reserve(16);
5677 switch (getToken().getKind()) {
5685 case FIRToken::error:
5689 emitError(
"unexpected token in circuit");
5692 case FIRToken::kw_class:
5693 case FIRToken::kw_declgroup:
5694 case FIRToken::kw_extclass:
5695 case FIRToken::kw_extmodule:
5696 case FIRToken::kw_intmodule:
5697 case FIRToken::kw_layer:
5698 case FIRToken::kw_formal:
5699 case FIRToken::kw_module:
5700 case FIRToken::kw_option:
5701 case FIRToken::kw_public:
5702 case FIRToken::kw_type: {
5703 auto indent = getIndentation();
5704 if (!indent.has_value())
5705 return emitError(
"'module' must be first token on its line"), failure();
5706 unsigned definitionIndent = *indent;
5708 if (definitionIndent <= circuitIndent)
5709 return emitError(
"module should be indented more"), failure();
5711 if (parseToplevelDefinition(circuit, definitionIndent))
5725 (void)getLexer().translateLocation(info.getFIRLoc());
5731 DenseMap<Attribute, Location> nameToOrigLoc;
5732 for (
auto &op : *circuit.getBodyBlock()) {
5735 op.getAttrOfType<StringAttr>(mlir::SymbolTable::getSymbolAttrName());
5740 auto it = nameToOrigLoc.try_emplace(nameAttr, op.getLoc());
5743 .append(
"redefinition of symbol named '", nameAttr.getValue(),
"'")
5744 .attachNote(it.first->second)
5745 .append(
"see existing symbol definition here");
5751 SymbolTable circuitSymTbl(circuit);
5753 moduleFixups.resize(deferredModules.size());
5758 for (
auto &d : deferredModules)
5759 innerSymbolNamespaces.get(d.moduleOp.getOperation());
5762 auto anyFailed = mlir::failableParallelForEachN(
5763 getContext(), 0, deferredModules.size(), [&](
size_t index) {
5764 if (parseModuleBody(circuitSymTbl, deferredModules[index],
5765 moduleFixups[index]))
5769 if (failed(anyFailed))
5774 for (
auto &fixups : moduleFixups) {
5775 if (failed(fixups.resolve(innerSymbolNamespaces)))
5781 auto parseLayerName = [&](StringRef name) {
5783 auto [head, rest] = name.split(
".");
5784 SmallVector<FlatSymbolRefAttr> nestedRefs;
5785 while (!rest.empty()) {
5787 std::tie(next, rest) = rest.split(
".");
5793 auto parseLayers = [&](
const auto &layers) {
5794 SmallVector<Attribute> layersAttr;
5795 for (
const auto &layer : layers)
5796 layersAttr.push_back(parseLayerName(layer));
5797 if (layersAttr.empty())
5802 if (
auto enableLayers = parseLayers(getConstants().options.enableLayers))
5803 circuit.setEnableLayersAttr(enableLayers);
5804 if (
auto disableLayers = parseLayers(getConstants().options.disableLayers))
5805 circuit.setDisableLayersAttr(disableLayers);
5806 circuit.setDefaultLayerSpecialization(
5807 getConstants().options.defaultLayerSpecialization);
5820 auto sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
5821 SmallVector<const llvm::MemoryBuffer *> annotationsBufs;
5822 unsigned fileID = 1;
5824 annotationsBufs.push_back(
5825 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID() + fileID));
5827 SmallVector<const llvm::MemoryBuffer *> omirBufs;
5828 for (
unsigned e = sourceMgr.getNumBuffers(); fileID < e; ++fileID)
5830 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID() + fileID));
5832 context->loadDialect<CHIRRTLDialect>();
5833 context->loadDialect<FIRRTLDialect, hw::HWDialect>();
5840 SharedParserConstants state(context, options);
5841 FIRLexer lexer(sourceMgr, context);
5843 .parseCircuit(annotationsBufs, omirBufs, ts))
5848 auto circuitVerificationTimer = ts.nest(
"Verify circuit");
5849 if (failed(
verify(*module)))
5856 static mlir::TranslateToMLIRRegistration fromFIR(
5857 "import-firrtl",
"import .fir",
5858 [](llvm::SourceMgr &sourceMgr, MLIRContext *context) {
5859 mlir::TimingScope ts;
assert(baseType &&"element must be base type")
static ParseResult parseParameterList(OpAsmParser &parser, SmallVector< Attribute > ¶meters)
Parse an parameter list if present.
std::vector< UnbundledValueEntry > UnbundledValuesList
SmallVector< std::pair< Attribute, Value > > UnbundledValueEntry
llvm::StringMap< std::pair< SMLoc, SymbolValueEntry >, llvm::BumpPtrAllocator > ModuleSymbolTable
llvm::PointerUnion< Value, UnbundledID > SymbolValueEntry
llvm::DenseMap< std::pair< Value, unsigned >, Value > SubaccessCache
ModuleSymbolTable::MapEntryTy ModuleSymbolTableEntry
llvm::PointerEmbeddedInt< unsigned, 31 > UnbundledID
static ParseResult parseType(Type &result, StringRef name, AsmParser &parser)
Parse a type defined by this dialect.
static std::vector< mlir::Value > toVector(mlir::ValueRange range)
static ParseResult parsePortList(OpAsmParser &p, SmallVectorImpl< module_like_impl::PortParse > &result)
This helper class is used to handle Info records, which specify higher level symbolic source location...
std::optional< Location > infoLoc
This is the location specified by the @ marker if present.
LocWithInfo(SMLoc firLoc, FIRParser *parser)
void setDefaultLoc(Location loc)
If we didn't parse an info locator for the specified value, this sets a default, overriding a fall ba...
SMLoc firLoc
This is the designated location in the .fir file for use when there is no @ info marker.
ParseResult parseOptionalInfo()
Parse an @info marker if present and update our location.
This class represents a reference to a specific field or element of an aggregate value.
FieldRef getSubField(unsigned subFieldID) const
Get a reference to a subfield.
Value getValue() const
Get the Value which created this location.
Location getLoc() const
Get the location associated with the value of this field ref.
This is the state captured for a lexer cursor.
This implements a lexer for .fir files.
std::optional< unsigned > getIndentation(const FIRToken &tok) const
Return the indentation level of the specified token or None if this token is preceded by another toke...
This represents a specific token for .fir files.
StringRef getSpelling() const
std::string getStringValue() const
Given a token containing a string literal, return its value, including removing the quote characters ...
llvm::SMLoc getLoc() const
static IntType get(MLIRContext *context, bool isSigned, int32_t widthOrSentinel=-1, bool isConst=false)
Return an SIntType or UIntType with the specified signedness, width, and constness.
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
mlir::Type innerType(mlir::Type type)
RefType getForceableResultType(bool forceable, Type type)
Return null or forceable reference result type.
Flow swapFlow(Flow flow)
Get a flow's reverse.
void registerFromFIRFileTranslation()
std::pair< bool, std::optional< mlir::LocationAttr > > maybeStringToLocation(llvm::StringRef spelling, bool skipParsing, mlir::StringAttr &locatorFilenameCache, FileLineColLoc &fileLineColLocCache, MLIRContext *context)
Flow foldFlow(Value val, Flow accumulatedFlow=Flow::Source)
Compute the flow for a Value, val, as determined by the FIRRTL specification.
constexpr const char * rawAnnotations
mlir::OwningOpRef< mlir::ModuleOp > importFIRFile(llvm::SourceMgr &sourceMgr, mlir::MLIRContext *context, mlir::TimingScope &ts, FIRParserOptions options={})
bool areTypesRefCastable(Type dstType, Type srcType)
Return true if destination ref type can be cast from source ref type, per FIRRTL spec rules they must...
bool areTypesEquivalent(FIRRTLType destType, FIRRTLType srcType, bool destOuterTypeIsConst=false, bool srcOuterTypeIsConst=false, bool requireSameWidths=false)
Returns whether the two types are equivalent.
hw::InnerRefAttr getInnerRefTo(const hw::InnerSymTarget &target, GetNamespaceCallback getNamespace)
Obtain an inner reference to the target (operation or port), adding an inner symbol as necessary.
bool isRecognizedPrintfEncodedVerif(PrintFOp printOp)
Classifier for legacy verif intent captured in printf + when's.
hw::InnerSymTarget getTargetFor(FieldRef ref)
Return the inner sym target for the specified value and fieldID.
bool fromOMIRJSON(llvm::json::Value &value, SmallVectorImpl< Attribute > &annotations, llvm::json::Path path, MLIRContext *context)
Convert a JSON value containing OMIR JSON (an array of OMNodes), convert this to an OMIRAnnotation,...
constexpr FIRVersion minimumFIRVersion(2, 0, 0)
void emitConnect(OpBuilder &builder, Location loc, Value lhs, Value rhs)
Emit a connect between two values.
bool importAnnotationsFromJSONRaw(llvm::json::Value &value, SmallVectorImpl< Attribute > &annotations, llvm::json::Path path, MLIRContext *context)
Deserialize a JSON value into FIRRTL Annotations.
constexpr FIRVersion nextFIRVersion(3, 3, 0)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
unsigned numAnnotationFiles
The number of annotation files that were specified on the command line.
InfoLocHandling
Specify how @info locators should be handled.
@ IgnoreInfo
If this is set to true, the @info locators are ignored, and the locations are set to the location in ...
The FIRRTL specification version.
This holds the name and type that describes the module's ports.
bool isOutput() const
Return true if this is a simple output-only port.
StringRef getName() const