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, {})),
78 MLIRContext *
const context;
84 llvm::StringMap<FIRRTLType> aliasMap;
87 llvm::DenseMap<StringRef, ClassLike> classMap;
90 const ArrayAttr emptyArrayAttr;
93 const StringAttr loIdentifier, hiIdentifier, amountIdentifier;
96 const hw::InnerRefAttr placeholderInnerRef;
99 SharedParserConstants(
const SharedParserConstants &) =
delete;
100 void operator=(
const SharedParserConstants &) =
delete;
113 FIRParser(SharedParserConstants &constants,
FIRLexer &lexer,
115 : version(version), constants(constants), lexer(lexer),
116 locatorFilenameCache(constants.loIdentifier ) {
120 SharedParserConstants &getConstants()
const {
return constants; }
121 MLIRContext *getContext()
const {
return constants.context; }
123 FIRLexer &getLexer() {
return lexer; }
126 std::optional<unsigned> getIndentation()
const {
131 const FIRToken &getToken()
const {
return lexer.getToken(); }
132 StringRef getTokenSpelling()
const {
return getToken().
getSpelling(); }
139 InFlightDiagnostic emitError(
const Twine &message = {}) {
140 return emitError(getToken().getLoc(), message);
142 InFlightDiagnostic emitError(SMLoc loc,
const Twine &message = {});
145 InFlightDiagnostic emitWarning(
const Twine &message = {}) {
146 return emitWarning(getToken().getLoc(), message);
149 InFlightDiagnostic emitWarning(SMLoc loc,
const Twine &message = {});
159 Location translateLocation(llvm::SMLoc loc) {
160 return lexer.translateLocation(loc);
165 ParseResult parseOptionalInfoLocator(LocationAttr &result);
169 ParseResult parseOptionalName(StringAttr &name);
175 ParseResult requireFeature(
FIRVersion minimum, StringRef feature) {
176 return requireFeature(minimum, feature, getToken().getLoc());
179 ParseResult requireFeature(
FIRVersion minimum, StringRef feature, SMLoc loc) {
180 if (version < minimum)
181 return emitError(loc)
182 << feature <<
" are a FIRRTL " << minimum
183 <<
"+ feature, but the specified FIRRTL version was " << version;
187 ParseResult removedFeature(
FIRVersion removedVersion, StringRef feature) {
188 return removedFeature(removedVersion, feature, getToken().getLoc());
191 ParseResult removedFeature(
FIRVersion removedVersion, StringRef feature,
193 if (version >= removedVersion)
194 return emitError(loc)
195 << feature <<
" were removed in FIRRTL " << removedVersion
196 <<
", but the specified FIRRTL version was " << version;
206 ParseResult parseOptionalAnnotations(SMLoc &loc, StringRef &result);
215 if (getToken().isNot(kind))
225 FIRToken consumedToken = getToken();
226 assert(consumedToken.
isNot(FIRToken::eof, FIRToken::error) &&
227 "shouldn't advance past EOF or errors");
229 return consumedToken;
238 FIRToken consumedToken = getToken();
239 assert(consumedToken.
is(kind) &&
"consumed an unexpected token");
241 return consumedToken;
246 ParseResult parseGetSpelling(StringRef &spelling) {
247 spelling = getTokenSpelling();
253 ParseResult parseToken(
FIRToken::Kind expectedToken,
const Twine &message);
258 const std::function<ParseResult()> &parseElement);
265 ParseResult parseIntLit(APInt &result,
const Twine &message);
266 ParseResult parseIntLit(int64_t &result,
const Twine &message);
267 ParseResult parseIntLit(int32_t &result,
const Twine &message);
270 ParseResult parseVersionLit(
const Twine &message);
273 template <
typename T>
274 ParseResult parseOptionalWidth(T &result);
277 ParseResult parseId(StringRef &result,
const Twine &message);
278 ParseResult parseId(StringAttr &result,
const Twine &message);
279 ParseResult parseFieldId(StringRef &result,
const Twine &message);
280 ParseResult parseFieldIdSeq(SmallVectorImpl<StringRef> &result,
281 const Twine &message);
282 ParseResult parseEnumType(
FIRRTLType &result);
283 ParseResult parseListType(
FIRRTLType &result);
286 ParseResult parsePropertyType(
PropertyType &result,
const Twine &message);
288 ParseResult parseRUW(RUWAttr &result);
289 ParseResult parseOptionalRUW(RUWAttr &result);
291 ParseResult parseParameter(StringAttr &resultName, Attribute &resultValue,
292 SMLoc &resultLoc,
bool allowAggregates =
false);
293 ParseResult parseParameterValue(Attribute &resultValue,
294 bool allowAggregates =
false);
300 FIRParser(
const FIRParser &) =
delete;
301 void operator=(
const FIRParser &) =
delete;
305 SharedParserConstants &constants;
309 StringAttr locatorFilenameCache;
311 FileLineColLoc fileLineColLocCache;
320 InFlightDiagnostic FIRParser::emitError(SMLoc loc,
const Twine &message) {
321 auto diag = mlir::emitError(translateLocation(loc), message);
325 if (getToken().is(FIRToken::error))
330 InFlightDiagnostic FIRParser::emitWarning(SMLoc loc,
const Twine &message) {
331 return mlir::emitWarning(translateLocation(loc), message);
341 const Twine &message) {
342 if (consumeIf(expectedToken))
344 return emitError(message);
351 const std::function<ParseResult()> &parseElement) {
352 if (consumeIf(rightToken))
358 while (consumeIf(FIRToken::comma)) {
363 if (parseToken(rightToken,
"expected ','"))
380 : parser(parser), firLoc(firLoc) {}
387 auto result = parser->translateLocation(firLoc);
395 if (failed(parser->parseOptionalInfoLocator(loc)))
399 switch (parser->constants.options.infoLocatorHandling) {
400 case ILH::IgnoreInfo:
401 assert(0 &&
"Should not return info locations if ignoring");
403 case ILH::PreferInfo:
408 {loc, parser->translateLocation(firLoc)});
435 ParseResult FIRParser::parseOptionalInfoLocator(LocationAttr &result) {
436 if (getToken().isNot(FIRToken::fileinfo))
439 auto loc = getToken().getLoc();
441 auto spelling = getTokenSpelling();
442 consumeToken(FIRToken::fileinfo);
446 constants.options.infoLocatorHandling ==
448 locatorFilenameCache, fileLineColLocCache, getContext());
451 if (!locationPair.first) {
452 mlir::emitWarning(translateLocation(loc),
453 "ignoring unknown @ info record format");
459 if (locationPair.first && constants.options.infoLocatorHandling ==
464 result = *locationPair.second;
472 ParseResult FIRParser::parseOptionalName(StringAttr &name) {
474 if (getToken().isNot(FIRToken::colon)) {
479 consumeToken(FIRToken::colon);
481 if (parseId(nameRef,
"expected result name"))
495 ParseResult FIRParser::parseOptionalAnnotations(SMLoc &loc, StringRef &result) {
497 if (getToken().isNot(FIRToken::inlineannotation))
500 loc = getToken().getLoc();
502 result = getTokenSpelling().drop_front(2).drop_back(1);
503 consumeToken(FIRToken::inlineannotation);
521 ParseResult FIRParser::parseIntLit(APInt &result,
const Twine &message) {
522 auto spelling = getTokenSpelling();
523 bool isNegative =
false;
524 switch (getToken().getKind()) {
525 case FIRToken::signed_integer:
526 isNegative = spelling[0] ==
'-';
527 assert(spelling[0] ==
'+' || spelling[0] ==
'-');
528 spelling = spelling.drop_front();
530 case FIRToken::integer:
531 if (spelling.getAsInteger(10, result))
532 return emitError(message), failure();
536 if (result.isNegative())
537 result = result.zext(result.getBitWidth() + 1);
546 if (result.getBitWidth() > 32 && result.getSignificantBits() <= 32)
547 result = result.trunc(32);
551 case FIRToken::radix_specified_integer: {
552 if (requireFeature({2, 4, 0},
"radix-specified integer literals"))
554 if (spelling[0] ==
'-') {
556 spelling = spelling.drop_front();
558 unsigned base = llvm::StringSwitch<unsigned>(spelling.take_front(2))
563 spelling = spelling.drop_front(2);
564 if (spelling.getAsInteger(base, result))
565 return emitError(
"invalid character in integer literal"), failure();
566 if (result.isNegative())
567 result = result.zext(result.getBitWidth() + 1);
573 case FIRToken::string: {
576 "String-encoded integer literals are unsupported after FIRRTL 3.0.0");
579 assert(spelling.front() ==
'"' && spelling.back() ==
'"');
580 spelling = spelling.drop_back().drop_front();
584 switch (spelling.empty() ?
' ' : spelling.front()) {
595 return emitError(
"expected base specifier (h/o/b) in integer literal"),
598 spelling = spelling.drop_front();
601 bool isNegative =
false;
602 if (!spelling.empty() && spelling.front() ==
'+')
603 spelling = spelling.drop_front();
604 else if (!spelling.empty() && spelling.front() ==
'-') {
606 spelling = spelling.drop_front();
610 if (spelling.empty())
611 return emitError(
"expected digits in integer literal"), failure();
613 if (spelling.getAsInteger(base, result))
614 return emitError(
"invalid character in integer literal"), failure();
619 if (result.isNegative())
620 result = result.zext(result.getBitWidth() + 1);
625 consumeToken(FIRToken::string);
630 return emitError(
"expected integer literal"), failure();
634 ParseResult FIRParser::parseIntLit(int64_t &result,
const Twine &message) {
636 auto loc = getToken().getLoc();
637 if (parseIntLit(value, message))
640 result = (int64_t)value.getLimitedValue(INT64_MAX);
642 return emitError(loc,
"value is too big to handle"), failure();
646 ParseResult FIRParser::parseIntLit(int32_t &result,
const Twine &message) {
648 auto loc = getToken().getLoc();
649 if (parseIntLit(value, message))
652 result = (int32_t)value.getLimitedValue(INT32_MAX);
654 return emitError(loc,
"value is too big to handle"), failure();
660 ParseResult FIRParser::parseVersionLit(
const Twine &message) {
661 auto spelling = getTokenSpelling();
662 if (getToken().getKind() != FIRToken::version)
663 return emitError(message), failure();
665 auto [a, d] = spelling.split(
".");
666 auto [b, c] = d.split(
".");
667 APInt aInt, bInt, cInt;
668 if (a.getAsInteger(10, aInt) || b.getAsInteger(10, bInt) ||
669 c.getAsInteger(10, cInt))
670 return emitError(
"failed to parse version string"), failure();
671 version.major = aInt.getLimitedValue(UINT32_MAX);
672 version.minor = bInt.getLimitedValue(UINT32_MAX);
673 version.patch = cInt.getLimitedValue(UINT32_MAX);
674 if (version.major != aInt || version.minor != bInt || version.patch != cInt)
675 return emitError(
"integers out of range"), failure();
679 consumeToken(FIRToken::version);
686 template <
typename T>
687 ParseResult FIRParser::parseOptionalWidth(T &result) {
688 if (!consumeIf(FIRToken::less))
689 return result = -1, success();
692 auto widthLoc = getToken().getLoc();
693 if (parseIntLit(result,
"expected width") ||
694 parseToken(FIRToken::greater,
"expected >"))
698 return emitError(widthLoc,
"invalid width specifier"), failure();
707 ParseResult FIRParser::parseId(StringRef &result,
const Twine &message) {
708 switch (getToken().getKind()) {
710 case FIRToken::identifier:
711 case FIRToken::literal_identifier:
713 #define TOK_KEYWORD(spelling) case FIRToken::kw_##spelling:
714 #include "FIRTokenKinds.def"
719 if (getToken().getKind() == FIRToken::literal_identifier)
720 result = getTokenSpelling().drop_front().drop_back();
722 result = getTokenSpelling();
732 ParseResult FIRParser::parseId(StringAttr &result,
const Twine &message) {
734 if (parseId(name, message))
746 ParseResult FIRParser::parseFieldId(StringRef &result,
const Twine &message) {
748 result = getTokenSpelling();
749 if (consumeIf(FIRToken::integer))
755 if (parseId(result, message))
767 ParseResult FIRParser::parseFieldIdSeq(SmallVectorImpl<StringRef> &result,
768 const Twine &message) {
770 StringRef tmp = getTokenSpelling();
772 if (consumeIf(FIRToken::integer)) {
773 result.push_back(tmp);
777 if (consumeIf(FIRToken::floatingpoint)) {
781 auto [a, b] = tmp.split(
".");
787 if (consumeIf(FIRToken::version)) {
789 auto [a, d] = tmp.split(
".");
790 auto [b, c] = d.split(
".");
798 if (parseId(tmp, message))
800 result.push_back(tmp);
806 ParseResult FIRParser::parseEnumType(
FIRRTLType &result) {
807 if (parseToken(FIRToken::l_brace_bar,
808 "expected leading '{|' in enumeration type"))
810 SmallVector<FEnumType::EnumElement> elements;
811 if (parseListUntil(FIRToken::r_brace_bar, [&]() -> ParseResult {
812 auto fieldLoc = getToken().getLoc();
816 if (parseId(name,
"expected valid identifier for enumeration tag"))
821 if (consumeIf(FIRToken::colon)) {
823 if (
parseType(parsedType,
"expected enumeration type"))
825 type = type_dyn_cast<FIRRTLBaseType>(parsedType);
827 return emitError(fieldLoc,
"field must be a base type");
840 ParseResult FIRParser::parsePropertyType(
PropertyType &result,
841 const Twine &message) {
845 auto prop = type_dyn_cast<PropertyType>(type);
847 return emitError(
"expected property type");
853 ParseResult FIRParser::parseListType(
FIRRTLType &result) {
854 consumeToken(FIRToken::kw_List);
857 if (parseToken(FIRToken::less,
"expected '<' in List type") ||
858 parsePropertyType(
elementType,
"expected List element type") ||
859 parseToken(FIRToken::greater,
"expected '>' in List type"))
885 switch (getToken().getKind()) {
887 return emitError(message), failure();
889 case FIRToken::kw_Clock:
890 consumeToken(FIRToken::kw_Clock);
894 case FIRToken::kw_Inst: {
898 consumeToken(FIRToken::kw_Inst);
899 if (parseToken(FIRToken::less,
"expected < in Inst type"))
902 auto loc = getToken().getLoc();
904 if (parseId(
id,
"expected class name in Inst type"))
908 const auto &classMap = getConstants().classMap;
909 auto lookup = classMap.find(
id);
910 if (lookup == classMap.end())
911 return emitError(loc) <<
"unknown class '" <<
id <<
"'";
913 auto classOp = lookup->second;
915 if (parseToken(FIRToken::greater,
"expected > in Inst type"))
918 result = classOp.getInstanceType();
922 case FIRToken::kw_AnyRef: {
926 consumeToken(FIRToken::kw_AnyRef);
931 case FIRToken::kw_Reset:
932 consumeToken(FIRToken::kw_Reset);
936 case FIRToken::kw_AsyncReset:
937 consumeToken(FIRToken::kw_AsyncReset);
941 case FIRToken::kw_UInt:
942 case FIRToken::kw_SInt:
943 case FIRToken::kw_Analog: {
944 auto kind = getToken().getKind();
949 if (parseOptionalWidth(width))
952 if (kind == FIRToken::kw_SInt)
954 else if (kind == FIRToken::kw_UInt)
957 assert(kind == FIRToken::kw_Analog);
963 case FIRToken::kw_Probe:
964 case FIRToken::kw_RWProbe: {
965 auto kind = getToken().getKind();
966 auto loc = getToken().getLoc();
971 if (parseToken(FIRToken::less,
"expected '<' in reference type") ||
972 parseType(type,
"expected probe data type"))
975 SmallVector<StringRef> layers;
976 if (consumeIf(FIRToken::comma)) {
977 if (requireFeature({4, 0, 0},
"colored probes"))
982 loc = getToken().getLoc();
983 if (parseId(layer,
"expected layer name"))
985 layers.push_back(layer);
986 }
while (consumeIf(FIRToken::period));
989 if (!consumeIf(FIRToken::greater))
990 return emitError(loc,
"expected '>' to end reference type");
992 bool forceable = kind == FIRToken::kw_RWProbe;
994 auto innerType = type_dyn_cast<FIRRTLBaseType>(type);
996 return emitError(loc,
"invalid probe inner type, must be base-type");
999 return emitError(loc,
"probe inner type must be passive");
1001 if (forceable &&
innerType.containsConst())
1002 return emitError(loc,
"rwprobe cannot contain const");
1004 SymbolRefAttr layer;
1005 if (!layers.empty()) {
1007 llvm::map_range(ArrayRef(layers).drop_front(), [&](StringRef a) {
1011 llvm::to_vector(nestedLayers));
1018 case FIRToken::l_brace: {
1019 consumeToken(FIRToken::l_brace);
1021 SmallVector<OpenBundleType::BundleElement, 4> elements;
1022 bool bundleCompatible =
true;
1023 if (parseListUntil(FIRToken::r_brace, [&]() -> ParseResult {
1024 bool isFlipped = consumeIf(FIRToken::kw_flip);
1026 StringRef fieldName;
1028 if (parseFieldId(fieldName,
"expected bundle field name") ||
1029 parseToken(FIRToken::colon,
"expected ':' in bundle"))
1031 if (
parseType(type,
"expected bundle field type"))
1036 bundleCompatible &= isa<BundleType::ElementType>(type);
1043 if (bundleCompatible) {
1044 auto bundleElements = llvm::map_range(elements, [](
auto element) {
1045 return BundleType::BundleElement{
1046 element.name, element.isFlip,
1047 cast<BundleType::ElementType>(element.type)};
1049 result =
BundleType::get(getContext(), llvm::to_vector(bundleElements));
1055 case FIRToken::l_brace_bar: {
1056 if (parseEnumType(result))
1061 case FIRToken::identifier: {
1063 auto loc = getToken().getLoc();
1064 if (parseId(
id,
"expected a type alias name"))
1066 auto it = constants.aliasMap.find(
id);
1067 if (it == constants.aliasMap.end()) {
1068 emitError(loc) <<
"type identifier `" <<
id <<
"` is not declared";
1071 result = it->second;
1075 case FIRToken::kw_const: {
1076 consumeToken(FIRToken::kw_const);
1077 auto nextToken = getToken();
1078 auto loc = nextToken.getLoc();
1081 if (nextToken.is(FIRToken::kw_const))
1082 return emitError(loc,
"'const' can only be specified once on a type");
1087 auto baseType = type_dyn_cast<FIRRTLBaseType>(result);
1089 return emitError(loc,
"only hardware types can be 'const'");
1091 result = baseType.getConstType(
true);
1095 case FIRToken::kw_String:
1096 if (requireFeature({3, 1, 0},
"Strings"))
1098 consumeToken(FIRToken::kw_String);
1101 case FIRToken::kw_Integer:
1102 if (requireFeature({3, 1, 0},
"Integers"))
1104 consumeToken(FIRToken::kw_Integer);
1107 case FIRToken::kw_Bool:
1110 consumeToken(FIRToken::kw_Bool);
1113 case FIRToken::kw_Double:
1116 consumeToken(FIRToken::kw_Double);
1119 case FIRToken::kw_Path:
1122 consumeToken(FIRToken::kw_Path);
1125 case FIRToken::kw_List:
1126 if (requireFeature({4, 0, 0},
"Lists") || parseListType(result))
1132 while (consumeIf(FIRToken::l_square)) {
1133 auto sizeLoc = getToken().getLoc();
1135 if (parseIntLit(size,
"expected width") ||
1136 parseToken(FIRToken::r_square,
"expected ]"))
1140 return emitError(sizeLoc,
"invalid size specifier"), failure();
1142 auto baseType = type_dyn_cast<FIRRTLBaseType>(result);
1153 ParseResult FIRParser::parseRUW(RUWAttr &result) {
1154 switch (getToken().getKind()) {
1156 case FIRToken::kw_old:
1157 result = RUWAttr::Old;
1158 consumeToken(FIRToken::kw_old);
1160 case FIRToken::kw_new:
1161 result = RUWAttr::New;
1162 consumeToken(FIRToken::kw_new);
1164 case FIRToken::kw_undefined:
1165 result = RUWAttr::Undefined;
1166 consumeToken(FIRToken::kw_undefined);
1176 ParseResult FIRParser::parseOptionalRUW(RUWAttr &result) {
1177 switch (getToken().getKind()) {
1181 case FIRToken::kw_old:
1182 result = RUWAttr::Old;
1183 consumeToken(FIRToken::kw_old);
1185 case FIRToken::kw_new:
1186 result = RUWAttr::New;
1187 consumeToken(FIRToken::kw_new);
1189 case FIRToken::kw_undefined:
1190 result = RUWAttr::Undefined;
1191 consumeToken(FIRToken::kw_undefined);
1199 ParseResult FIRParser::parseParameter(StringAttr &resultName,
1200 Attribute &resultValue, SMLoc &resultLoc,
1201 bool allowAggregates) {
1202 auto loc = getToken().getLoc();
1206 if (parseId(name,
"expected parameter name") ||
1207 parseToken(FIRToken::equal,
"expected '=' in parameter"))
1212 if (parseParameterValue(value, allowAggregates))
1216 resultValue = value;
1227 ParseResult FIRParser::parseParameterValue(Attribute &value,
1228 bool allowAggregates) {
1229 mlir::Builder builder(getContext());
1230 switch (getToken().getKind()) {
1233 case FIRToken::integer:
1234 case FIRToken::signed_integer: {
1236 if (parseIntLit(result,
"invalid integer parameter"))
1242 if (result.getBitWidth() < 32)
1243 result = result.sext(32);
1245 value = builder.getIntegerAttr(
1246 builder.getIntegerType(result.getBitWidth(), result.isSignBitSet()),
1252 case FIRToken::string: {
1254 value = builder.getStringAttr(getToken().getStringValue());
1255 consumeToken(FIRToken::string);
1260 case FIRToken::verbatim_string: {
1262 auto text = builder.getStringAttr(getToken().getVerbatimStringValue());
1264 consumeToken(FIRToken::verbatim_string);
1269 case FIRToken::floatingpoint: {
1271 if (!llvm::to_float(getTokenSpelling(), v))
1272 return emitError(
"invalid float parameter syntax"), failure();
1274 value = builder.getF64FloatAttr(v);
1275 consumeToken(FIRToken::floatingpoint);
1280 case FIRToken::l_square: {
1281 if (!allowAggregates)
1282 return emitError(
"expected non-aggregate parameter value");
1285 SmallVector<Attribute> elements;
1286 auto parseElement = [&] {
1287 return parseParameterValue(elements.emplace_back(),
1290 if (parseListUntil(FIRToken::r_square, parseElement))
1293 value = builder.getArrayAttr(elements);
1298 case FIRToken::l_brace: {
1299 if (!allowAggregates)
1300 return emitError(
"expected non-aggregate parameter value");
1303 NamedAttrList fields;
1304 auto parseField = [&]() -> ParseResult {
1305 StringAttr fieldName;
1306 Attribute fieldValue;
1308 if (parseParameter(fieldName, fieldValue, fieldLoc,
1311 if (fields.set(fieldName, fieldValue))
1312 return emitError(fieldLoc)
1313 <<
"redefinition of parameter '" << fieldName.getValue() <<
"'";
1316 if (parseListUntil(FIRToken::r_brace, parseField))
1319 value = fields.getDictionary(getContext());
1324 return emitError(
"expected parameter value");
1339 llvm::StringMap<std::pair<SMLoc, SymbolValueEntry>, llvm::BumpPtrAllocator>;
1347 struct UnbundledValueRestorer {
1349 size_t startingSize;
1351 startingSize = list.size();
1353 ~UnbundledValueRestorer() { list.resize(startingSize); }
1362 struct FIRModuleContext :
public FIRParser {
1363 explicit FIRModuleContext(SharedParserConstants &constants,
FIRLexer &lexer,
1365 : FIRParser(constants, lexer, version) {}
1371 llvm::DenseMap<std::pair<Attribute, Type>, Value> constantCache;
1374 template <
typename OpTy = ConstantOp,
typename... Args>
1375 Value getCachedConstant(ImplicitLocOpBuilder &builder, Attribute attr,
1376 Type type, Args &&...args) {
1377 auto &result = constantCache[{attr, type}];
1383 OpBuilder::InsertPoint savedIP;
1385 auto *parentOp = builder.getInsertionBlock()->getParentOp();
1386 if (!isa<FModuleLike>(parentOp)) {
1387 savedIP = builder.saveInsertionPoint();
1388 while (!isa<FModuleLike>(parentOp)) {
1389 builder.setInsertionPoint(parentOp);
1390 parentOp = builder.getInsertionBlock()->getParentOp();
1394 result = builder.create<OpTy>(type, std::forward<Args>(args)...);
1396 if (savedIP.isSet())
1397 builder.setInsertionPoint(savedIP.getBlock(), savedIP.getPoint());
1408 Value &getCachedSubaccess(Value value,
unsigned index) {
1409 auto &result = subaccessCache[{value, index}];
1412 auto it = scopeMap.find(value.getParentBlock());
1413 if (it != scopeMap.end())
1414 it->second->scopedSubaccesses.push_back({result, index});
1424 ParseResult addSymbolEntry(StringRef name,
SymbolValueEntry entry, SMLoc loc,
1425 bool insertNameIntoGlobalScope =
false);
1426 ParseResult addSymbolEntry(StringRef name, Value value, SMLoc loc,
1427 bool insertNameIntoGlobalScope =
false) {
1429 insertNameIntoGlobalScope);
1434 SMLoc loc,
bool fatal =
true);
1439 StringRef field, SMLoc loc);
1447 assert(index < unbundledValues.size());
1448 return unbundledValues[index];
1458 struct ContextScope {
1459 friend struct FIRModuleContext;
1460 ContextScope(FIRModuleContext &moduleContext, Block *block)
1461 : moduleContext(moduleContext), block(block),
1462 previousScope(moduleContext.currentScope) {
1463 moduleContext.currentScope =
this;
1464 moduleContext.scopeMap[block] =
this;
1469 for (
auto *entryPtr : scopedDecls)
1470 entryPtr->second.first = SMLoc();
1473 for (
auto subaccess : scopedSubaccesses)
1474 moduleContext.subaccessCache.erase(subaccess);
1476 moduleContext.scopeMap.erase(block);
1478 moduleContext.currentScope = previousScope;
1482 void operator=(
const ContextScope &) =
delete;
1483 ContextScope(
const ContextScope &) =
delete;
1485 FIRModuleContext &moduleContext;
1487 ContextScope *previousScope;
1488 std::vector<ModuleSymbolTableEntry *> scopedDecls;
1489 std::vector<std::pair<Value, unsigned>> scopedSubaccesses;
1503 DenseMap<Block *, ContextScope *> scopeMap;
1508 ContextScope *currentScope =
nullptr;
1519 ParseResult FIRModuleContext::addSymbolEntry(StringRef name,
1521 bool insertNameIntoGlobalScope) {
1526 if (entryIt->second.first.isValid()) {
1527 emitError(loc,
"redefinition of name '" + name +
"'")
1528 .attachNote(translateLocation(entryIt->second.first))
1529 <<
"previous definition here";
1535 entryIt->second = {loc, entry};
1536 if (currentScope && !insertNameIntoGlobalScope)
1537 currentScope->scopedDecls.push_back(&*entryIt);
1545 StringRef name, SMLoc loc) {
1546 auto &entry = symbolTable[name];
1547 if (!entry.first.isValid())
1548 return emitError(loc,
"use of unknown declaration '" + name +
"'");
1549 result = entry.second;
1550 assert(result &&
"name in symbol table without definition");
1554 ParseResult FIRModuleContext::resolveSymbolEntry(Value &result,
1556 SMLoc loc,
bool fatal) {
1557 if (!entry.is<Value>()) {
1559 emitError(loc,
"bundle value should only be used from subfield");
1562 result = entry.get<Value>();
1566 ParseResult FIRModuleContext::resolveSymbolEntry(Value &result,
1568 StringRef fieldName,
1571 emitError(loc,
"value should not be used from subfield");
1577 unsigned unbundledId = entry.get<
UnbundledID>() - 1;
1578 assert(unbundledId < unbundledValues.size());
1580 for (
auto elt : ubEntry) {
1581 if (elt.first == fieldAttr) {
1582 result = elt.second;
1587 emitError(loc,
"use of invalid field name '")
1588 << fieldName <<
"' on bundle value";
1614 struct LazyLocationListener :
public OpBuilder::Listener {
1615 LazyLocationListener(OpBuilder &builder) : builder(builder) {
1616 assert(builder.getListener() ==
nullptr);
1617 builder.setListener(
this);
1620 ~LazyLocationListener() {
1621 assert(subOps.empty() &&
"didn't process parsed operations");
1622 assert(builder.getListener() ==
this);
1623 builder.setListener(
nullptr);
1626 void startStatement() {
1627 assert(!isActive &&
"Already processing a statement");
1633 void endStatement(FIRParser &parser) {
1634 assert(isActive &&
"Not parsing a statement");
1638 for (
auto opAndSMLoc : subOps) {
1642 switch (parser.getConstants().options.infoLocatorHandling) {
1643 case ILH::IgnoreInfo:
1645 opAndSMLoc.first->setLoc(parser.translateLocation(opAndSMLoc.second));
1647 case ILH::PreferInfo:
1648 opAndSMLoc.first->setLoc(infoLoc);
1650 case ILH::FusedInfo:
1652 infoLoc.getContext(),
1653 {infoLoc, parser.translateLocation(opAndSMLoc.second)}));
1660 for (
auto opAndSMLoc : subOps)
1661 opAndSMLoc.first->setLoc(parser.translateLocation(opAndSMLoc.second));
1666 infoLoc = LocationAttr();
1667 currentSMLoc = SMLoc();
1672 void setLoc(SMLoc loc) { currentSMLoc = loc; }
1675 void setInfoLoc(LocationAttr loc) {
1676 assert(!infoLoc &&
"Info location multiply specified");
1682 void notifyOperationInserted(Operation *op,
1683 mlir::IRRewriter::InsertPoint)
override {
1684 assert(currentSMLoc != SMLoc() &&
"No .fir file location specified");
1685 assert(isActive &&
"Not parsing a statement");
1686 subOps.push_back({op, currentSMLoc});
1691 bool isActive =
false;
1699 LocationAttr infoLoc;
1706 SmallVector<std::pair<Operation *, SMLoc>, 8> subOps;
1708 void operator=(
const LazyLocationListener &) =
delete;
1709 LazyLocationListener(
const LazyLocationListener &) =
delete;
1717 struct InnerSymFixups {
1719 void add(hw::InnerRefUserOpInterface user, hw::InnerSymTarget target) {
1720 fixups.push_back({user, target});
1725 LogicalResult resolve(hw::InnerSymbolNamespaceCollection &isnc);
1729 hw::InnerRefUserOpInterface innerRefUser;
1730 hw::InnerSymTarget target;
1732 SmallVector<Fixup, 0> fixups;
1737 InnerSymFixups::resolve(hw::InnerSymbolNamespaceCollection &isnc) {
1738 for (
auto &f : fixups) {
1740 f.target, [&isnc](FModuleLike module) -> hw::InnerSymbolNamespace & {
1741 return isnc.get(module);
1743 assert(ref &&
"unable to resolve inner symbol target");
1747 TypeSwitch<Operation *, LogicalResult>(f.innerRefUser.getOperation())
1748 .Case<RWProbeOp>([ref](RWProbeOp op) {
1749 op.setTargetAttr(ref);
1752 .Default([](
auto *op) {
1753 return op->emitError(
"unknown inner-ref user requiring fixup");
1764 struct FIRStmtParser :
public FIRParser {
1765 explicit FIRStmtParser(Block &blockToInsertInto,
1766 FIRModuleContext &moduleContext,
1767 InnerSymFixups &innerSymFixups,
1768 const SymbolTable &circuitSymTbl,
FIRVersion version,
1769 SymbolRefAttr layerSym = {})
1770 : FIRParser(moduleContext.getConstants(), moduleContext.getLexer(),
1773 locationProcessor(this->builder), moduleContext(moduleContext),
1774 innerSymFixups(innerSymFixups), layerSym(layerSym),
1775 circuitSymTbl(circuitSymTbl) {
1776 builder.setInsertionPointToEnd(&blockToInsertInto);
1779 ParseResult parseSimpleStmt(
unsigned stmtIndent);
1780 ParseResult parseSimpleStmtBlock(
unsigned indent);
1783 ParseResult parseSimpleStmtImpl(
unsigned stmtIndent);
1786 void emitInvalidate(Value val,
Flow flow);
1792 void emitInvalidate(Value val) { emitInvalidate(val,
foldFlow(val)); }
1795 ParseResult parseOptionalInfo() {
1797 if (failed(parseOptionalInfoLocator(loc)))
1799 locationProcessor.setInfoLoc(loc);
1804 ParseResult parseExpImpl(Value &result,
const Twine &message,
1805 bool isLeadingStmt);
1806 ParseResult parseExp(Value &result,
const Twine &message) {
1807 return parseExpImpl(result, message,
false);
1809 ParseResult parseExpLeadingStmt(Value &result,
const Twine &message) {
1810 return parseExpImpl(result, message,
true);
1812 ParseResult parseEnumExp(Value &result);
1813 ParseResult parsePathExp(Value &result);
1814 ParseResult parseRefExp(Value &result,
const Twine &message);
1815 ParseResult parseStaticRefExp(Value &result,
const Twine &message);
1816 ParseResult parseRWProbeStaticRefExp(
FieldRef &refResult, Type &type,
1817 const Twine &message);
1820 ParseResult parseIntrinsic(Value &result,
bool isStatement);
1821 ParseResult parseIntrinsicStmt() {
1823 return parseIntrinsic(unused,
true);
1825 ParseResult parseIntrinsicExp(Value &result) {
1826 return parseIntrinsic(result,
false);
1828 ParseResult parseOptionalParams(ArrayAttr &resultParameters);
1830 template <
typename subop>
1831 FailureOr<Value> emitCachedSubAccess(Value base,
unsigned indexNo, SMLoc loc);
1832 ParseResult parseOptionalExpPostscript(Value &result,
1833 bool allowDynamic =
true);
1834 ParseResult parsePostFixFieldId(Value &result);
1835 ParseResult parsePostFixIntSubscript(Value &result);
1836 ParseResult parsePostFixDynamicSubscript(Value &result);
1837 ParseResult parseIntegerLiteralExp(Value &result);
1838 ParseResult parseListExp(Value &result);
1839 ParseResult parseListConcatExp(Value &result);
1841 template <
typename T,
size_t M,
size_t N,
size_t... Ms,
size_t... Ns>
1842 ParseResult parsePrim(std::index_sequence<Ms...>, std::index_sequence<Ns...>,
1844 auto loc = getToken().getLoc();
1845 locationProcessor.setLoc(loc);
1848 auto vals = std::array<Value, M>();
1849 auto ints = std::array<int64_t, N>();
1853 for (
size_t i = 0; i < M; ++i) {
1855 if (parseToken(FIRToken::comma,
"expected ','"))
1857 if (parseExp(vals[i],
"expected expression in primitive operand"))
1863 for (
size_t i = 0; i < N; ++i) {
1865 if (parseToken(FIRToken::comma,
"expected ','"))
1867 if (parseIntLit(ints[i],
"expected integer in primitive operand"))
1872 if (parseToken(FIRToken::r_paren,
"expected ')'"))
1876 auto type = T::inferReturnType(cast<FIRRTLType>(vals[Ms].getType())...,
1880 T::inferReturnType(cast<FIRRTLType>(vals[Ms].getType())..., ints[Ns]...,
1881 translateLocation(loc));
1886 auto op = builder.create<T>(type, vals[Ms]..., ints[Ns]...);
1887 result = op.getResult();
1891 template <
typename T,
unsigned M,
unsigned N>
1892 ParseResult parsePrimExp(Value &result) {
1893 auto ms = std::make_index_sequence<M>();
1894 auto ns = std::make_index_sequence<N>();
1895 return parsePrim<T, M, N>(ms, ns, result);
1898 std::optional<ParseResult> parseExpWithLeadingKeyword(
FIRToken keyword);
1901 ParseResult parseSubBlock(Block &blockToInsertInto,
unsigned indent,
1902 SymbolRefAttr layerSym);
1903 ParseResult parseAttach();
1904 ParseResult parseMemPort(MemDirAttr direction);
1905 ParseResult parsePrintf();
1906 ParseResult parseSkip();
1907 ParseResult parseStop();
1908 ParseResult parseAssert();
1909 ParseResult parseAssume();
1910 ParseResult parseCover();
1911 ParseResult parseWhen(
unsigned whenIndent);
1912 ParseResult parseMatch(
unsigned matchIndent);
1913 ParseResult parseRefDefine();
1914 ParseResult parseRefForce();
1915 ParseResult parseRefForceInitial();
1916 ParseResult parseRefRelease();
1917 ParseResult parseRefReleaseInitial();
1918 ParseResult parseRefRead(Value &result);
1919 ParseResult parseProbe(Value &result);
1920 ParseResult parsePropAssign();
1921 ParseResult parseRWProbe(Value &result);
1922 ParseResult parseLeadingExpStmt(Value lhs);
1923 ParseResult parseConnect();
1924 ParseResult parseInvalidate();
1925 ParseResult parseLayerBlockOrGroup(
unsigned indent);
1928 ParseResult parseInstance();
1929 ParseResult parseInstanceChoice();
1930 ParseResult parseObject();
1931 ParseResult parseCombMem();
1932 ParseResult parseSeqMem();
1933 ParseResult parseMem(
unsigned memIndent);
1934 ParseResult parseNode();
1935 ParseResult parseWire();
1936 ParseResult parseRegister(
unsigned regIndent);
1937 ParseResult parseRegisterWithReset();
1940 FModuleLike getReferencedModule(SMLoc loc, StringRef moduleName);
1943 ImplicitLocOpBuilder builder;
1944 LazyLocationListener locationProcessor;
1947 FIRModuleContext &moduleContext;
1950 InnerSymFixups &innerSymFixups;
1954 SymbolRefAttr layerSym;
1956 const SymbolTable &circuitSymTbl;
1963 void FIRStmtParser::emitInvalidate(Value val,
Flow flow) {
1964 auto tpe = type_dyn_cast<FIRRTLBaseType>(val.getType());
1971 auto props = tpe.getRecursiveTypeProperties();
1972 if (props.isPassive && !props.containsAnalog) {
1975 emitConnect(builder, val, builder.create<InvalidValueOp>(tpe));
1986 TypeSwitch<FIRRTLType>(tpe)
1987 .Case<BundleType>([&](
auto tpe) {
1988 for (
size_t i = 0, e = tpe.getNumElements(); i < e; ++i) {
1989 auto &subfield = moduleContext.getCachedSubaccess(val, i);
1991 OpBuilder::InsertionGuard guard(builder);
1992 builder.setInsertionPointAfterValue(val);
1993 subfield = builder.create<SubfieldOp>(val, i);
1995 emitInvalidate(subfield,
1996 tpe.getElement(i).isFlip ?
swapFlow(flow) : flow);
1999 .Case<FVectorType>([&](
auto tpe) {
2000 auto tpex = tpe.getElementType();
2001 for (
size_t i = 0, e = tpe.getNumElements(); i != e; ++i) {
2002 auto &subindex = moduleContext.getCachedSubaccess(val, i);
2004 OpBuilder::InsertionGuard guard(builder);
2005 builder.setInsertionPointAfterValue(val);
2006 subindex = builder.create<SubindexOp>(tpex, val, i);
2008 emitInvalidate(subindex, flow);
2036 ParseResult FIRStmtParser::parseExpImpl(Value &result,
const Twine &message,
2037 bool isLeadingStmt) {
2038 auto token = getToken();
2039 auto kind = token.getKind();
2041 case FIRToken::lp_integer_add:
2042 case FIRToken::lp_integer_mul:
2043 case FIRToken::lp_integer_shr:
2044 case FIRToken::lp_integer_shl:
2045 if (requireFeature({4, 0, 0},
"Integer arithmetic expressions"))
2054 #define TOK_LPKEYWORD_PRIM(SPELLING, CLASS, NUMOPERANDS, NUMATTRIBUTES) \
2055 case FIRToken::lp_##SPELLING: \
2056 if (parsePrimExp<CLASS, NUMOPERANDS, NUMATTRIBUTES>(result)) \
2059 #include "FIRTokenKinds.def"
2061 case FIRToken::l_brace_bar:
2063 return emitError(
"unexpected enumeration as start of statement");
2064 if (parseEnumExp(result))
2067 case FIRToken::lp_read:
2069 return emitError(
"unexpected read() as start of statement");
2070 if (parseRefRead(result))
2073 case FIRToken::lp_probe:
2075 return emitError(
"unexpected probe() as start of statement");
2076 if (parseProbe(result))
2079 case FIRToken::lp_rwprobe:
2081 return emitError(
"unexpected rwprobe() as start of statement");
2082 if (parseRWProbe(result))
2086 case FIRToken::kw_UInt:
2087 case FIRToken::kw_SInt:
2088 if (parseIntegerLiteralExp(result))
2091 case FIRToken::kw_String: {
2092 if (requireFeature({3, 1, 0},
"Strings"))
2094 locationProcessor.setLoc(getToken().getLoc());
2095 consumeToken(FIRToken::kw_String);
2097 if (parseToken(FIRToken::l_paren,
"expected '(' in String expression") ||
2098 parseGetSpelling(spelling) ||
2099 parseToken(FIRToken::string,
2100 "expected string literal in String expression") ||
2101 parseToken(FIRToken::r_paren,
"expected ')' in String expression"))
2104 result = moduleContext.getCachedConstant<StringConstantOp>(
2105 builder, attr, builder.getType<StringType>(), attr);
2108 case FIRToken::kw_Integer: {
2109 if (requireFeature({3, 1, 0},
"Integers"))
2111 locationProcessor.setLoc(getToken().getLoc());
2112 consumeToken(FIRToken::kw_Integer);
2114 if (parseToken(FIRToken::l_paren,
"expected '(' in Integer expression") ||
2115 parseIntLit(value,
"expected integer literal in Integer expression") ||
2116 parseToken(FIRToken::r_paren,
"expected ')' in Integer expression"))
2118 APSInt apint(value,
false);
2119 result = moduleContext.getCachedConstant<FIntegerConstantOp>(
2121 builder.getType<FIntegerType>(), apint);
2124 case FIRToken::kw_Bool: {
2127 locationProcessor.setLoc(getToken().getLoc());
2128 consumeToken(FIRToken::kw_Bool);
2129 if (parseToken(FIRToken::l_paren,
"expected '(' in Bool expression"))
2132 if (consumeIf(FIRToken::kw_true))
2134 else if (consumeIf(FIRToken::kw_false))
2137 return emitError(
"expected true or false in Bool expression");
2138 if (parseToken(FIRToken::r_paren,
"expected ')' in Bool expression"))
2140 auto attr = builder.getBoolAttr(value);
2141 result = moduleContext.getCachedConstant<BoolConstantOp>(
2142 builder, attr, builder.getType<BoolType>(), value);
2145 case FIRToken::kw_Double: {
2148 locationProcessor.setLoc(getToken().getLoc());
2149 consumeToken(FIRToken::kw_Double);
2150 if (parseToken(FIRToken::l_paren,
"expected '(' in Double expression"))
2152 auto spelling = getTokenSpelling();
2153 if (parseToken(FIRToken::floatingpoint,
2154 "expected floating point in Double expression") ||
2155 parseToken(FIRToken::r_paren,
"expected ')' in Double expression"))
2160 if (!llvm::to_float(spelling, d))
2161 return emitError(
"invalid double");
2162 auto attr = builder.getF64FloatAttr(d);
2163 result = moduleContext.getCachedConstant<DoubleConstantOp>(
2164 builder, attr, builder.getType<DoubleType>(), attr);
2167 case FIRToken::kw_List: {
2168 if (requireFeature({4, 0, 0},
"Lists"))
2171 return emitError(
"unexpected List<>() as start of statement");
2172 if (parseListExp(result))
2177 case FIRToken::lp_list_concat: {
2179 return emitError(
"unexpected list_create() as start of statement");
2180 if (requireFeature({4, 0, 0},
"List concat") || parseListConcatExp(result))
2185 case FIRToken::lp_path:
2187 return emitError(
"unexpected path() as start of statement");
2192 case FIRToken::lp_intrinsic:
2193 if (requireFeature({4, 0, 0},
"generic intrinsics") ||
2194 parseIntrinsicExp(result))
2200 case FIRToken::identifier:
2201 case FIRToken::literal_identifier:
2204 auto loc = getToken().getLoc();
2206 if (parseId(name, message) ||
2207 moduleContext.lookupSymbolEntry(symtabEntry, name, loc))
2211 if (!moduleContext.resolveSymbolEntry(result, symtabEntry, loc,
false))
2219 if (isLeadingStmt && consumeIf(FIRToken::kw_is)) {
2220 if (parseToken(FIRToken::kw_invalid,
"expected 'invalid'") ||
2221 parseOptionalInfo())
2224 locationProcessor.setLoc(loc);
2226 unsigned unbundledId = symtabEntry.get<
UnbundledID>() - 1;
2228 moduleContext.getUnbundledEntry(unbundledId);
2229 for (
auto elt : ubEntry)
2230 emitInvalidate(elt.second);
2238 StringRef fieldName;
2239 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
2240 parseFieldId(fieldName,
"expected field name") ||
2241 moduleContext.resolveSymbolEntry(result, symtabEntry, fieldName, loc))
2249 case FIRToken::lp_shr:
2252 if (version <
FIRVersion(4, 0, 0) && type_isa<UIntType>(result.getType()))
2253 result = builder.create<PadPrimOp>(result, 1);
2259 return parseOptionalExpPostscript(result);
2269 ParseResult FIRStmtParser::parseOptionalExpPostscript(Value &result,
2270 bool allowDynamic) {
2275 if (consumeIf(FIRToken::period)) {
2276 if (parsePostFixFieldId(result))
2283 if (consumeIf(FIRToken::l_square)) {
2284 if (getToken().isAny(FIRToken::integer, FIRToken::string)) {
2285 if (parsePostFixIntSubscript(result))
2290 return emitError(
"subaccess not allowed here");
2291 if (parsePostFixDynamicSubscript(result))
2301 template <
typename subop>
2303 FIRStmtParser::emitCachedSubAccess(Value base,
unsigned indexNo, SMLoc loc) {
2305 auto &value = moduleContext.getCachedSubaccess(base, indexNo);
2311 auto baseType = cast<FIRRTLType>(base.getType());
2312 auto resultType = subop::inferReturnType(baseType, indexNo, {});
2315 (void)subop::inferReturnType(baseType, indexNo, translateLocation(loc));
2321 locationProcessor.setLoc(loc);
2322 OpBuilder::InsertionGuard guard(builder);
2323 builder.setInsertionPointAfterValue(base);
2324 auto op = builder.create<subop>(resultType, base, indexNo);
2327 return value = op.getResult();
2334 ParseResult FIRStmtParser::parsePostFixFieldId(Value &result) {
2335 auto loc = getToken().getLoc();
2336 SmallVector<StringRef, 3> fields;
2337 if (parseFieldIdSeq(fields,
"expected field name"))
2339 for (
auto fieldName : fields) {
2340 std::optional<unsigned> indexV;
2341 auto type = result.getType();
2342 if (
auto refTy = type_dyn_cast<RefType>(type))
2343 type = refTy.getType();
2344 if (
auto bundle = type_dyn_cast<BundleType>(type))
2345 indexV = bundle.getElementIndex(fieldName);
2346 else if (
auto bundle = type_dyn_cast<OpenBundleType>(type))
2347 indexV = bundle.getElementIndex(fieldName);
2348 else if (
auto klass = type_dyn_cast<ClassType>(type))
2349 indexV = klass.getElementIndex(fieldName);
2351 return emitError(loc,
"subfield requires bundle or object operand ");
2353 return emitError(loc,
"unknown field '" + fieldName +
"' in type ")
2354 << result.getType();
2355 auto indexNo = *indexV;
2357 FailureOr<Value> subResult;
2358 if (type_isa<RefType>(result.getType()))
2359 subResult = emitCachedSubAccess<RefSubOp>(result, indexNo, loc);
2360 else if (type_isa<ClassType>(type))
2361 subResult = emitCachedSubAccess<ObjectSubfieldOp>(result, indexNo, loc);
2362 else if (type_isa<BundleType>(type))
2363 subResult = emitCachedSubAccess<SubfieldOp>(result, indexNo, loc);
2365 subResult = emitCachedSubAccess<OpenSubfieldOp>(result, indexNo, loc);
2367 if (failed(subResult))
2369 result = *subResult;
2378 ParseResult FIRStmtParser::parsePostFixIntSubscript(Value &result) {
2379 auto loc = getToken().getLoc();
2381 if (parseIntLit(indexNo,
"expected index") ||
2382 parseToken(FIRToken::r_square,
"expected ']'"))
2386 return emitError(loc,
"invalid index specifier"), failure();
2388 FailureOr<Value> subResult;
2389 if (type_isa<RefType>(result.getType()))
2390 subResult = emitCachedSubAccess<RefSubOp>(result, indexNo, loc);
2391 else if (type_isa<FVectorType>(result.getType()))
2392 subResult = emitCachedSubAccess<SubindexOp>(result, indexNo, loc);
2394 subResult = emitCachedSubAccess<OpenSubindexOp>(result, indexNo, loc);
2396 if (failed(subResult))
2398 result = *subResult;
2406 ParseResult FIRStmtParser::parsePostFixDynamicSubscript(Value &result) {
2407 auto loc = getToken().getLoc();
2409 if (parseExp(index,
"expected subscript index expression") ||
2410 parseToken(FIRToken::r_square,
"expected ']' in subscript"))
2414 auto indexType = type_dyn_cast<FIRRTLBaseType>(index.getType());
2416 return emitError(
"expected base type for index expression");
2417 indexType = indexType.getPassiveType();
2418 locationProcessor.setLoc(loc);
2423 SubaccessOp::inferReturnType(result.getType(), index.getType(), {});
2426 (void)SubaccessOp::inferReturnType(result.getType(), index.getType(),
2427 translateLocation(loc));
2432 auto op = builder.create<SubaccessOp>(resultType, result, index);
2433 result = op.getResult();
2439 ParseResult FIRStmtParser::parseIntegerLiteralExp(Value &result) {
2440 bool isSigned = getToken().is(FIRToken::kw_SInt);
2441 auto loc = getToken().getLoc();
2447 if (parseOptionalWidth(width) ||
2448 parseToken(FIRToken::l_paren,
"expected '(' in integer expression") ||
2449 parseIntLit(value,
"expected integer value") ||
2450 parseToken(FIRToken::r_paren,
"expected ')' in integer expression"))
2455 auto type =
IntType::get(builder.getContext(), isSigned, width,
true);
2457 IntegerType::SignednessSemantics signedness =
2458 isSigned ? IntegerType::Signed : IntegerType::Unsigned;
2460 if (!value.isZero())
2461 return emitError(loc,
"zero bit constant must be zero");
2462 value = value.trunc(0);
2463 }
else if (width != -1) {
2465 bool valueFits = isSigned ? value.isSignedIntN(width) : value.isIntN(width);
2467 return emitError(loc,
"initializer too wide for declared width");
2468 value = isSigned ? value.sextOrTrunc(width) : value.zextOrTrunc(width);
2473 auto attr = builder.getIntegerAttr(attrType, value);
2476 auto &entry = moduleContext.constantCache[{attr, type}];
2483 locationProcessor.setLoc(loc);
2484 result = moduleContext.getCachedConstant(builder, attr, type, attr);
2489 ParseResult FIRStmtParser::parseListExp(Value &result) {
2490 auto loc = getToken().getLoc();
2492 if (parseListType(type))
2494 auto listType = type_cast<ListType>(type);
2497 if (parseToken(FIRToken::l_paren,
"expected '(' in List expression"))
2500 SmallVector<Value, 3> operands;
2501 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2503 locationProcessor.setLoc(loc);
2504 if (parseExp(operand,
"expected expression in List expression"))
2508 if (!isa<AnyRefType>(elementType) ||
2509 !isa<ClassType>(operand.getType()))
2510 return emitError(loc,
"unexpected expression of type ")
2511 << operand.getType() <<
" in List expression of type "
2513 operand = builder.create<ObjectAnyRefCastOp>(operand);
2516 operands.push_back(operand);
2521 locationProcessor.setLoc(loc);
2522 result = builder.create<ListCreateOp>(listType, operands);
2527 ParseResult FIRStmtParser::parseListConcatExp(Value &result) {
2528 consumeToken(FIRToken::lp_list_concat);
2530 auto loc = getToken().getLoc();
2532 SmallVector<Value, 3> operands;
2533 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2535 locationProcessor.setLoc(loc);
2536 if (parseExp(operand,
"expected expression in List concat expression"))
2539 if (!type_isa<ListType>(operand.getType()))
2540 return emitError(loc,
"unexpected expression of type ")
2541 << operand.getType() <<
" in List concat expression";
2544 type = type_cast<ListType>(operand.getType());
2546 if (operand.getType() != type)
2547 return emitError(loc,
"unexpected expression of type ")
2548 << operand.getType() <<
" in List concat expression of type "
2551 operands.push_back(operand);
2556 if (operands.empty())
2557 return emitError(loc,
"need at least one List to concatenate");
2559 locationProcessor.setLoc(loc);
2560 result = builder.create<ListConcatOp>(type, operands);
2581 std::optional<ParseResult>
2582 FIRStmtParser::parseExpWithLeadingKeyword(
FIRToken keyword) {
2583 switch (getToken().getKind()) {
2586 return std::nullopt;
2588 case FIRToken::period:
2589 case FIRToken::l_square:
2590 case FIRToken::kw_is:
2591 case FIRToken::less_equal:
2597 auto loc = keyword.
getLoc();
2599 if (moduleContext.lookupSymbolEntry(symtabEntry, keyword.
getSpelling(), loc))
2600 return ParseResult(failure());
2606 if (moduleContext.resolveSymbolEntry(lhs, symtabEntry, loc,
false)) {
2609 if (!consumeIf(FIRToken::period))
2610 return ParseResult(failure());
2612 StringRef fieldName;
2613 if (parseFieldId(fieldName,
"expected field name") ||
2614 moduleContext.resolveSymbolEntry(lhs, symtabEntry, fieldName, loc))
2615 return ParseResult(failure());
2619 if (parseOptionalExpPostscript(lhs))
2620 return ParseResult(failure());
2622 return parseLeadingExpStmt(lhs);
2628 ParseResult FIRStmtParser::parseSimpleStmtBlock(
unsigned indent) {
2631 if (getToken().isAny(FIRToken::eof, FIRToken::error))
2634 auto subIndent = getIndentation();
2635 if (!subIndent.has_value())
2636 return emitError(
"expected statement to be on its own line"), failure();
2638 if (*subIndent <= indent)
2642 if (parseSimpleStmt(*subIndent))
2647 ParseResult FIRStmtParser::parseSimpleStmt(
unsigned stmtIndent) {
2648 locationProcessor.startStatement();
2649 auto result = parseSimpleStmtImpl(stmtIndent);
2650 locationProcessor.endStatement(*
this);
2671 ParseResult FIRStmtParser::parseSimpleStmtImpl(
unsigned stmtIndent) {
2672 auto kind = getToken().getKind();
2675 case FIRToken::kw_invalidate:
2676 case FIRToken::kw_connect:
2677 case FIRToken::kw_regreset:
2681 kind = FIRToken::identifier;
2688 case FIRToken::kw_attach:
2689 return parseAttach();
2690 case FIRToken::kw_infer:
2691 return parseMemPort(MemDirAttr::Infer);
2692 case FIRToken::kw_read:
2693 return parseMemPort(MemDirAttr::Read);
2694 case FIRToken::kw_write:
2695 return parseMemPort(MemDirAttr::Write);
2696 case FIRToken::kw_rdwr:
2697 return parseMemPort(MemDirAttr::ReadWrite);
2698 case FIRToken::kw_connect:
2699 return parseConnect();
2700 case FIRToken::kw_propassign:
2701 if (requireFeature({3, 1, 0},
"properties"))
2703 return parsePropAssign();
2704 case FIRToken::kw_invalidate:
2705 return parseInvalidate();
2706 case FIRToken::lp_printf:
2707 return parsePrintf();
2708 case FIRToken::kw_skip:
2710 case FIRToken::lp_stop:
2712 case FIRToken::lp_assert:
2713 return parseAssert();
2714 case FIRToken::lp_assume:
2715 return parseAssume();
2716 case FIRToken::lp_cover:
2717 return parseCover();
2718 case FIRToken::kw_when:
2719 return parseWhen(stmtIndent);
2720 case FIRToken::kw_match:
2721 return parseMatch(stmtIndent);
2722 case FIRToken::kw_define:
2723 return parseRefDefine();
2724 case FIRToken::lp_force:
2725 return parseRefForce();
2726 case FIRToken::lp_force_initial:
2727 return parseRefForceInitial();
2728 case FIRToken::lp_release:
2729 return parseRefRelease();
2730 case FIRToken::lp_release_initial:
2731 return parseRefReleaseInitial();
2732 case FIRToken::kw_group:
2733 if (requireFeature({3, 2, 0},
"optional groups") ||
2734 removedFeature({3, 3, 0},
"optional groups"))
2736 return parseLayerBlockOrGroup(stmtIndent);
2737 case FIRToken::kw_layerblock:
2738 if (requireFeature({3, 3, 0},
"layers"))
2740 return parseLayerBlockOrGroup(stmtIndent);
2741 case FIRToken::lp_intrinsic:
2742 if (requireFeature({4, 0, 0},
"generic intrinsics"))
2744 return parseIntrinsicStmt();
2748 if (parseExpLeadingStmt(lhs,
"unexpected token in module"))
2755 return parseLeadingExpStmt(lhs);
2759 case FIRToken::kw_inst:
2760 return parseInstance();
2761 case FIRToken::kw_instchoice:
2762 return parseInstanceChoice();
2763 case FIRToken::kw_object:
2764 return parseObject();
2765 case FIRToken::kw_cmem:
2766 return parseCombMem();
2767 case FIRToken::kw_smem:
2768 return parseSeqMem();
2769 case FIRToken::kw_mem:
2770 return parseMem(stmtIndent);
2771 case FIRToken::kw_node:
2773 case FIRToken::kw_wire:
2775 case FIRToken::kw_reg:
2776 return parseRegister(stmtIndent);
2777 case FIRToken::kw_regreset:
2778 return parseRegisterWithReset();
2782 ParseResult FIRStmtParser::parseSubBlock(Block &blockToInsertInto,
2784 SymbolRefAttr layerSym) {
2786 auto suiteScope = std::make_unique<FIRModuleContext::ContextScope>(
2787 moduleContext, &blockToInsertInto);
2792 UnbundledValueRestorer x(moduleContext.unbundledValues);
2796 auto subParser = std::make_unique<FIRStmtParser>(
2797 blockToInsertInto, moduleContext, innerSymFixups, circuitSymTbl, version,
2801 auto stmtIndent = getIndentation();
2804 if (!stmtIndent.has_value())
2805 return subParser->parseSimpleStmt(indent);
2807 if (*stmtIndent <= indent)
2808 return emitError(
"statement must be indented more than previous statement"),
2812 return subParser->parseSimpleStmtBlock(indent);
2816 ParseResult FIRStmtParser::parseAttach() {
2817 auto startTok = consumeToken(FIRToken::kw_attach);
2820 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2823 if (parseToken(FIRToken::l_paren,
"expected '(' after attach"))
2826 SmallVector<Value, 4> operands;
2827 operands.push_back({});
2828 if (parseExp(operands.back(),
"expected operand in attach"))
2831 while (consumeIf(FIRToken::comma)) {
2832 operands.push_back({});
2833 if (parseExp(operands.back(),
"expected operand in attach"))
2836 if (parseToken(FIRToken::r_paren,
"expected close paren"))
2839 if (parseOptionalInfo())
2842 locationProcessor.setLoc(startTok.getLoc());
2843 builder.create<AttachOp>(operands);
2850 ParseResult FIRStmtParser::parseMemPort(MemDirAttr direction) {
2851 auto startTok = consumeToken();
2852 auto startLoc = startTok.getLoc();
2856 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2862 Value memory, indexExp, clock;
2863 if (parseToken(FIRToken::kw_mport,
"expected 'mport' in memory port") ||
2864 parseId(
id,
"expected result name") ||
2865 parseToken(FIRToken::equal,
"expected '=' in memory port") ||
2866 parseId(memName,
"expected memory name") ||
2867 moduleContext.lookupSymbolEntry(memorySym, memName, startLoc) ||
2868 moduleContext.resolveSymbolEntry(memory, memorySym, startLoc) ||
2869 parseToken(FIRToken::l_square,
"expected '[' in memory port") ||
2870 parseExp(indexExp,
"expected index expression") ||
2871 parseToken(FIRToken::r_square,
"expected ']' in memory port") ||
2872 parseToken(FIRToken::comma,
"expected ','") ||
2873 parseExp(clock,
"expected clock expression") || parseOptionalInfo())
2876 auto memVType = type_dyn_cast<CMemoryType>(memory.getType());
2878 return emitError(startLoc,
2879 "memory port should have behavioral memory type");
2880 auto resultType = memVType.getElementType();
2882 ArrayAttr annotations = getConstants().emptyArrayAttr;
2883 locationProcessor.setLoc(startLoc);
2886 Value memoryPort, memoryData;
2888 OpBuilder::InsertionGuard guard(builder);
2889 builder.setInsertionPointAfterValue(memory);
2890 auto memoryPortOp = builder.create<MemoryPortOp>(
2893 memoryData = memoryPortOp.getResult(0);
2894 memoryPort = memoryPortOp.getResult(1);
2898 builder.create<MemoryPortAccessOp>(memoryPort, indexExp, clock);
2900 return moduleContext.addSymbolEntry(
id, memoryData, startLoc,
true);
2904 ParseResult FIRStmtParser::parsePrintf() {
2905 auto startTok = consumeToken(FIRToken::lp_printf);
2907 Value clock, condition;
2908 StringRef formatString;
2909 if (parseExp(clock,
"expected clock expression in printf") ||
2910 parseToken(FIRToken::comma,
"expected ','") ||
2911 parseExp(condition,
"expected condition in printf") ||
2912 parseToken(FIRToken::comma,
"expected ','") ||
2913 parseGetSpelling(formatString) ||
2914 parseToken(FIRToken::string,
"expected format string in printf"))
2917 SmallVector<Value, 4> operands;
2918 while (consumeIf(FIRToken::comma)) {
2919 operands.push_back({});
2920 if (parseExp(operands.back(),
"expected operand in printf"))
2923 if (parseToken(FIRToken::r_paren,
"expected ')'"))
2927 if (parseOptionalName(name))
2930 if (parseOptionalInfo())
2933 locationProcessor.setLoc(startTok.getLoc());
2936 builder.create<PrintFOp>(clock, condition,
2937 builder.getStringAttr(formatStrUnescaped), operands,
2943 ParseResult FIRStmtParser::parseSkip() {
2944 auto startTok = consumeToken(FIRToken::kw_skip);
2948 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2951 if (parseOptionalInfo())
2954 locationProcessor.setLoc(startTok.getLoc());
2955 builder.create<SkipOp>();
2960 ParseResult FIRStmtParser::parseStop() {
2961 auto startTok = consumeToken(FIRToken::lp_stop);
2963 Value clock, condition;
2966 if (parseExp(clock,
"expected clock expression in 'stop'") ||
2967 parseToken(FIRToken::comma,
"expected ','") ||
2968 parseExp(condition,
"expected condition in 'stop'") ||
2969 parseToken(FIRToken::comma,
"expected ','") ||
2970 parseIntLit(exitCode,
"expected exit code in 'stop'") ||
2971 parseToken(FIRToken::r_paren,
"expected ')' in 'stop'") ||
2972 parseOptionalName(name) || parseOptionalInfo())
2975 locationProcessor.setLoc(startTok.getLoc());
2976 builder.create<StopOp>(clock, condition, builder.getI32IntegerAttr(exitCode),
2982 ParseResult FIRStmtParser::parseAssert() {
2983 auto startTok = consumeToken(FIRToken::lp_assert);
2985 Value clock, predicate, enable;
2986 StringRef formatString;
2988 if (parseExp(clock,
"expected clock expression in 'assert'") ||
2989 parseToken(FIRToken::comma,
"expected ','") ||
2990 parseExp(predicate,
"expected predicate in 'assert'") ||
2991 parseToken(FIRToken::comma,
"expected ','") ||
2992 parseExp(enable,
"expected enable in 'assert'") ||
2993 parseToken(FIRToken::comma,
"expected ','") ||
2994 parseGetSpelling(formatString) ||
2995 parseToken(FIRToken::string,
"expected format string in 'assert'"))
2998 SmallVector<Value, 4> operands;
2999 while (!consumeIf(FIRToken::r_paren)) {
3000 operands.push_back({});
3001 if (parseToken(FIRToken::comma,
"expected ','") ||
3002 parseExp(operands.back(),
"expected operand in 'assert'"))
3006 if (parseOptionalName(name) || parseOptionalInfo())
3009 locationProcessor.setLoc(startTok.getLoc());
3011 builder.create<AssertOp>(clock, predicate, enable, formatStrUnescaped,
3012 operands, name.getValue());
3017 ParseResult FIRStmtParser::parseAssume() {
3018 auto startTok = consumeToken(FIRToken::lp_assume);
3020 Value clock, predicate, enable;
3021 StringRef formatString;
3023 if (parseExp(clock,
"expected clock expression in 'assume'") ||
3024 parseToken(FIRToken::comma,
"expected ','") ||
3025 parseExp(predicate,
"expected predicate in 'assume'") ||
3026 parseToken(FIRToken::comma,
"expected ','") ||
3027 parseExp(enable,
"expected enable in 'assume'") ||
3028 parseToken(FIRToken::comma,
"expected ','") ||
3029 parseGetSpelling(formatString) ||
3030 parseToken(FIRToken::string,
"expected format string in 'assume'"))
3033 SmallVector<Value, 4> operands;
3034 while (!consumeIf(FIRToken::r_paren)) {
3035 operands.push_back({});
3036 if (parseToken(FIRToken::comma,
"expected ','") ||
3037 parseExp(operands.back(),
"expected operand in 'assume'"))
3041 if (parseOptionalName(name) || parseOptionalInfo())
3044 locationProcessor.setLoc(startTok.getLoc());
3046 builder.create<AssumeOp>(clock, predicate, enable, formatStrUnescaped,
3047 operands, name.getValue());
3052 ParseResult FIRStmtParser::parseCover() {
3053 auto startTok = consumeToken(FIRToken::lp_cover);
3055 Value clock, predicate, enable;
3058 if (parseExp(clock,
"expected clock expression in 'cover'") ||
3059 parseToken(FIRToken::comma,
"expected ','") ||
3060 parseExp(predicate,
"expected predicate in 'cover'") ||
3061 parseToken(FIRToken::comma,
"expected ','") ||
3062 parseExp(enable,
"expected enable in 'cover'") ||
3063 parseToken(FIRToken::comma,
"expected ','") ||
3064 parseGetSpelling(message) ||
3065 parseToken(FIRToken::string,
"expected message in 'cover'") ||
3066 parseToken(FIRToken::r_paren,
"expected ')' in 'cover'") ||
3067 parseOptionalName(name) || parseOptionalInfo())
3070 locationProcessor.setLoc(startTok.getLoc());
3072 builder.create<CoverOp>(clock, predicate, enable, messageUnescaped,
3073 ValueRange{}, name.getValue());
3079 ParseResult FIRStmtParser::parseWhen(
unsigned whenIndent) {
3080 auto startTok = consumeToken(FIRToken::kw_when);
3084 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3088 if (parseExp(condition,
"expected condition in 'when'") ||
3089 parseToken(FIRToken::colon,
"expected ':' in when") ||
3090 parseOptionalInfo())
3093 locationProcessor.setLoc(startTok.getLoc());
3095 auto whenStmt = builder.create<WhenOp>(condition,
false);
3098 if (parseSubBlock(whenStmt.getThenBlock(), whenIndent, layerSym))
3102 if (getToken().isNot(FIRToken::kw_else))
3107 auto elseIndent = getIndentation();
3108 if (elseIndent && *elseIndent < whenIndent)
3111 consumeToken(FIRToken::kw_else);
3114 whenStmt.createElseRegion();
3120 if (getToken().is(FIRToken::kw_when)) {
3122 auto subParser = std::make_unique<FIRStmtParser>(
3123 whenStmt.getElseBlock(), moduleContext, innerSymFixups, circuitSymTbl,
3126 return subParser->parseSimpleStmt(whenIndent);
3130 LocationAttr elseLoc;
3131 if (parseToken(FIRToken::colon,
"expected ':' after 'else'") ||
3132 parseOptionalInfoLocator(elseLoc) ||
3133 parseSubBlock(whenStmt.getElseBlock(), whenIndent, layerSym))
3142 ParseResult FIRStmtParser::parseEnumExp(Value &value) {
3143 auto startLoc = getToken().getLoc();
3144 locationProcessor.setLoc(startLoc);
3146 if (parseEnumType(type))
3150 auto enumType = type_dyn_cast<FEnumType>(type);
3152 return emitError(startLoc,
3153 "expected enumeration type in enumeration expression");
3156 if (parseToken(FIRToken::l_paren,
"expected '(' in enumeration expression") ||
3157 parseId(tag,
"expected enumeration tag"))
3161 if (consumeIf(FIRToken::r_paren)) {
3164 auto type =
IntType::get(builder.getContext(),
false, 0,
true);
3166 auto attr = builder.getIntegerAttr(attrType, APInt(0, 0,
false));
3167 input = builder.create<ConstantOp>(type, attr);
3170 if (parseToken(FIRToken::comma,
"expected ','") ||
3171 parseExp(input,
"expected expression in enumeration value") ||
3172 parseToken(FIRToken::r_paren,
"expected closing ')'"))
3176 value = builder.create<FEnumCreateOp>(enumType, tag, input);
3184 ParseResult FIRStmtParser::parseMatch(
unsigned matchIndent) {
3185 auto startTok = consumeToken(FIRToken::kw_match);
3187 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3191 if (parseExp(input,
"expected expression in 'match'") ||
3192 parseToken(FIRToken::colon,
"expected ':' in 'match'") ||
3193 parseOptionalInfo())
3196 auto enumType = type_dyn_cast<FEnumType>(input.getType());
3198 return mlir::emitError(
3200 "expected enumeration type for 'match' statement, but got ")
3203 locationProcessor.setLoc(startTok.getLoc());
3205 SmallVector<Attribute> tags;
3206 SmallVector<std::unique_ptr<Region>> regions;
3208 auto tagLoc = getToken().getLoc();
3211 auto caseIndent = getIndentation();
3212 if (!caseIndent || *caseIndent <= matchIndent)
3216 StringRef tagSpelling;
3217 if (parseId(tagSpelling,
"expected enumeration tag in match statement"))
3219 auto tagIndex = enumType.getElementIndex(tagSpelling);
3221 return emitError(tagLoc,
"tag ")
3222 << tagSpelling <<
" not a member of enumeration " << enumType;
3224 tags.push_back(tag);
3227 auto *caseBlock = ®ions.emplace_back(
new Region)->emplaceBlock();
3230 FIRModuleContext::ContextScope scope(moduleContext, caseBlock);
3235 UnbundledValueRestorer x(moduleContext.unbundledValues);
3238 if (consumeIf(FIRToken::l_paren)) {
3239 StringAttr identifier;
3240 if (parseId(identifier,
"expected identifier for 'case' binding"))
3244 auto dataType = enumType.getElementType(*tagIndex);
3245 caseBlock->addArgument(dataType, LocWithInfo(tagLoc,
this).getLoc());
3247 if (moduleContext.addSymbolEntry(identifier, caseBlock->getArgument(0),
3251 if (parseToken(FIRToken::r_paren,
"expected ')' in match statement case"))
3255 auto dataType =
IntType::get(builder.getContext(),
false, 0);
3256 caseBlock->addArgument(dataType, LocWithInfo(tagLoc,
this).getLoc());
3259 if (parseToken(FIRToken::colon,
"expected ':' in match statement case"))
3263 auto subParser = std::make_unique<FIRStmtParser>(
3264 *caseBlock, moduleContext, innerSymFixups, circuitSymTbl, version,
3266 if (subParser->parseSimpleStmtBlock(*caseIndent))
3270 builder.create<MatchOp>(input,
ArrayAttr::get(getContext(), tags), regions);
3276 ParseResult FIRStmtParser::parseRefExp(Value &result,
const Twine &message) {
3277 auto token = getToken().getKind();
3278 if (token == FIRToken::lp_probe)
3279 return parseProbe(result);
3280 if (token == FIRToken::lp_rwprobe)
3281 return parseRWProbe(result);
3286 return parseStaticRefExp(result, message);
3293 ParseResult FIRStmtParser::parseStaticRefExp(Value &result,
3294 const Twine &message) {
3295 auto parseIdOrInstance = [&]() -> ParseResult {
3297 auto loc = getToken().getLoc();
3299 if (parseId(
id, message) ||
3300 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
3304 if (!moduleContext.resolveSymbolEntry(result, symtabEntry, loc,
false))
3310 StringRef fieldName;
3312 parseToken(FIRToken::period,
"expected '.' in field reference") ||
3313 parseFieldId(fieldName,
"expected field name") ||
3314 moduleContext.resolveSymbolEntry(result, symtabEntry, fieldName, loc));
3316 return failure(parseIdOrInstance() ||
3317 parseOptionalExpPostscript(result,
false));
3328 ParseResult FIRStmtParser::parseRWProbeStaticRefExp(
FieldRef &refResult,
3330 const Twine &message) {
3331 auto loc = getToken().getLoc();
3335 if (parseId(
id, message) ||
3336 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
3348 if (
auto unbundledId = dyn_cast<UnbundledID>(symtabEntry)) {
3350 auto &ubEntry = moduleContext.getUnbundledEntry(unbundledId - 1);
3352 StringRef fieldName;
3353 auto loc = getToken().getLoc();
3354 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
3355 parseFieldId(fieldName,
"expected field name"))
3361 for (
auto &elt : ubEntry) {
3362 if (elt.first == fieldAttr) {
3365 auto &instResult = elt.second;
3368 auto *defining = instResult.getDefiningOp();
3370 if (isa<WireOp>(defining)) {
3371 result = instResult;
3376 auto type = instResult.getType();
3380 bool forceable =
static_cast<bool>(
3383 return emitError(loc,
"unable to force instance result of type ")
3387 auto annotations = getConstants().emptyArrayAttr;
3388 StringAttr sym = {};
3389 SmallString<64> name;
3390 (
id +
"_" + fieldName +
"_bounce").
toVector(name);
3391 locationProcessor.setLoc(loc);
3392 OpBuilder::InsertionGuard guard(builder);
3393 builder.setInsertionPoint(defining);
3394 auto bounce = builder.create<WireOp>(
3395 type, name, NameKindEnum::InterestingName, annotations, sym);
3396 auto bounceVal = bounce.getData();
3399 instResult.replaceAllUsesWith(bounceVal);
3402 builder.setInsertionPointAfter(defining);
3410 result = instResult = bounce.getDataRaw();
3416 emitError(loc,
"use of invalid field name '")
3417 << fieldName <<
"' on bundle value";
3422 result = symtabEntry.get<Value>();
3426 assert(isa<BlockArgument>(result) ||
3427 result.getDefiningOp<hw::InnerSymbolOpInterface>());
3433 type = result.getType();
3435 if (consumeIf(FIRToken::period)) {
3436 SmallVector<StringRef, 3> fields;
3437 if (parseFieldIdSeq(fields,
"expected field name"))
3439 for (
auto fieldName : fields) {
3440 if (
auto bundle = type_dyn_cast<BundleType>(type)) {
3441 if (
auto index = bundle.getElementIndex(fieldName)) {
3442 refResult = refResult.
getSubField(bundle.getFieldID(*index));
3443 type = bundle.getElementTypePreservingConst(*index);
3446 }
else if (
auto bundle = type_dyn_cast<OpenBundleType>(type)) {
3447 if (
auto index = bundle.getElementIndex(fieldName)) {
3448 refResult = refResult.
getSubField(bundle.getFieldID(*index));
3449 type = bundle.getElementTypePreservingConst(*index);
3453 return emitError(loc,
"subfield requires bundle operand")
3454 <<
"got " << type <<
"\n";
3456 return emitError(loc,
3457 "unknown field '" + fieldName +
"' in bundle type ")
3462 if (consumeIf(FIRToken::l_square)) {
3463 auto loc = getToken().
getLoc();
3465 if (parseIntLit(index,
"expected index") ||
3466 parseToken(FIRToken::r_square,
"expected ']'"))
3470 return emitError(loc,
"invalid index specifier");
3472 if (
auto vector = type_dyn_cast<FVectorType>(type)) {
3473 if ((
unsigned)index < vector.getNumElements()) {
3474 refResult = refResult.
getSubField(vector.getFieldID(index));
3475 type = vector.getElementTypePreservingConst();
3478 }
else if (
auto vector = type_dyn_cast<OpenVectorType>(type)) {
3479 if ((
unsigned)index < vector.getNumElements()) {
3480 refResult = refResult.
getSubField(vector.getFieldID(index));
3481 type = vector.getElementTypePreservingConst();
3485 return emitError(loc,
"subindex requires vector operand");
3487 return emitError(loc,
"out of range index '")
3488 << index <<
"' for vector type " << type;
3496 ParseResult FIRStmtParser::parseIntrinsic(Value &result,
bool isStatement) {
3497 auto startTok = consumeToken(FIRToken::lp_intrinsic);
3498 StringRef intrinsic;
3499 ArrayAttr parameters;
3502 if (parseId(intrinsic,
"expected intrinsic identifier") ||
3503 parseOptionalParams(parameters))
3506 if (consumeIf(FIRToken::colon)) {
3507 if (
parseType(type,
"expected intrinsic return type"))
3509 }
else if (!isStatement)
3510 return emitError(
"expected ':' in intrinsic expression");
3512 SmallVector<Value> operands;
3513 auto loc = startTok.getLoc();
3514 if (consumeIf(FIRToken::comma)) {
3515 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
3517 if (parseExp(operand,
"expected operand in intrinsic"))
3519 operands.push_back(operand);
3520 locationProcessor.setLoc(loc);
3525 if (parseToken(FIRToken::r_paren,
"expected ')' in intrinsic"))
3530 if (parseOptionalInfo())
3533 locationProcessor.setLoc(loc);
3535 auto op = builder.create<GenericIntrinsicOp>(
3536 type, builder.getStringAttr(intrinsic), operands, parameters);
3538 result = op.getResult();
3543 ParseResult FIRStmtParser::parseOptionalParams(ArrayAttr &resultParameters) {
3544 if (!consumeIf(FIRToken::less))
3547 SmallVector<Attribute, 8> parameters;
3548 SmallPtrSet<StringAttr, 8> seen;
3549 if (parseListUntil(FIRToken::greater, [&]() -> ParseResult {
3553 if (parseParameter(name, value, loc))
3555 auto typedValue = dyn_cast<TypedAttr>(value);
3557 return emitError(loc)
3558 <<
"invalid value for parameter '" << name.getValue() <<
"'";
3559 if (!seen.insert(name).second)
3560 return emitError(loc,
"redefinition of parameter '" +
3561 name.getValue() +
"'");
3573 ParseResult FIRStmtParser::parsePathExp(Value &result) {
3574 auto startTok = consumeToken(FIRToken::lp_path);
3575 locationProcessor.setLoc(startTok.getLoc());
3577 if (parseGetSpelling(target) ||
3578 parseToken(FIRToken::string,
3579 "expected target string in path expression") ||
3580 parseToken(FIRToken::r_paren,
"expected ')' in path expression"))
3582 result = builder.create<UnresolvedPathOp>(
3588 ParseResult FIRStmtParser::parseRefDefine() {
3589 auto startTok = consumeToken(FIRToken::kw_define);
3592 if (parseStaticRefExp(target,
3593 "expected static reference expression in 'define'") ||
3594 parseToken(FIRToken::equal,
3595 "expected '=' after define reference expression") ||
3596 parseRefExp(src,
"expected reference expression in 'define'") ||
3597 parseOptionalInfo())
3601 if (!type_isa<RefType>(target.getType()))
3602 return emitError(startTok.getLoc(),
"expected reference-type expression in "
3603 "'define' target (LHS), got ")
3604 << target.getType();
3605 if (!type_isa<RefType>(src.getType()))
3606 return emitError(startTok.getLoc(),
"expected reference-type expression in "
3607 "'define' source (RHS), got ")
3612 if (isa_and_nonnull<RefSubOp>(target.getDefiningOp()))
3613 return emitError(startTok.getLoc(),
3614 "cannot define into a sub-element of a reference");
3616 locationProcessor.setLoc(startTok.getLoc());
3619 return emitError(startTok.getLoc(),
"cannot define reference of type ")
3620 << target.getType() <<
" with incompatible reference of type "
3630 ParseResult FIRStmtParser::parseRefRead(Value &result) {
3631 auto startTok = consumeToken(FIRToken::lp_read);
3634 if (parseRefExp(ref,
"expected reference expression in 'read'") ||
3635 parseToken(FIRToken::r_paren,
"expected ')' in 'read'"))
3638 locationProcessor.setLoc(startTok.getLoc());
3641 if (!type_isa<RefType>(ref.getType()))
3642 return emitError(startTok.getLoc(),
3643 "expected reference-type expression in 'read', got ")
3646 result = builder.create<RefResolveOp>(ref);
3652 ParseResult FIRStmtParser::parseProbe(Value &result) {
3653 auto startTok = consumeToken(FIRToken::lp_probe);
3656 if (parseStaticRefExp(staticRef,
3657 "expected static reference expression in 'probe'") ||
3658 parseToken(FIRToken::r_paren,
"expected ')' in 'probe'"))
3661 locationProcessor.setLoc(startTok.getLoc());
3664 if (!type_isa<FIRRTLBaseType>(staticRef.getType()))
3665 return emitError(startTok.getLoc(),
3666 "expected base-type expression in 'probe', got ")
3667 << staticRef.getType();
3671 if (isa_and_nonnull<MemOp, CombMemOp, SeqMemOp, MemoryPortOp,
3672 MemoryDebugPortOp, MemoryPortAccessOp>(
3673 staticRef.getDefiningOp()))
3674 return emitError(startTok.getLoc(),
"cannot probe memories or their ports");
3676 result = builder.create<RefSendOp>(staticRef);
3682 ParseResult FIRStmtParser::parseRWProbe(Value &result) {
3683 auto startTok = consumeToken(FIRToken::lp_rwprobe);
3686 Type parsedTargetType;
3687 if (parseRWProbeStaticRefExp(
3688 staticRef, parsedTargetType,
3689 "expected static reference expression in 'rwprobe'") ||
3690 parseToken(FIRToken::r_paren,
"expected ')' in 'rwprobe'"))
3693 locationProcessor.setLoc(startTok.getLoc());
3699 auto targetType = type_dyn_cast<FIRRTLBaseType>(parsedTargetType);
3701 return emitError(startTok.getLoc(),
3702 "expected base-type expression in 'rwprobe', got ")
3703 << parsedTargetType;
3706 auto *definingOp = root.getDefiningOp();
3708 if (isa_and_nonnull<MemOp, CombMemOp, SeqMemOp, MemoryPortOp,
3709 MemoryDebugPortOp, MemoryPortAccessOp>(definingOp))
3710 return emitError(startTok.getLoc(),
"cannot probe memories or their ports");
3714 return emitError(startTok.getLoc(),
"cannot force target of type ")
3718 auto op = builder.create<RWProbeOp>(forceableType,
3719 getConstants().placeholderInnerRef);
3726 ParseResult FIRStmtParser::parseRefForce() {
3727 auto startTok = consumeToken(FIRToken::lp_force);
3729 Value clock, pred, dest, src;
3730 if (parseExp(clock,
"expected clock expression in force") ||
3731 parseToken(FIRToken::comma,
"expected ','") ||
3732 parseExp(pred,
"expected predicate expression in force") ||
3733 parseToken(FIRToken::comma,
"expected ','") ||
3734 parseRefExp(dest,
"expected destination reference expression in force") ||
3735 parseToken(FIRToken::comma,
"expected ','") ||
3736 parseExp(src,
"expected source expression in force") ||
3737 parseToken(FIRToken::r_paren,
"expected ')' in force") ||
3738 parseOptionalInfo())
3742 auto ref = type_dyn_cast<RefType>(dest.getType());
3743 if (!ref || !ref.getForceable())
3746 "expected rwprobe-type expression for force destination, got ")
3748 auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(src.getType());
3750 return emitError(startTok.getLoc(),
3751 "expected base-type for force source, got ")
3753 if (!srcBaseType.isPassive())
3754 return emitError(startTok.getLoc(),
3755 "expected passive value for force source, got ")
3758 locationProcessor.setLoc(startTok.getLoc());
3761 auto noConstSrcType = srcBaseType.getAllConstDroppedType();
3762 if (noConstSrcType != ref.getType()) {
3764 auto compatibleRWProbe =
RefType::get(noConstSrcType,
true, ref.getLayer());
3766 dest = builder.create<RefCastOp>(compatibleRWProbe, dest);
3768 return emitError(startTok.getLoc(),
"incompatible force source of type ")
3769 << src.getType() <<
" cannot target destination "
3773 builder.create<RefForceOp>(clock, pred, dest, src);
3779 ParseResult FIRStmtParser::parseRefForceInitial() {
3780 auto startTok = consumeToken(FIRToken::lp_force_initial);
3784 dest,
"expected destination reference expression in force_initial") ||
3785 parseToken(FIRToken::comma,
"expected ','") ||
3786 parseExp(src,
"expected source expression in force_initial") ||
3787 parseToken(FIRToken::r_paren,
"expected ')' in force_initial") ||
3788 parseOptionalInfo())
3792 auto ref = type_dyn_cast<RefType>(dest.getType());
3793 if (!ref || !ref.getForceable())
3794 return emitError(startTok.getLoc(),
"expected rwprobe-type expression for "
3795 "force_initial destination, got ")
3797 auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(src.getType());
3799 return emitError(startTok.getLoc(),
3800 "expected base-type expression for force_initial "
3803 if (!srcBaseType.isPassive())
3804 return emitError(startTok.getLoc(),
3805 "expected passive value for force_initial source, got ")
3808 locationProcessor.setLoc(startTok.getLoc());
3811 auto noConstSrcType = srcBaseType.getAllConstDroppedType();
3812 if (noConstSrcType != ref.getType()) {
3814 auto compatibleRWProbe =
RefType::get(noConstSrcType,
true, ref.getLayer());
3816 dest = builder.create<RefCastOp>(compatibleRWProbe, dest);
3818 return emitError(startTok.getLoc(),
3819 "incompatible force_initial source of type ")
3820 << src.getType() <<
" cannot target destination "
3824 auto value = APInt::getAllOnes(1);
3827 value.getBitWidth(),
3828 IntegerType::Unsigned),
3830 auto pred = moduleContext.getCachedConstant(builder, attr, type, attr);
3831 builder.create<RefForceInitialOp>(pred, dest, src);
3837 ParseResult FIRStmtParser::parseRefRelease() {
3838 auto startTok = consumeToken(FIRToken::lp_release);
3840 Value clock, pred, dest;
3841 if (parseExp(clock,
"expected clock expression in release") ||
3842 parseToken(FIRToken::comma,
"expected ','") ||
3843 parseExp(pred,
"expected predicate expression in release") ||
3844 parseToken(FIRToken::comma,
"expected ','") ||
3846 "expected destination reference expression in release") ||
3847 parseToken(FIRToken::r_paren,
"expected ')' in release") ||
3848 parseOptionalInfo())
3852 if (
auto ref = type_dyn_cast<RefType>(dest.getType());
3853 !ref || !ref.getForceable())
3856 "expected rwprobe-type expression for release destination, got ")
3859 locationProcessor.setLoc(startTok.getLoc());
3861 builder.create<RefReleaseOp>(clock, pred, dest);
3867 ParseResult FIRStmtParser::parseRefReleaseInitial() {
3868 auto startTok = consumeToken(FIRToken::lp_release_initial);
3873 "expected destination reference expression in release_initial") ||
3874 parseToken(FIRToken::r_paren,
"expected ')' in release_initial") ||
3875 parseOptionalInfo())
3879 if (
auto ref = type_dyn_cast<RefType>(dest.getType());
3880 !ref || !ref.getForceable())
3881 return emitError(startTok.getLoc(),
"expected rwprobe-type expression for "
3882 "release_initial destination, got ")
3885 locationProcessor.setLoc(startTok.getLoc());
3887 auto value = APInt::getAllOnes(1);
3890 value.getBitWidth(),
3891 IntegerType::Unsigned),
3893 auto pred = moduleContext.getCachedConstant(builder, attr, type, attr);
3894 builder.create<RefReleaseInitialOp>(pred, dest);
3900 ParseResult FIRStmtParser::parseConnect() {
3901 auto startTok = consumeToken(FIRToken::kw_connect);
3902 auto loc = startTok.getLoc();
3905 if (parseExp(lhs,
"expected connect expression") ||
3906 parseToken(FIRToken::comma,
"expected ','") ||
3907 parseExp(rhs,
"expected connect expression") || parseOptionalInfo())
3910 auto lhsType = type_dyn_cast<FIRRTLBaseType>(lhs.getType());
3911 auto rhsType = type_dyn_cast<FIRRTLBaseType>(rhs.getType());
3912 if (!lhsType || !rhsType)
3913 return emitError(loc,
"cannot connect reference or property types");
3915 if (lhsType.containsReference() || rhsType.containsReference())
3916 return emitError(loc,
"cannot connect types containing references");
3919 return emitError(loc,
"cannot connect non-equivalent type ")
3920 << rhsType <<
" to " << lhsType;
3922 locationProcessor.setLoc(loc);
3928 ParseResult FIRStmtParser::parsePropAssign() {
3929 auto startTok = consumeToken(FIRToken::kw_propassign);
3930 auto loc = startTok.getLoc();
3933 if (parseExp(lhs,
"expected propassign expression") ||
3934 parseToken(FIRToken::comma,
"expected ','") ||
3935 parseExp(rhs,
"expected propassign expression") || parseOptionalInfo())
3938 auto lhsType = type_dyn_cast<PropertyType>(lhs.getType());
3939 auto rhsType = type_dyn_cast<PropertyType>(rhs.getType());
3940 if (!lhsType || !rhsType)
3941 return emitError(loc,
"can only propassign property types");
3942 locationProcessor.setLoc(loc);
3943 if (lhsType != rhsType) {
3945 if (isa<AnyRefType>(lhsType) && isa<ClassType>(rhsType))
3946 rhs = builder.create<ObjectAnyRefCastOp>(rhs);
3948 return emitError(loc,
"cannot propassign non-equivalent type ")
3949 << rhsType <<
" to " << lhsType;
3951 builder.create<PropAssignOp>(lhs, rhs);
3956 ParseResult FIRStmtParser::parseInvalidate() {
3957 auto startTok = consumeToken(FIRToken::kw_invalidate);
3962 auto loc = getToken().getLoc();
3964 if (parseId(
id,
"expected static reference expression") ||
3965 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
3970 if (!moduleContext.resolveSymbolEntry(lhs, symtabEntry, loc,
false)) {
3971 if (parseOptionalExpPostscript(lhs,
false) ||
3972 parseOptionalInfo())
3975 locationProcessor.setLoc(startTok.getLoc());
3976 emitInvalidate(lhs);
3985 if (getToken().isNot(FIRToken::period)) {
3986 locationProcessor.setLoc(loc);
3988 unsigned unbundledId = symtabEntry.get<
UnbundledID>() - 1;
3990 for (
auto elt : ubEntry)
3991 emitInvalidate(elt.second);
3997 StringRef fieldName;
3998 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
3999 parseFieldId(fieldName,
"expected field name") ||
4000 moduleContext.resolveSymbolEntry(lhs, symtabEntry, fieldName, loc))
4004 if (parseOptionalExpPostscript(lhs,
false) ||
4005 parseOptionalInfo())
4008 locationProcessor.setLoc(startTok.getLoc());
4009 emitInvalidate(lhs);
4013 ParseResult FIRStmtParser::parseLayerBlockOrGroup(
unsigned indent) {
4015 auto startTok = consumeToken();
4016 assert(startTok.isAny(FIRToken::kw_layerblock, FIRToken::kw_group) &&
4017 "consumed an unexpected token");
4018 auto loc = startTok.getLoc();
4021 if (parseId(
id,
"expected layer identifer") ||
4022 parseToken(FIRToken::colon,
"expected ':' at end of layer block") ||
4023 parseOptionalInfo())
4026 locationProcessor.setLoc(loc);
4028 StringRef rootLayer;
4029 SmallVector<FlatSymbolRefAttr> nestedLayers;
4033 rootLayer = layerSym.getRootReference();
4034 auto nestedRefs = layerSym.getNestedReferences();
4035 nestedLayers.append(nestedRefs.begin(), nestedRefs.end());
4039 auto layerBlockOp = builder.create<LayerBlockOp>(
4041 layerBlockOp->getRegion(0).push_back(
new Block());
4043 if (getIndentation() > indent)
4044 if (parseSubBlock(layerBlockOp.getRegion().front(), indent,
4045 layerBlockOp.getLayerName()))
4053 ParseResult FIRStmtParser::parseLeadingExpStmt(Value lhs) {
4054 auto loc = getToken().getLoc();
4057 if (consumeIf(FIRToken::kw_is)) {
4058 if (parseToken(FIRToken::kw_invalid,
"expected 'invalid'") ||
4059 parseOptionalInfo())
4062 if (removedFeature({3, 0, 0},
"'is invalid' statements", loc))
4065 locationProcessor.setLoc(loc);
4066 emitInvalidate(lhs);
4070 if (parseToken(FIRToken::less_equal,
"expected '<=' in statement"))
4073 if (removedFeature({3, 0, 0},
"'<=' connections", loc))
4077 if (parseExp(rhs,
"unexpected token in statement") || parseOptionalInfo())
4080 locationProcessor.setLoc(loc);
4082 auto lhsType = type_dyn_cast<FIRRTLBaseType>(lhs.getType());
4083 auto rhsType = type_dyn_cast<FIRRTLBaseType>(rhs.getType());
4084 if (!lhsType || !rhsType)
4085 return emitError(loc,
"cannot connect reference or property types");
4087 if (lhsType.containsReference() || rhsType.containsReference())
4088 return emitError(loc,
"cannot connect types containing references");
4091 return emitError(loc,
"cannot connect non-equivalent type ")
4092 << rhsType <<
" to " << lhsType;
4101 ParseResult FIRStmtParser::parseInstance() {
4102 auto startTok = consumeToken(FIRToken::kw_inst);
4106 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4110 StringRef moduleName;
4111 if (parseId(
id,
"expected instance name") ||
4112 parseToken(FIRToken::kw_of,
"expected 'of' in instance") ||
4113 parseId(moduleName,
"expected module name") || parseOptionalInfo())
4116 locationProcessor.setLoc(startTok.getLoc());
4119 auto referencedModule = getReferencedModule(startTok.getLoc(), moduleName);
4120 if (!referencedModule)
4123 SmallVector<PortInfo> modulePorts = referencedModule.getPorts();
4125 auto annotations = getConstants().emptyArrayAttr;
4126 SmallVector<Attribute, 4> portAnnotations(modulePorts.size(), annotations);
4128 hw::InnerSymAttr sym = {};
4129 auto result = builder.create<InstanceOp>(
4130 referencedModule, id, NameKindEnum::InterestingName,
4131 annotations.getValue(), portAnnotations,
false, sym);
4137 unbundledValueEntry.reserve(modulePorts.size());
4138 for (
size_t i = 0, e = modulePorts.size(); i != e; ++i)
4139 unbundledValueEntry.push_back({modulePorts[i].name, result.getResult(i)});
4143 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4144 auto entryId =
UnbundledID(moduleContext.unbundledValues.size());
4145 return moduleContext.addSymbolEntry(
id, entryId, startTok.getLoc());
4150 ParseResult FIRStmtParser::parseInstanceChoice() {
4151 auto startTok = consumeToken(FIRToken::kw_instchoice);
4152 SMLoc loc = startTok.getLoc();
4155 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4162 StringRef defaultModuleName;
4163 StringRef optionGroupName;
4164 if (parseId(
id,
"expected instance name") ||
4165 parseToken(FIRToken::kw_of,
"expected 'of' in instance") ||
4166 parseId(defaultModuleName,
"expected module name") ||
4167 parseToken(FIRToken::comma,
"expected ','") ||
4168 parseId(optionGroupName,
"expected option group name") ||
4169 parseToken(FIRToken::colon,
"expected ':' after instchoice") ||
4170 parseOptionalInfo())
4173 locationProcessor.setLoc(startTok.getLoc());
4177 auto defaultModule = getReferencedModule(loc, defaultModuleName);
4181 SmallVector<PortInfo> modulePorts = defaultModule.getPorts();
4184 auto optionGroup = circuitSymTbl.lookup<OptionOp>(optionGroupName);
4186 return emitError(loc,
4187 "use of undefined option group '" + optionGroupName +
"'");
4189 auto baseIndent = getIndentation();
4190 SmallVector<std::pair<OptionCaseOp, FModuleLike>> caseModules;
4191 while (getIndentation() == baseIndent) {
4193 StringRef caseModuleName;
4194 if (parseId(caseId,
"expected a case identifier") ||
4195 parseToken(FIRToken::equal_greater,
4196 "expected '=> in instance choice definition") ||
4197 parseId(caseModuleName,
"expected module name"))
4200 auto caseModule = getReferencedModule(loc, caseModuleName);
4204 for (
const auto &[defaultPort, casePort] :
4205 llvm::zip(modulePorts, caseModule.getPorts())) {
4206 if (defaultPort.name != casePort.name)
4207 return emitError(loc,
"instance case module port '")
4208 << casePort.name.getValue()
4209 <<
"' does not match the default module port '"
4210 << defaultPort.name.getValue() <<
"'";
4211 if (defaultPort.type != casePort.type)
4212 return emitError(loc,
"instance case port '")
4213 << casePort.name.getValue()
4214 <<
"' type does not match the default module port";
4218 dyn_cast_or_null<OptionCaseOp>(optionGroup.lookupSymbol(caseId));
4220 return emitError(loc,
"use of undefined option case '" + caseId +
"'");
4221 caseModules.emplace_back(optionCase, caseModule);
4224 auto annotations = getConstants().emptyArrayAttr;
4225 SmallVector<Attribute, 4> portAnnotations(modulePorts.size(), annotations);
4229 auto result = builder.create<InstanceChoiceOp>(
4230 defaultModule, caseModules, id, NameKindEnum::InterestingName,
4231 annotations.getValue(), portAnnotations, sym);
4235 unbundledValueEntry.reserve(modulePorts.size());
4236 for (
size_t i = 0, e = modulePorts.size(); i != e; ++i)
4237 unbundledValueEntry.push_back({modulePorts[i].name, result.getResult(i)});
4239 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4240 auto entryId =
UnbundledID(moduleContext.unbundledValues.size());
4241 return moduleContext.addSymbolEntry(
id, entryId, startTok.getLoc());
4244 FModuleLike FIRStmtParser::getReferencedModule(SMLoc loc,
4245 StringRef moduleName) {
4246 auto referencedModule = circuitSymTbl.lookup<FModuleLike>(moduleName);
4247 if (!referencedModule) {
4249 "use of undefined module name '" + moduleName +
"' in instance");
4252 if (isa<ClassOp /* ClassLike */>(referencedModule)) {
4253 emitError(loc,
"cannot create instance of class '" + moduleName +
4254 "', did you mean object?");
4257 return referencedModule;
4261 ParseResult FIRStmtParser::parseObject() {
4262 auto startTok = consumeToken(FIRToken::kw_object);
4266 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4273 StringRef className;
4274 if (parseId(
id,
"expected object name") ||
4275 parseToken(FIRToken::kw_of,
"expected 'of' in object") ||
4276 parseId(className,
"expected class name") || parseOptionalInfo())
4279 locationProcessor.setLoc(startTok.getLoc());
4282 const auto &classMap = getConstants().classMap;
4283 auto lookup = classMap.find(className);
4284 if (lookup == classMap.end())
4285 return emitError(startTok.getLoc(),
"use of undefined class name '" +
4286 className +
"' in object");
4287 auto referencedClass = lookup->getSecond();
4288 auto result = builder.create<ObjectOp>(referencedClass, id);
4289 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4293 ParseResult FIRStmtParser::parseCombMem() {
4295 auto startTok = consumeToken(FIRToken::kw_cmem);
4299 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4304 if (parseId(
id,
"expected cmem name") ||
4305 parseToken(FIRToken::colon,
"expected ':' in cmem") ||
4306 parseType(type,
"expected cmem type") || parseOptionalInfo())
4309 locationProcessor.setLoc(startTok.getLoc());
4312 auto vectorType = type_dyn_cast<FVectorType>(type);
4314 return emitError(
"cmem requires vector type");
4316 auto annotations = getConstants().emptyArrayAttr;
4317 StringAttr sym = {};
4318 auto result = builder.create<CombMemOp>(
4319 vectorType.getElementType(), vectorType.getNumElements(), id,
4320 NameKindEnum::InterestingName, annotations, sym);
4321 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4325 ParseResult FIRStmtParser::parseSeqMem() {
4327 auto startTok = consumeToken(FIRToken::kw_smem);
4331 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4336 RUWAttr ruw = RUWAttr::Undefined;
4338 if (parseId(
id,
"expected smem name") ||
4339 parseToken(FIRToken::colon,
"expected ':' in smem") ||
4343 if (consumeIf(FIRToken::comma)) {
4348 if (parseOptionalInfo()) {
4352 locationProcessor.setLoc(startTok.getLoc());
4355 auto vectorType = type_dyn_cast<FVectorType>(type);
4357 return emitError(
"smem requires vector type");
4359 auto annotations = getConstants().emptyArrayAttr;
4360 StringAttr sym = {};
4361 auto result = builder.create<SeqMemOp>(
4362 vectorType.getElementType(), vectorType.getNumElements(), ruw, id,
4363 NameKindEnum::InterestingName, annotations, sym);
4364 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4376 ParseResult FIRStmtParser::parseMem(
unsigned memIndent) {
4377 auto startTok = consumeToken(FIRToken::kw_mem);
4381 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4385 if (parseId(
id,
"expected mem name") ||
4386 parseToken(FIRToken::colon,
"expected ':' in mem") || parseOptionalInfo())
4390 int64_t depth = -1, readLatency = -1, writeLatency = -1;
4391 RUWAttr ruw = RUWAttr::Undefined;
4393 SmallVector<std::pair<StringAttr, Type>, 4> ports;
4397 auto nextIndent = getIndentation();
4398 if (!nextIndent || *nextIndent <= memIndent)
4401 auto spelling = getTokenSpelling();
4402 if (parseToken(FIRToken::identifier,
"unexpected token in 'mem'") ||
4403 parseToken(FIRToken::equal_greater,
"expected '=>' in 'mem'"))
4406 if (spelling ==
"data-type") {
4408 return emitError(
"'mem' type specified multiple times"), failure();
4410 if (
parseType(type,
"expected type in data-type declaration"))
4414 if (spelling ==
"depth") {
4415 if (parseIntLit(depth,
"expected integer in depth specification"))
4419 if (spelling ==
"read-latency") {
4420 if (parseIntLit(readLatency,
"expected integer latency"))
4424 if (spelling ==
"write-latency") {
4425 if (parseIntLit(writeLatency,
"expected integer latency"))
4429 if (spelling ==
"read-under-write") {
4430 if (getToken().isNot(FIRToken::kw_old, FIRToken::kw_new,
4431 FIRToken::kw_undefined))
4432 return emitError(
"expected specifier"), failure();
4434 if (parseOptionalRUW(ruw))
4439 MemOp::PortKind portKind;
4440 if (spelling ==
"reader")
4441 portKind = MemOp::PortKind::Read;
4442 else if (spelling ==
"writer")
4443 portKind = MemOp::PortKind::Write;
4444 else if (spelling ==
"readwriter")
4445 portKind = MemOp::PortKind::ReadWrite;
4447 return emitError(
"unexpected field in 'mem' declaration"), failure();
4450 if (parseId(portName,
"expected port name"))
4452 auto baseType = type_dyn_cast<FIRRTLBaseType>(type);
4454 return emitError(
"unexpected type, must be base type");
4455 ports.push_back({builder.getStringAttr(portName),
4456 MemOp::getTypeForPort(depth, baseType, portKind)});
4458 while (!getIndentation().has_value()) {
4459 if (parseId(portName,
"expected port name"))
4461 ports.push_back({builder.getStringAttr(portName),
4462 MemOp::getTypeForPort(depth, baseType, portKind)});
4473 llvm::array_pod_sort(ports.begin(), ports.end(),
4474 [](
const std::pair<StringAttr, Type> *lhs,
4475 const std::pair<StringAttr, Type> *rhs) ->
int {
4476 return lhs->first.getValue().compare(
4477 rhs->first.getValue());
4480 auto annotations = getConstants().emptyArrayAttr;
4481 SmallVector<Attribute, 4> resultNames;
4482 SmallVector<Type, 4> resultTypes;
4483 SmallVector<Attribute, 4> resultAnnotations;
4484 for (
auto p : ports) {
4485 resultNames.push_back(p.first);
4486 resultTypes.push_back(p.second);
4487 resultAnnotations.push_back(annotations);
4490 locationProcessor.setLoc(startTok.getLoc());
4492 auto result = builder.create<MemOp>(
4493 resultTypes, readLatency, writeLatency, depth, ruw,
4494 builder.getArrayAttr(resultNames), id, NameKindEnum::InterestingName,
4495 annotations, builder.getArrayAttr(resultAnnotations), hw::InnerSymAttr(),
4496 MemoryInitAttr(), StringAttr());
4499 unbundledValueEntry.reserve(result.getNumResults());
4500 for (
size_t i = 0, e = result.getNumResults(); i != e; ++i)
4501 unbundledValueEntry.push_back({resultNames[i], result.getResult(i)});
4503 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4504 auto entryID =
UnbundledID(moduleContext.unbundledValues.size());
4505 return moduleContext.addSymbolEntry(
id, entryID, startTok.getLoc());
4509 ParseResult FIRStmtParser::parseNode() {
4510 auto startTok = consumeToken(FIRToken::kw_node);
4514 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4519 if (parseId(
id,
"expected node name") ||
4520 parseToken(FIRToken::equal,
"expected '=' in node") ||
4521 parseExp(initializer,
"expected expression for node") ||
4522 parseOptionalInfo())
4525 locationProcessor.setLoc(startTok.getLoc());
4537 auto initializerType = type_cast<FIRRTLType>(initializer.getType());
4538 auto initializerBaseType =
4539 type_dyn_cast<FIRRTLBaseType>(initializer.getType());
4540 if (type_isa<AnalogType>(initializerType) ||
4541 !(initializerBaseType && initializerBaseType.isPassive())) {
4542 emitError(startTok.getLoc())
4543 <<
"Node cannot be analog and must be passive or passive under a flip "
4544 << initializer.getType();
4548 auto annotations = getConstants().emptyArrayAttr;
4549 StringAttr sym = {};
4551 auto result = builder.create<NodeOp>(
4552 initializer, id, NameKindEnum::InterestingName, annotations, sym);
4553 return moduleContext.addSymbolEntry(
id, result.getResult(),
4558 ParseResult FIRStmtParser::parseWire() {
4559 auto startTok = consumeToken(FIRToken::kw_wire);
4563 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4568 if (parseId(
id,
"expected wire name") ||
4569 parseToken(FIRToken::colon,
"expected ':' in wire") ||
4570 parseType(type,
"expected wire type") || parseOptionalInfo())
4573 locationProcessor.setLoc(startTok.getLoc());
4575 auto annotations = getConstants().emptyArrayAttr;
4576 StringAttr sym = {};
4579 auto namekind = isa<PropertyType, RefType>(type)
4580 ? NameKindEnum::DroppableName
4581 : NameKindEnum::InterestingName;
4583 auto result = builder.create<WireOp>(type, id, namekind, annotations, sym);
4584 return moduleContext.addSymbolEntry(
id, result.getResult(),
4598 ParseResult FIRStmtParser::parseRegister(
unsigned regIndent) {
4599 auto startTok = consumeToken(FIRToken::kw_reg);
4603 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4612 if (parseId(
id,
"expected reg name") ||
4613 parseToken(FIRToken::colon,
"expected ':' in reg") ||
4615 parseToken(FIRToken::comma,
"expected ','") ||
4616 parseExp(clock,
"expected expression for register clock"))
4619 if (!type_isa<FIRRTLBaseType>(type))
4620 return emitError(startTok.getLoc(),
"register must have base type");
4623 Value resetSignal, resetValue;
4624 if (consumeIf(FIRToken::kw_with)) {
4625 if (removedFeature({3, 0, 0},
"'reg with' registers"))
4628 if (parseToken(FIRToken::colon,
"expected ':' in reg"))
4636 bool hasExtraLParen = consumeIf(FIRToken::l_paren);
4638 auto indent = getIndentation();
4639 if (!indent || *indent <= regIndent)
4640 if (!hasExtraLParen)
4641 return emitError(
"expected indented reset specifier in reg"), failure();
4643 if (parseToken(FIRToken::kw_reset,
"expected 'reset' in reg") ||
4644 parseToken(FIRToken::equal_greater,
"expected => in reset specifier") ||
4645 parseToken(FIRToken::l_paren,
"expected '(' in reset specifier") ||
4646 parseExp(resetSignal,
"expected expression for reset signal") ||
4647 parseToken(FIRToken::comma,
"expected ','"))
4655 if (getTokenSpelling() ==
id) {
4657 if (parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4659 resetSignal = Value();
4661 if (parseExp(resetValue,
"expected expression for reset value") ||
4662 parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4666 if (hasExtraLParen &&
4667 parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4673 if (parseOptionalInfo())
4676 locationProcessor.setLoc(startTok.getLoc());
4678 ArrayAttr annotations = getConstants().emptyArrayAttr;
4680 StringAttr sym = {};
4684 .create<RegResetOp>(type, clock, resetSignal, resetValue, id,
4685 NameKindEnum::InterestingName, annotations, sym)
4689 .create<RegOp>(type, clock, id, NameKindEnum::InterestingName,
4692 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4700 ParseResult FIRStmtParser::parseRegisterWithReset() {
4701 auto startTok = consumeToken(FIRToken::kw_regreset);
4705 Value clock, resetSignal, resetValue;
4707 if (parseId(
id,
"expected reg name") ||
4708 parseToken(FIRToken::colon,
"expected ':' in reg") ||
4710 parseToken(FIRToken::comma,
"expected ','") ||
4711 parseExp(clock,
"expected expression for register clock") ||
4712 parseToken(FIRToken::comma,
"expected ','") ||
4713 parseExp(resetSignal,
"expected expression for register reset") ||
4714 parseToken(FIRToken::comma,
"expected ','") ||
4715 parseExp(resetValue,
"expected expression for register reset value") ||
4716 parseOptionalInfo())
4719 if (!type_isa<FIRRTLBaseType>(type))
4720 return emitError(startTok.getLoc(),
"register must have base type");
4722 locationProcessor.setLoc(startTok.getLoc());
4726 .create<RegResetOp>(type, clock, resetSignal, resetValue, id,
4727 NameKindEnum::InterestingName,
4728 getConstants().emptyArrayAttr, StringAttr{})
4731 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4741 struct FIRCircuitParser :
public FIRParser {
4742 explicit FIRCircuitParser(SharedParserConstants &state,
FIRLexer &lexer,
4744 : FIRParser(state, lexer, version), mlirModule(mlirModule) {}
4747 parseCircuit(SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBuf,
4748 mlir::TimingScope &ts);
4753 ParseResult importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
4754 SmallVectorImpl<Attribute> &attrs);
4756 ParseResult parseToplevelDefinition(CircuitOp circuit,
unsigned indent);
4758 ParseResult parseClass(CircuitOp circuit,
unsigned indent);
4759 ParseResult parseExtClass(CircuitOp circuit,
unsigned indent);
4760 ParseResult parseExtModule(CircuitOp circuit,
unsigned indent);
4761 ParseResult parseIntModule(CircuitOp circuit,
unsigned indent);
4762 ParseResult parseModule(CircuitOp circuit,
bool isPublic,
unsigned indent);
4763 ParseResult parseFormal(CircuitOp circuit,
unsigned indent);
4765 ParseResult parseLayerName(SymbolRefAttr &result);
4766 ParseResult parseOptionalEnabledLayers(ArrayAttr &result);
4767 ParseResult
parsePortList(SmallVectorImpl<PortInfo> &resultPorts,
4768 SmallVectorImpl<SMLoc> &resultPortLocs,
4771 ParseResult parseRefList(ArrayRef<PortInfo> portList,
4772 ArrayAttr &internalPathsResult);
4774 ParseResult skipToModuleEnd(
unsigned indent);
4776 ParseResult parseTypeDecl();
4778 ParseResult parseOptionDecl(CircuitOp circuit);
4780 ParseResult parseLayer(CircuitOp circuit);
4782 struct DeferredModuleToParse {
4783 FModuleLike moduleOp;
4784 SmallVector<SMLoc> portLocs;
4789 ParseResult parseModuleBody(
const SymbolTable &circuitSymTbl,
4790 DeferredModuleToParse &deferredModule,
4791 InnerSymFixups &fixups);
4793 SmallVector<DeferredModuleToParse, 0> deferredModules;
4795 SmallVector<InnerSymFixups, 0> moduleFixups;
4797 hw::InnerSymbolNamespaceCollection innerSymbolNamespaces;
4799 ModuleOp mlirModule;
4804 FIRCircuitParser::importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
4805 SmallVectorImpl<Attribute> &attrs) {
4807 auto annotations = json::parse(annotationsStr);
4808 if (
auto err = annotations.takeError()) {
4809 handleAllErrors(std::move(err), [&](
const json::ParseError &a) {
4810 auto diag = emitError(loc,
"Failed to parse JSON Annotations");
4811 diag.attachNote() << a.message();
4816 json::Path::Root root;
4817 llvm::StringMap<ArrayAttr> thisAnnotationMap;
4820 auto diag = emitError(loc,
"Invalid/unsupported annotation format");
4821 std::string jsonErrorMessage =
4822 "See inline comments for problem area in JSON:\n";
4823 llvm::raw_string_ostream s(jsonErrorMessage);
4824 root.printErrorContext(annotations.get(), s);
4825 diag.attachNote() << jsonErrorMessage;
4832 ParseResult FIRCircuitParser::parseLayerName(SymbolRefAttr &result) {
4833 auto *context = getContext();
4834 SmallVector<StringRef> strings;
4837 if (parseId(name,
"expected layer name"))
4839 strings.push_back(name);
4840 }
while (consumeIf(FIRToken::period));
4842 SmallVector<FlatSymbolRefAttr> nested;
4843 nested.reserve(strings.size() - 1);
4844 for (
unsigned i = 1, e = strings.size(); i < e; ++i)
4851 ParseResult FIRCircuitParser::parseOptionalEnabledLayers(ArrayAttr &result) {
4852 if (getToken().getKind() != FIRToken::kw_enablelayer) {
4857 if (requireFeature({4, 0, 0},
"modules with layers enabled"))
4860 SmallVector<Attribute> layers;
4862 SymbolRefAttr layer;
4864 if (parseLayerName(layer))
4866 layers.push_back(layer);
4867 }
while (getToken().getKind() == FIRToken::kw_enablelayer);
4878 SmallVectorImpl<SMLoc> &resultPortLocs,
4881 while (getToken().isAny(FIRToken::kw_input, FIRToken::kw_output) &&
4883 getIndentation() > indent) {
4889 auto backtrackState = getLexer().getCursor();
4891 bool isOutput = getToken().is(FIRToken::kw_output);
4896 if (!getToken().isAny(FIRToken::identifier, FIRToken::literal_identifier) &&
4897 !getToken().isKeyword()) {
4898 backtrackState.restore(getLexer());
4904 LocWithInfo info(getToken().getLoc(),
this);
4905 if (parseId(name,
"expected port name") ||
4906 parseToken(FIRToken::colon,
"expected ':' in port definition") ||
4907 parseType(type,
"expected a type in port declaration") ||
4908 info.parseOptionalInfo())
4911 StringAttr innerSym = {};
4912 resultPorts.push_back(
4913 {name, type,
direction::get(isOutput), innerSym, info.getLoc()});
4914 resultPortLocs.push_back(info.getFIRLoc());
4919 for (
auto portAndLoc : llvm::zip(resultPorts, resultPortLocs)) {
4920 PortInfo &port = std::get<0>(portAndLoc);
4921 auto &entry = portIds[port.
name];
4922 if (!entry.isValid()) {
4923 entry = std::get<1>(portAndLoc);
4927 emitError(std::get<1>(portAndLoc),
4928 "redefinition of name '" + port.
getName() +
"'")
4929 .attachNote(translateLocation(entry))
4930 <<
"previous definition here";
4939 ParseResult FIRCircuitParser::parseRefList(ArrayRef<PortInfo> portList,
4940 ArrayAttr &internalPathsResult) {
4941 struct RefStatementInfo {
4943 InternalPathAttr resolvedPath;
4947 SmallVector<RefStatementInfo> refStatements;
4948 SmallPtrSet<StringAttr, 8> seenNames;
4949 SmallPtrSet<StringAttr, 8> seenRefs;
4952 if (getToken().is(FIRToken::kw_ref) &&
4953 (requireFeature({2, 0, 0},
"ref statements") ||
4954 removedFeature({4, 0, 0},
"ref statements")))
4958 while (consumeIf(FIRToken::kw_ref)) {
4959 auto loc = getToken().getLoc();
4963 if (parseId(refName,
"expected ref name"))
4965 if (consumeIf(FIRToken::period) || consumeIf(FIRToken::l_square))
4967 loc,
"ref statements for aggregate elements not yet supported");
4968 if (parseToken(FIRToken::kw_is,
"expected 'is' in ref statement"))
4971 if (!seenRefs.insert(refName).second)
4972 return emitError(loc,
"duplicate ref statement for '" + refName.strref() +
4975 auto kind = getToken().getKind();
4976 if (kind != FIRToken::string)
4977 return emitError(loc,
"expected string in ref statement");
4981 consumeToken(FIRToken::string);
4983 refStatements.push_back(RefStatementInfo{refName, resolved, loc});
4987 SmallVector<Attribute> internalPaths(portList.size(),
4990 llvm::SmallBitVector usedRefs(refStatements.size());
4991 size_t matchedPaths = 0;
4992 for (
auto [idx, port] : llvm::enumerate(portList)) {
4993 if (!type_isa<RefType>(port.
type))
4999 return mlir::emitError(
5001 "references in ports must be output on extmodule and intmodule");
5003 llvm::find_if(refStatements, [pname = port.
name](
const auto &r) {
5004 return r.refName == pname;
5007 if (refStmtIt == refStatements.end()) {
5008 if (!refStatements.empty())
5009 return mlir::emitError(port.
loc,
"no ref statement found for ref port ")
5014 usedRefs.set(std::distance(refStatements.begin(), refStmtIt));
5015 internalPaths[idx] = refStmtIt->resolvedPath;
5019 if (!refStatements.empty() && matchedPaths != refStatements.size()) {
5020 assert(matchedPaths < refStatements.size());
5022 auto idx = usedRefs.find_first_unset();
5024 return emitError(refStatements[idx].loc,
"unused ref statement");
5028 internalPathsResult =
ArrayAttr::get(getContext(), internalPaths);
5034 ParseResult FIRCircuitParser::skipToModuleEnd(
unsigned indent) {
5036 switch (getToken().getKind()) {
5040 case FIRToken::error:
5044 case FIRToken::kw_class:
5045 case FIRToken::kw_declgroup:
5046 case FIRToken::kw_extclass:
5047 case FIRToken::kw_extmodule:
5048 case FIRToken::kw_intmodule:
5049 case FIRToken::kw_formal:
5050 case FIRToken::kw_module:
5051 case FIRToken::kw_public:
5052 case FIRToken::kw_layer:
5053 case FIRToken::kw_option:
5054 case FIRToken::kw_type:
5058 if (getIndentation() == indent)
5071 SmallVector<Attribute, 8> parameters;
5072 SmallPtrSet<StringAttr, 8> seen;
5073 while (consumeIf(FIRToken::kw_parameter)) {
5077 if (parseParameter(name, value, loc))
5079 auto typedValue = dyn_cast<TypedAttr>(value);
5081 return emitError(loc)
5082 <<
"invalid value for parameter '" << name.getValue() <<
"'";
5083 if (!seen.insert(name).second)
5084 return emitError(loc,
5085 "redefinition of parameter '" + name.getValue() +
"'");
5093 ParseResult FIRCircuitParser::parseClass(CircuitOp circuit,
unsigned indent) {
5095 SmallVector<PortInfo, 8> portList;
5096 SmallVector<SMLoc> portLocs;
5097 LocWithInfo info(getToken().getLoc(),
this);
5102 consumeToken(FIRToken::kw_class);
5103 if (parseId(name,
"expected class name") ||
5104 parseToken(FIRToken::colon,
"expected ':' in class definition") ||
5105 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5108 if (name == circuit.getName())
5109 return mlir::emitError(info.getLoc(),
5110 "class cannot be the top of a circuit");
5112 for (
auto &portInfo : portList)
5113 if (!isa<PropertyType>(portInfo.type))
5114 return mlir::emitError(portInfo.loc,
5115 "ports on classes must be properties");
5118 auto builder = circuit.getBodyBuilder();
5119 auto classOp = builder.create<ClassOp>(info.getLoc(), name, portList);
5120 classOp.setPrivate();
5121 deferredModules.emplace_back(
5122 DeferredModuleToParse{classOp, portLocs, getLexer().getCursor(), indent});
5125 getConstants().classMap[name.getValue()] = classOp;
5126 return skipToModuleEnd(indent);
5130 ParseResult FIRCircuitParser::parseExtClass(CircuitOp circuit,
5133 SmallVector<PortInfo, 8> portList;
5134 SmallVector<SMLoc> portLocs;
5135 LocWithInfo info(getToken().getLoc(),
this);
5140 consumeToken(FIRToken::kw_extclass);
5141 if (parseId(name,
"expected extclass name") ||
5142 parseToken(FIRToken::colon,
"expected ':' in extclass definition") ||
5143 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5146 if (name == circuit.getName())
5147 return mlir::emitError(info.getLoc(),
5148 "extclass cannot be the top of a circuit");
5150 for (
auto &portInfo : portList)
5151 if (!isa<PropertyType>(portInfo.type))
5152 return mlir::emitError(portInfo.loc,
5153 "ports on extclasses must be properties");
5156 auto builder = circuit.getBodyBuilder();
5157 auto extClassOp = builder.create<ExtClassOp>(info.getLoc(), name, portList);
5160 getConstants().classMap[name.getValue()] = extClassOp;
5161 return skipToModuleEnd(indent);
5168 ParseResult FIRCircuitParser::parseExtModule(CircuitOp circuit,
5172 SmallVector<PortInfo, 8> portList;
5173 SmallVector<SMLoc> portLocs;
5174 LocWithInfo info(getToken().getLoc(),
this);
5175 consumeToken(FIRToken::kw_extmodule);
5176 if (parseId(name,
"expected extmodule name") ||
5177 parseOptionalEnabledLayers(layers) ||
5178 parseToken(FIRToken::colon,
"expected ':' in extmodule definition") ||
5179 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5183 if (consumeIf(FIRToken::kw_defname)) {
5184 if (parseToken(FIRToken::equal,
"expected '=' in defname") ||
5185 parseId(defName,
"expected defname name"))
5189 ArrayAttr parameters;
5190 ArrayAttr internalPaths;
5195 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
5196 if (
auto ftype = type_dyn_cast<FIRRTLType>(pi.type)) {
5197 if (ftype.hasUninferredWidth())
5198 return emitError(loc,
"extmodule port must have known width");
5203 auto builder = circuit.getBodyBuilder();
5204 auto isMainModule = (name == circuit.getName());
5206 (isMainModule && getConstants().options.scalarizePublicModules) ||
5207 getConstants().options.scalarizeExtModules
5208 ? Convention::Scalarized
5209 : Convention::Internal;
5212 auto extModuleOp = builder.create<FExtModuleOp>(
5213 info.getLoc(), name, conventionAttr, portList, defName, annotations,
5214 parameters, internalPaths, layers);
5215 auto visibility = isMainModule ? SymbolTable::Visibility::Public
5216 : SymbolTable::Visibility::Private;
5217 SymbolTable::setSymbolVisibility(extModuleOp, visibility);
5225 ParseResult FIRCircuitParser::parseIntModule(CircuitOp circuit,
5230 SmallVector<PortInfo, 8> portList;
5231 SmallVector<SMLoc> portLocs;
5232 LocWithInfo info(getToken().getLoc(),
this);
5233 consumeToken(FIRToken::kw_intmodule);
5234 if (parseId(name,
"expected intmodule name") ||
5235 parseOptionalEnabledLayers(layers) ||
5236 parseToken(FIRToken::colon,
"expected ':' in intmodule definition") ||
5237 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent) ||
5238 parseToken(FIRToken::kw_intrinsic,
"expected 'intrinsic'") ||
5239 parseToken(FIRToken::equal,
"expected '=' in intrinsic") ||
5240 parseId(intName,
"expected intrinsic name"))
5243 ArrayAttr parameters;
5244 ArrayAttr internalPaths;
5248 ArrayAttr annotations = getConstants().emptyArrayAttr;
5249 auto builder = circuit.getBodyBuilder();
5251 .create<FIntModuleOp>(info.getLoc(), name, portList, intName, annotations,
5252 parameters, internalPaths, layers)
5258 ParseResult FIRCircuitParser::parseModule(CircuitOp circuit,
bool isPublic,
5261 SmallVector<PortInfo, 8> portList;
5262 SmallVector<SMLoc> portLocs;
5264 auto modLoc = getToken().getLoc();
5265 LocWithInfo info(modLoc,
this);
5266 consumeToken(FIRToken::kw_module);
5267 if (parseId(name,
"expected module name") ||
5268 parseOptionalEnabledLayers(layers) ||
5269 parseToken(FIRToken::colon,
"expected ':' in module definition") ||
5270 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5274 if (name == circuit.getName()) {
5275 if (!isPublic && removedFeature({4, 0, 0},
"private main modules", modLoc))
5280 if (isPublic && version >=
FIRVersion({4, 0, 0})) {
5281 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
5282 if (
auto ftype = type_dyn_cast<FIRRTLType>(pi.type)) {
5283 if (ftype.hasUninferredWidth())
5284 return emitError(loc,
"public module port must have known width");
5285 if (ftype.hasUninferredReset())
5286 return emitError(loc,
5287 "public module port must have concrete reset type");
5292 ArrayAttr annotations = getConstants().emptyArrayAttr;
5293 auto convention = Convention::Internal;
5294 if (isPublic && getConstants().options.scalarizePublicModules)
5295 convention = Convention::Scalarized;
5296 if (!isPublic && getConstants().options.scalarizeInternalModules)
5297 convention = Convention::Scalarized;
5299 auto builder = circuit.getBodyBuilder();
5300 auto moduleOp = builder.create<FModuleOp>(info.getLoc(), name, conventionAttr,
5301 portList, annotations, layers);
5303 auto visibility = isPublic ? SymbolTable::Visibility::Public
5304 : SymbolTable::Visibility::Private;
5305 SymbolTable::setSymbolVisibility(moduleOp, visibility);
5309 deferredModules.emplace_back(DeferredModuleToParse{
5310 moduleOp, portLocs, getLexer().getCursor(), indent});
5312 if (skipToModuleEnd(indent))
5319 ParseResult FIRCircuitParser::parseFormal(CircuitOp circuit,
unsigned indent) {
5320 consumeToken(FIRToken::kw_formal);
5321 StringRef id, moduleName;
5323 LocWithInfo info(getToken().getLoc(),
this);
5324 auto builder = circuit.getBodyBuilder();
5328 if (parseId(
id,
"expected formal test name") ||
5329 parseToken(FIRToken::kw_of,
"expected 'of' in formal test") ||
5330 parseId(moduleName,
"expected module name"))
5334 NamedAttrList params;
5335 if (consumeIf(FIRToken::comma)) {
5337 if (getToken().isNot(FIRToken::identifier) || getTokenSpelling() !=
"bound")
5338 return emitError(
"expected 'bound' after ','");
5340 if (parseToken(FIRToken::equal,
"expected '=' after 'bound'") ||
5341 parseIntLit(bound,
"expected integer bound after '='"))
5344 return emitError(
"bound must be a positive integer");
5345 if (info.parseOptionalInfo())
5347 params.set(
"bound", builder.getIntegerAttr(builder.getI32Type(), bound));
5350 if (parseToken(FIRToken::colon,
"expected ':' in formal test") ||
5351 info.parseOptionalInfo())
5353 while (getIndentation() > indent) {
5354 StringAttr paramName;
5355 Attribute paramValue;
5357 if (parseParameter(paramName, paramValue, paramLoc,
5360 if (params.set(paramName, paramValue))
5361 return emitError(paramLoc,
"redefinition of parameter '" +
5362 paramName.getValue() +
"'");
5366 builder.create<firrtl::FormalOp>(info.getLoc(), id, moduleName,
5367 params.getDictionary(getContext()));
5371 ParseResult FIRCircuitParser::parseToplevelDefinition(CircuitOp circuit,
5373 switch (getToken().getKind()) {
5374 case FIRToken::kw_class:
5375 return parseClass(circuit, indent);
5376 case FIRToken::kw_declgroup:
5377 if (requireFeature({3, 2, 0},
"optional groups") ||
5378 removedFeature({3, 3, 0},
"optional groups"))
5380 return parseLayer(circuit);
5381 case FIRToken::kw_extclass:
5382 return parseExtClass(circuit, indent);
5383 case FIRToken::kw_extmodule:
5384 return parseExtModule(circuit, indent);
5385 case FIRToken::kw_formal:
5386 if (requireFeature({4, 0, 0},
"inline formal tests"))
5388 return parseFormal(circuit, indent);
5389 case FIRToken::kw_intmodule:
5390 if (requireFeature({1, 2, 0},
"inline formal tests") ||
5391 removedFeature({4, 0, 0},
"intrinsic modules"))
5393 return parseIntModule(circuit, indent);
5394 case FIRToken::kw_layer:
5395 if (requireFeature({3, 3, 0},
"layers"))
5397 return parseLayer(circuit);
5398 case FIRToken::kw_module:
5399 return parseModule(circuit,
false, indent);
5400 case FIRToken::kw_public:
5401 if (requireFeature({3, 3, 0},
"public modules"))
5404 if (getToken().getKind() == FIRToken::kw_module)
5405 return parseModule(circuit,
true, indent);
5406 return emitError(getToken().getLoc(),
"only modules may be public");
5407 case FIRToken::kw_type:
5408 return parseTypeDecl();
5409 case FIRToken::kw_option:
5412 return parseOptionDecl(circuit);
5414 return emitError(getToken().getLoc(),
"unknown toplevel definition");
5419 ParseResult FIRCircuitParser::parseTypeDecl() {
5423 auto loc = getToken().getLoc();
5425 if (getToken().isKeyword())
5426 return emitError(loc) <<
"cannot use keyword '" << getToken().getSpelling()
5427 <<
"' for type alias name";
5429 if (parseId(
id,
"expected type name") ||
5430 parseToken(FIRToken::equal,
"expected '=' in type decl") ||
5436 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type))
5440 <<
"type alias for non-base type " << type
5441 <<
" is currently not supported. Type alias is stripped immediately";
5443 if (!getConstants().aliasMap.insert({id, type}).second)
5444 return emitError(loc) <<
"type alias `" << name.getValue()
5445 <<
"` is already defined";
5450 ParseResult FIRCircuitParser::parseOptionDecl(CircuitOp circuit) {
5453 auto loc = getToken().getLoc();
5455 LocWithInfo info(getToken().getLoc(),
this);
5456 if (parseId(
id,
"expected an option group name") ||
5457 parseToken(FIRToken::colon,
5458 "expected ':' after option group definition") ||
5459 info.parseOptionalInfo())
5462 auto builder = OpBuilder::atBlockEnd(circuit.getBodyBlock());
5463 auto optionOp = builder.create<OptionOp>(info.getLoc(), id);
5464 auto *block =
new Block;
5465 optionOp.getBody().push_back(block);
5466 builder.setInsertionPointToEnd(block);
5468 auto baseIndent = getIndentation();
5470 while (getIndentation() == baseIndent) {
5472 LocWithInfo caseInfo(getToken().getLoc(),
this);
5473 if (parseId(
id,
"expected an option case ID") ||
5474 caseInfo.parseOptionalInfo())
5477 if (!cases.insert(
id).second)
5478 return emitError(loc)
5479 <<
"duplicate option case definition '" <<
id <<
"'";
5481 builder.create<OptionCaseOp>(caseInfo.getLoc(), id);
5488 ParseResult FIRCircuitParser::parseLayer(CircuitOp circuit) {
5489 auto baseIndent = getIndentation();
5492 SmallVector<std::pair<std::optional<unsigned>, LayerOp>> layerStack;
5495 auto parseOne = [&](
Block *block) -> ParseResult {
5496 auto indent = getIndentation();
5497 StringRef id, convention;
5498 LocWithInfo info(getToken().getLoc(),
this);
5500 if (parseId(
id,
"expected layer name") ||
5501 parseToken(FIRToken::comma,
"expected ','") ||
5502 parseGetSpelling(convention))
5505 auto layerConvention = symbolizeLayerConvention(convention);
5506 if (!layerConvention) {
5507 emitError() <<
"unknown convention '" << convention
5508 <<
"' (did you misspell it?)";
5513 hw::OutputFileAttr outputDir;
5514 if (consumeIf(FIRToken::comma)) {
5515 if (getToken().getKind() == FIRToken::string) {
5516 auto text = getToken().getStringValue();
5518 return emitError() <<
"output directory must not be blank";
5519 outputDir = hw::OutputFileAttr::getAsDirectory(getContext(), text);
5520 consumeToken(FIRToken::string);
5524 if (parseToken(FIRToken::colon,
"expected ':' after layer definition") ||
5525 info.parseOptionalInfo())
5527 auto builder = OpBuilder::atBlockEnd(block);
5529 auto layerOp = builder.create<LayerOp>(info.getLoc(), id, *layerConvention);
5530 layerOp->getRegion(0).push_back(
new Block());
5532 layerOp->setAttr(
"output_file", outputDir);
5533 layerStack.push_back({indent, layerOp});
5537 if (parseOne(circuit.getBodyBlock()))
5541 while (getIndentation() > baseIndent) {
5542 switch (getToken().getKind()) {
5543 case FIRToken::kw_declgroup:
5544 case FIRToken::kw_layer: {
5547 while (layerStack.back().first >= getIndentation())
5548 layerStack.pop_back();
5549 auto parentLayer = layerStack.back().second;
5550 if (parseOne(&parentLayer.getBody().front()))
5555 return emitError(
"expected 'layer'"), failure();
5564 FIRCircuitParser::parseModuleBody(
const SymbolTable &circuitSymTbl,
5565 DeferredModuleToParse &deferredModule,
5566 InnerSymFixups &fixups) {
5567 FModuleLike moduleOp = deferredModule.moduleOp;
5568 auto &body = moduleOp->getRegion(0).front();
5569 auto &portLocs = deferredModule.portLocs;
5573 FIRLexer moduleBodyLexer(getLexer().getSourceMgr(), getContext());
5576 deferredModule.lexerCursor.restore(moduleBodyLexer);
5578 FIRModuleContext moduleContext(getConstants(), moduleBodyLexer, version);
5582 auto portList = moduleOp.getPorts();
5583 auto portArgs = body.getArguments();
5584 for (
auto tuple : llvm::zip(portList, portLocs, portArgs)) {
5585 PortInfo &port = std::get<0>(tuple);
5586 llvm::SMLoc loc = std::get<1>(tuple);
5587 BlockArgument portArg = std::get<2>(tuple);
5589 if (moduleContext.addSymbolEntry(port.
getName(), portArg, loc))
5593 FIRStmtParser stmtParser(body, moduleContext, fixups, circuitSymTbl, version);
5596 auto result = stmtParser.parseSimpleStmtBlock(deferredModule.indent);
5602 size_t numVerifPrintfs = 0;
5603 std::optional<Location> printfLoc;
5605 deferredModule.moduleOp.walk([&](PrintFOp printFOp) {
5610 printfLoc = printFOp.getLoc();
5613 if (numVerifPrintfs > 0) {
5615 mlir::emitError(deferredModule.moduleOp.getLoc(),
"module contains ")
5617 <<
" printf-encoded verification operation(s), which are no longer "
5619 diag.attachNote(*printfLoc)
5620 <<
"example printf here, this is now just a printf and nothing more";
5621 diag.attachNote() <<
"For more information, see "
5622 "https://github.com/llvm/circt/issues/6970";
5636 ParseResult FIRCircuitParser::parseCircuit(
5637 SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBufs,
5638 mlir::TimingScope &ts) {
5640 auto indent = getIndentation();
5641 if (parseToken(FIRToken::kw_FIRRTL,
"expected 'FIRRTL'"))
5643 if (!indent.has_value())
5644 return emitError(
"'FIRRTL' must be first token on its line");
5645 if (parseToken(FIRToken::kw_version,
"expected version after 'FIRRTL'") ||
5646 parseVersionLit(
"expected version literal"))
5648 indent = getIndentation();
5650 if (!indent.has_value())
5651 return emitError(
"'circuit' must be first token on its line");
5652 unsigned circuitIndent = *indent;
5654 LocWithInfo info(getToken().getLoc(),
this);
5656 SMLoc inlineAnnotationsLoc;
5657 StringRef inlineAnnotations;
5660 if (parseToken(FIRToken::kw_circuit,
5661 "expected a top-level 'circuit' definition") ||
5662 parseId(name,
"expected circuit name") ||
5663 parseToken(FIRToken::colon,
"expected ':' in circuit definition") ||
5664 parseOptionalAnnotations(inlineAnnotationsLoc, inlineAnnotations) ||
5665 info.parseOptionalInfo())
5669 OpBuilder b(mlirModule.getBodyRegion());
5670 auto circuit = b.create<CircuitOp>(info.getLoc(), name);
5673 auto parseAnnotationTimer = ts.nest(
"Parse annotations");
5679 SmallVector<Attribute> annos;
5680 if (!inlineAnnotations.empty())
5681 if (importAnnotationsRaw(inlineAnnotationsLoc, inlineAnnotations, annos))
5685 for (
auto *annotationsBuf : annotationsBufs)
5686 if (importAnnotationsRaw(info.getFIRLoc(), annotationsBuf->getBuffer(),
5690 parseAnnotationTimer.stop();
5698 auto parseTimer = ts.nest(
"Parse modules");
5699 deferredModules.reserve(16);
5703 switch (getToken().getKind()) {
5711 case FIRToken::error:
5715 emitError(
"unexpected token in circuit");
5718 case FIRToken::kw_class:
5719 case FIRToken::kw_declgroup:
5720 case FIRToken::kw_extclass:
5721 case FIRToken::kw_extmodule:
5722 case FIRToken::kw_intmodule:
5723 case FIRToken::kw_layer:
5724 case FIRToken::kw_formal:
5725 case FIRToken::kw_module:
5726 case FIRToken::kw_option:
5727 case FIRToken::kw_public:
5728 case FIRToken::kw_type: {
5729 auto indent = getIndentation();
5730 if (!indent.has_value())
5731 return emitError(
"'module' must be first token on its line"), failure();
5732 unsigned definitionIndent = *indent;
5734 if (definitionIndent <= circuitIndent)
5735 return emitError(
"module should be indented more"), failure();
5737 if (parseToplevelDefinition(circuit, definitionIndent))
5751 (void)getLexer().translateLocation(info.getFIRLoc());
5757 DenseMap<Attribute, Location> nameToOrigLoc;
5758 for (
auto &op : *circuit.getBodyBlock()) {
5761 op.getAttrOfType<StringAttr>(mlir::SymbolTable::getSymbolAttrName());
5766 auto it = nameToOrigLoc.try_emplace(nameAttr, op.getLoc());
5769 .append(
"redefinition of symbol named '", nameAttr.getValue(),
"'")
5770 .attachNote(it.first->second)
5771 .append(
"see existing symbol definition here");
5777 SymbolTable circuitSymTbl(circuit);
5779 moduleFixups.resize(deferredModules.size());
5784 for (
auto &d : deferredModules)
5785 innerSymbolNamespaces.get(d.moduleOp.getOperation());
5788 auto anyFailed = mlir::failableParallelForEachN(
5789 getContext(), 0, deferredModules.size(), [&](
size_t index) {
5790 if (parseModuleBody(circuitSymTbl, deferredModules[index],
5791 moduleFixups[index]))
5795 if (failed(anyFailed))
5800 for (
auto &fixups : moduleFixups) {
5801 if (failed(fixups.resolve(innerSymbolNamespaces)))
5807 auto parseLayerName = [&](StringRef name) -> Attribute {
5809 auto [head, rest] = name.split(
".");
5810 SmallVector<FlatSymbolRefAttr> nestedRefs;
5811 while (!rest.empty()) {
5813 std::tie(next, rest) = rest.split(
".");
5819 auto getArrayAttr = [&](ArrayRef<std::string> strArray,
auto getAttr) {
5820 SmallVector<Attribute> attrArray;
5821 auto *context = getContext();
5822 for (
const auto &str : strArray)
5823 attrArray.push_back(getAttr(str));
5824 if (attrArray.empty())
5829 if (
auto enableLayers =
5830 getArrayAttr(getConstants().options.enableLayers, parseLayerName))
5831 circuit.setEnableLayersAttr(enableLayers);
5832 if (
auto disableLayers =
5833 getArrayAttr(getConstants().options.disableLayers, parseLayerName))
5834 circuit.setDisableLayersAttr(disableLayers);
5836 auto getStrAttr = [&](StringRef str) -> Attribute {
5840 if (
auto selectInstChoice =
5841 getArrayAttr(getConstants().options.selectInstanceChoice, getStrAttr))
5842 circuit.setSelectInstChoiceAttr(selectInstChoice);
5844 circuit.setDefaultLayerSpecialization(
5845 getConstants().options.defaultLayerSpecialization);
5858 auto sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
5859 SmallVector<const llvm::MemoryBuffer *> annotationsBufs;
5860 unsigned fileID = 1;
5862 annotationsBufs.push_back(
5863 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID() + fileID));
5865 context->loadDialect<CHIRRTLDialect>();
5866 context->loadDialect<FIRRTLDialect, hw::HWDialect>();
5873 SharedParserConstants state(context, options);
5874 FIRLexer lexer(sourceMgr, context);
5876 .parseCircuit(annotationsBufs, ts))
5881 auto circuitVerificationTimer = ts.nest(
"Verify circuit");
5882 if (failed(
verify(*module)))
5889 static mlir::TranslateToMLIRRegistration fromFIR(
5890 "import-firrtl",
"import .fir",
5891 [](llvm::SourceMgr &sourceMgr, MLIRContext *context) {
5892 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.
constexpr FIRVersion missingSpecFIRVersion
A marker for parser features that are currently missing from the spec.
hw::InnerSymTarget getTargetFor(FieldRef ref)
Return the inner sym target for the specified value and fieldID.
constexpr FIRVersion minimumFIRVersion(2, 0, 0)
The current minimum version of FIRRTL that the parser supports.
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.
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