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"))
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 SmallVectorImpl<const llvm::MemoryBuffer *> &omirBuf,
4749 mlir::TimingScope &ts);
4754 ParseResult importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
4755 SmallVectorImpl<Attribute> &attrs);
4759 ParseResult importOMIR(CircuitOp circuit, SMLoc loc, StringRef annotationStr,
4760 SmallVectorImpl<Attribute> &attrs);
4762 ParseResult parseToplevelDefinition(CircuitOp circuit,
unsigned indent);
4764 ParseResult parseClass(CircuitOp circuit,
unsigned indent);
4765 ParseResult parseExtClass(CircuitOp circuit,
unsigned indent);
4766 ParseResult parseExtModule(CircuitOp circuit,
unsigned indent);
4767 ParseResult parseIntModule(CircuitOp circuit,
unsigned indent);
4768 ParseResult parseModule(CircuitOp circuit,
bool isPublic,
unsigned indent);
4769 ParseResult parseFormal(CircuitOp circuit,
unsigned indent);
4771 ParseResult parseLayerName(SymbolRefAttr &result);
4772 ParseResult parseOptionalEnabledLayers(ArrayAttr &result);
4773 ParseResult
parsePortList(SmallVectorImpl<PortInfo> &resultPorts,
4774 SmallVectorImpl<SMLoc> &resultPortLocs,
4777 ParseResult parseRefList(ArrayRef<PortInfo> portList,
4778 ArrayAttr &internalPathsResult);
4780 ParseResult skipToModuleEnd(
unsigned indent);
4782 ParseResult parseTypeDecl();
4784 ParseResult parseOptionDecl(CircuitOp circuit);
4786 ParseResult parseLayer(CircuitOp circuit);
4788 struct DeferredModuleToParse {
4789 FModuleLike moduleOp;
4790 SmallVector<SMLoc> portLocs;
4795 ParseResult parseModuleBody(
const SymbolTable &circuitSymTbl,
4796 DeferredModuleToParse &deferredModule,
4797 InnerSymFixups &fixups);
4799 SmallVector<DeferredModuleToParse, 0> deferredModules;
4801 SmallVector<InnerSymFixups, 0> moduleFixups;
4803 hw::InnerSymbolNamespaceCollection innerSymbolNamespaces;
4805 ModuleOp mlirModule;
4810 FIRCircuitParser::importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
4811 SmallVectorImpl<Attribute> &attrs) {
4813 auto annotations = json::parse(annotationsStr);
4814 if (
auto err = annotations.takeError()) {
4815 handleAllErrors(std::move(err), [&](
const json::ParseError &a) {
4816 auto diag = emitError(loc,
"Failed to parse JSON Annotations");
4817 diag.attachNote() << a.message();
4822 json::Path::Root root;
4823 llvm::StringMap<ArrayAttr> thisAnnotationMap;
4826 auto diag = emitError(loc,
"Invalid/unsupported annotation format");
4827 std::string jsonErrorMessage =
4828 "See inline comments for problem area in JSON:\n";
4829 llvm::raw_string_ostream s(jsonErrorMessage);
4830 root.printErrorContext(annotations.get(), s);
4831 diag.attachNote() << jsonErrorMessage;
4838 ParseResult FIRCircuitParser::importOMIR(CircuitOp circuit, SMLoc loc,
4839 StringRef annotationsStr,
4840 SmallVectorImpl<Attribute> &annos) {
4842 auto annotations = json::parse(annotationsStr);
4843 if (
auto err = annotations.takeError()) {
4844 handleAllErrors(std::move(err), [&](
const json::ParseError &a) {
4845 auto diag = emitError(loc,
"Failed to parse OMIR file");
4846 diag.attachNote() << a.message();
4851 json::Path::Root root;
4852 if (!
fromOMIRJSON(annotations.get(), annos, root, circuit.getContext())) {
4853 auto diag = emitError(loc,
"Invalid/unsupported OMIR format");
4854 std::string jsonErrorMessage =
4855 "See inline comments for problem area in JSON:\n";
4856 llvm::raw_string_ostream s(jsonErrorMessage);
4857 root.printErrorContext(annotations.get(), s);
4858 diag.attachNote() << jsonErrorMessage;
4865 ParseResult FIRCircuitParser::parseLayerName(SymbolRefAttr &result) {
4866 auto *context = getContext();
4867 SmallVector<StringRef> strings;
4870 if (parseId(name,
"expected layer name"))
4872 strings.push_back(name);
4873 }
while (consumeIf(FIRToken::period));
4875 SmallVector<FlatSymbolRefAttr> nested;
4876 nested.reserve(strings.size() - 1);
4877 for (
unsigned i = 1, e = strings.size(); i < e; ++i)
4884 ParseResult FIRCircuitParser::parseOptionalEnabledLayers(ArrayAttr &result) {
4885 if (getToken().getKind() != FIRToken::kw_enablelayer) {
4890 if (requireFeature({4, 0, 0},
"modules with layers enabled"))
4893 SmallVector<Attribute> layers;
4895 SymbolRefAttr layer;
4897 if (parseLayerName(layer))
4899 layers.push_back(layer);
4900 }
while (getToken().getKind() == FIRToken::kw_enablelayer);
4911 SmallVectorImpl<SMLoc> &resultPortLocs,
4914 while (getToken().isAny(FIRToken::kw_input, FIRToken::kw_output) &&
4916 getIndentation() > indent) {
4922 auto backtrackState = getLexer().getCursor();
4924 bool isOutput = getToken().is(FIRToken::kw_output);
4929 if (!getToken().isAny(FIRToken::identifier, FIRToken::literal_identifier) &&
4930 !getToken().isKeyword()) {
4931 backtrackState.restore(getLexer());
4937 LocWithInfo info(getToken().getLoc(),
this);
4938 if (parseId(name,
"expected port name") ||
4939 parseToken(FIRToken::colon,
"expected ':' in port definition") ||
4940 parseType(type,
"expected a type in port declaration") ||
4941 info.parseOptionalInfo())
4944 StringAttr innerSym = {};
4945 resultPorts.push_back(
4946 {name, type,
direction::get(isOutput), innerSym, info.getLoc()});
4947 resultPortLocs.push_back(info.getFIRLoc());
4952 for (
auto portAndLoc : llvm::zip(resultPorts, resultPortLocs)) {
4953 PortInfo &port = std::get<0>(portAndLoc);
4954 auto &entry = portIds[port.
name];
4955 if (!entry.isValid()) {
4956 entry = std::get<1>(portAndLoc);
4960 emitError(std::get<1>(portAndLoc),
4961 "redefinition of name '" + port.
getName() +
"'")
4962 .attachNote(translateLocation(entry))
4963 <<
"previous definition here";
4972 ParseResult FIRCircuitParser::parseRefList(ArrayRef<PortInfo> portList,
4973 ArrayAttr &internalPathsResult) {
4974 struct RefStatementInfo {
4976 InternalPathAttr resolvedPath;
4980 SmallVector<RefStatementInfo> refStatements;
4981 SmallPtrSet<StringAttr, 8> seenNames;
4982 SmallPtrSet<StringAttr, 8> seenRefs;
4985 if (getToken().is(FIRToken::kw_ref) &&
4986 (requireFeature({2, 0, 0},
"ref statements") ||
4987 removedFeature({4, 0, 0},
"ref statements")))
4991 while (consumeIf(FIRToken::kw_ref)) {
4992 auto loc = getToken().getLoc();
4996 if (parseId(refName,
"expected ref name"))
4998 if (consumeIf(FIRToken::period) || consumeIf(FIRToken::l_square))
5000 loc,
"ref statements for aggregate elements not yet supported");
5001 if (parseToken(FIRToken::kw_is,
"expected 'is' in ref statement"))
5004 if (!seenRefs.insert(refName).second)
5005 return emitError(loc,
"duplicate ref statement for '" + refName.strref() +
5008 auto kind = getToken().getKind();
5009 if (kind != FIRToken::string)
5010 return emitError(loc,
"expected string in ref statement");
5014 consumeToken(FIRToken::string);
5016 refStatements.push_back(RefStatementInfo{refName, resolved, loc});
5020 SmallVector<Attribute> internalPaths(portList.size(),
5023 llvm::SmallBitVector usedRefs(refStatements.size());
5024 size_t matchedPaths = 0;
5025 for (
auto [idx, port] : llvm::enumerate(portList)) {
5026 if (!type_isa<RefType>(port.
type))
5032 return mlir::emitError(
5034 "references in ports must be output on extmodule and intmodule");
5036 llvm::find_if(refStatements, [pname = port.
name](
const auto &r) {
5037 return r.refName == pname;
5040 if (refStmtIt == refStatements.end()) {
5041 if (!refStatements.empty())
5042 return mlir::emitError(port.
loc,
"no ref statement found for ref port ")
5047 usedRefs.set(std::distance(refStatements.begin(), refStmtIt));
5048 internalPaths[idx] = refStmtIt->resolvedPath;
5052 if (!refStatements.empty() && matchedPaths != refStatements.size()) {
5053 assert(matchedPaths < refStatements.size());
5055 auto idx = usedRefs.find_first_unset();
5057 return emitError(refStatements[idx].loc,
"unused ref statement");
5061 internalPathsResult =
ArrayAttr::get(getContext(), internalPaths);
5067 ParseResult FIRCircuitParser::skipToModuleEnd(
unsigned indent) {
5069 switch (getToken().getKind()) {
5073 case FIRToken::error:
5077 case FIRToken::kw_class:
5078 case FIRToken::kw_declgroup:
5079 case FIRToken::kw_extclass:
5080 case FIRToken::kw_extmodule:
5081 case FIRToken::kw_intmodule:
5082 case FIRToken::kw_formal:
5083 case FIRToken::kw_module:
5084 case FIRToken::kw_public:
5085 case FIRToken::kw_layer:
5086 case FIRToken::kw_option:
5087 case FIRToken::kw_type:
5091 if (getIndentation() == indent)
5104 SmallVector<Attribute, 8> parameters;
5105 SmallPtrSet<StringAttr, 8> seen;
5106 while (consumeIf(FIRToken::kw_parameter)) {
5110 if (parseParameter(name, value, loc))
5112 auto typedValue = dyn_cast<TypedAttr>(value);
5114 return emitError(loc)
5115 <<
"invalid value for parameter '" << name.getValue() <<
"'";
5116 if (!seen.insert(name).second)
5117 return emitError(loc,
5118 "redefinition of parameter '" + name.getValue() +
"'");
5126 ParseResult FIRCircuitParser::parseClass(CircuitOp circuit,
unsigned indent) {
5128 SmallVector<PortInfo, 8> portList;
5129 SmallVector<SMLoc> portLocs;
5130 LocWithInfo info(getToken().getLoc(),
this);
5135 consumeToken(FIRToken::kw_class);
5136 if (parseId(name,
"expected class name") ||
5137 parseToken(FIRToken::colon,
"expected ':' in class definition") ||
5138 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5141 if (name == circuit.getName())
5142 return mlir::emitError(info.getLoc(),
5143 "class cannot be the top of a circuit");
5145 for (
auto &portInfo : portList)
5146 if (!isa<PropertyType>(portInfo.type))
5147 return mlir::emitError(portInfo.loc,
5148 "ports on classes must be properties");
5151 auto builder = circuit.getBodyBuilder();
5152 auto classOp = builder.create<ClassOp>(info.getLoc(), name, portList);
5153 classOp.setPrivate();
5154 deferredModules.emplace_back(
5155 DeferredModuleToParse{classOp, portLocs, getLexer().getCursor(), indent});
5158 getConstants().classMap[name.getValue()] = classOp;
5159 return skipToModuleEnd(indent);
5163 ParseResult FIRCircuitParser::parseExtClass(CircuitOp circuit,
5166 SmallVector<PortInfo, 8> portList;
5167 SmallVector<SMLoc> portLocs;
5168 LocWithInfo info(getToken().getLoc(),
this);
5173 consumeToken(FIRToken::kw_extclass);
5174 if (parseId(name,
"expected extclass name") ||
5175 parseToken(FIRToken::colon,
"expected ':' in extclass definition") ||
5176 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5179 if (name == circuit.getName())
5180 return mlir::emitError(info.getLoc(),
5181 "extclass cannot be the top of a circuit");
5183 for (
auto &portInfo : portList)
5184 if (!isa<PropertyType>(portInfo.type))
5185 return mlir::emitError(portInfo.loc,
5186 "ports on extclasses must be properties");
5189 auto builder = circuit.getBodyBuilder();
5190 auto extClassOp = builder.create<ExtClassOp>(info.getLoc(), name, portList);
5193 getConstants().classMap[name.getValue()] = extClassOp;
5194 return skipToModuleEnd(indent);
5201 ParseResult FIRCircuitParser::parseExtModule(CircuitOp circuit,
5205 SmallVector<PortInfo, 8> portList;
5206 SmallVector<SMLoc> portLocs;
5207 LocWithInfo info(getToken().getLoc(),
this);
5208 consumeToken(FIRToken::kw_extmodule);
5209 if (parseId(name,
"expected extmodule name") ||
5210 parseOptionalEnabledLayers(layers) ||
5211 parseToken(FIRToken::colon,
"expected ':' in extmodule definition") ||
5212 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5216 if (consumeIf(FIRToken::kw_defname)) {
5217 if (parseToken(FIRToken::equal,
"expected '=' in defname") ||
5218 parseId(defName,
"expected defname name"))
5222 ArrayAttr parameters;
5223 ArrayAttr internalPaths;
5228 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
5229 if (
auto ftype = type_dyn_cast<FIRRTLType>(pi.type)) {
5230 if (ftype.hasUninferredWidth())
5231 return emitError(loc,
"extmodule port must have known width");
5236 auto builder = circuit.getBodyBuilder();
5237 auto isMainModule = (name == circuit.getName());
5239 (isMainModule && getConstants().options.scalarizePublicModules) ||
5240 getConstants().options.scalarizeExtModules
5241 ? Convention::Scalarized
5242 : Convention::Internal;
5245 auto extModuleOp = builder.create<FExtModuleOp>(
5246 info.getLoc(), name, conventionAttr, portList, defName, annotations,
5247 parameters, internalPaths, layers);
5248 auto visibility = isMainModule ? SymbolTable::Visibility::Public
5249 : SymbolTable::Visibility::Private;
5250 SymbolTable::setSymbolVisibility(extModuleOp, visibility);
5258 ParseResult FIRCircuitParser::parseIntModule(CircuitOp circuit,
5263 SmallVector<PortInfo, 8> portList;
5264 SmallVector<SMLoc> portLocs;
5265 LocWithInfo info(getToken().getLoc(),
this);
5266 consumeToken(FIRToken::kw_intmodule);
5267 if (parseId(name,
"expected intmodule name") ||
5268 parseOptionalEnabledLayers(layers) ||
5269 parseToken(FIRToken::colon,
"expected ':' in intmodule definition") ||
5270 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent) ||
5271 parseToken(FIRToken::kw_intrinsic,
"expected 'intrinsic'") ||
5272 parseToken(FIRToken::equal,
"expected '=' in intrinsic") ||
5273 parseId(intName,
"expected intrinsic name"))
5276 ArrayAttr parameters;
5277 ArrayAttr internalPaths;
5281 ArrayAttr annotations = getConstants().emptyArrayAttr;
5282 auto builder = circuit.getBodyBuilder();
5284 .create<FIntModuleOp>(info.getLoc(), name, portList, intName, annotations,
5285 parameters, internalPaths, layers)
5291 ParseResult FIRCircuitParser::parseModule(CircuitOp circuit,
bool isPublic,
5294 SmallVector<PortInfo, 8> portList;
5295 SmallVector<SMLoc> portLocs;
5297 auto modLoc = getToken().getLoc();
5298 LocWithInfo info(modLoc,
this);
5299 consumeToken(FIRToken::kw_module);
5300 if (parseId(name,
"expected module name") ||
5301 parseOptionalEnabledLayers(layers) ||
5302 parseToken(FIRToken::colon,
"expected ':' in module definition") ||
5303 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5307 if (name == circuit.getName()) {
5308 if (!isPublic && removedFeature({4, 0, 0},
"private main modules", modLoc))
5313 if (isPublic && version >=
FIRVersion({4, 0, 0})) {
5314 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
5315 if (
auto ftype = type_dyn_cast<FIRRTLType>(pi.type)) {
5316 if (ftype.hasUninferredWidth())
5317 return emitError(loc,
"public module port must have known width");
5318 if (ftype.hasUninferredReset())
5319 return emitError(loc,
5320 "public module port must have concrete reset type");
5325 ArrayAttr annotations = getConstants().emptyArrayAttr;
5326 auto convention = Convention::Internal;
5327 if (isPublic && getConstants().options.scalarizePublicModules)
5328 convention = Convention::Scalarized;
5329 if (!isPublic && getConstants().options.scalarizeInternalModules)
5330 convention = Convention::Scalarized;
5332 auto builder = circuit.getBodyBuilder();
5333 auto moduleOp = builder.create<FModuleOp>(info.getLoc(), name, conventionAttr,
5334 portList, annotations, layers);
5336 auto visibility = isPublic ? SymbolTable::Visibility::Public
5337 : SymbolTable::Visibility::Private;
5338 SymbolTable::setSymbolVisibility(moduleOp, visibility);
5342 deferredModules.emplace_back(DeferredModuleToParse{
5343 moduleOp, portLocs, getLexer().getCursor(), indent});
5345 if (skipToModuleEnd(indent))
5352 ParseResult FIRCircuitParser::parseFormal(CircuitOp circuit,
unsigned indent) {
5353 consumeToken(FIRToken::kw_formal);
5354 StringRef id, moduleName;
5356 LocWithInfo info(getToken().getLoc(),
this);
5357 auto builder = circuit.getBodyBuilder();
5361 if (parseId(
id,
"expected formal test name") ||
5362 parseToken(FIRToken::kw_of,
"expected 'of' in formal test") ||
5363 parseId(moduleName,
"expected module name"))
5367 NamedAttrList params;
5368 if (consumeIf(FIRToken::comma)) {
5370 if (getToken().isNot(FIRToken::identifier) || getTokenSpelling() !=
"bound")
5371 return emitError(
"expected 'bound' after ','");
5373 if (parseToken(FIRToken::equal,
"expected '=' after 'bound'") ||
5374 parseIntLit(bound,
"expected integer bound after '='"))
5377 return emitError(
"bound must be a positive integer");
5378 if (info.parseOptionalInfo())
5380 params.set(
"bound", builder.getIntegerAttr(builder.getI32Type(), bound));
5383 if (parseToken(FIRToken::colon,
"expected ':' in formal test") ||
5384 info.parseOptionalInfo())
5386 while (getIndentation() > indent) {
5387 StringAttr paramName;
5388 Attribute paramValue;
5390 if (parseParameter(paramName, paramValue, paramLoc,
5393 if (params.set(paramName, paramValue))
5394 return emitError(paramLoc,
"redefinition of parameter '" +
5395 paramName.getValue() +
"'");
5399 builder.create<firrtl::FormalOp>(info.getLoc(), id, moduleName,
5400 params.getDictionary(getContext()));
5404 ParseResult FIRCircuitParser::parseToplevelDefinition(CircuitOp circuit,
5406 switch (getToken().getKind()) {
5407 case FIRToken::kw_class:
5408 return parseClass(circuit, indent);
5409 case FIRToken::kw_declgroup:
5410 if (requireFeature({3, 2, 0},
"optional groups") ||
5411 removedFeature({3, 3, 0},
"optional groups"))
5413 return parseLayer(circuit);
5414 case FIRToken::kw_extclass:
5415 return parseExtClass(circuit, indent);
5416 case FIRToken::kw_extmodule:
5417 return parseExtModule(circuit, indent);
5418 case FIRToken::kw_formal:
5419 if (requireFeature({4, 0, 0},
"inline formal tests"))
5421 return parseFormal(circuit, indent);
5422 case FIRToken::kw_intmodule:
5423 if (requireFeature({1, 2, 0},
"inline formal tests") ||
5424 removedFeature({4, 0, 0},
"intrinsic modules"))
5426 return parseIntModule(circuit, indent);
5427 case FIRToken::kw_layer:
5428 if (requireFeature({3, 3, 0},
"layers"))
5430 return parseLayer(circuit);
5431 case FIRToken::kw_module:
5432 return parseModule(circuit,
false, indent);
5433 case FIRToken::kw_public:
5434 if (requireFeature({3, 3, 0},
"public modules"))
5437 if (getToken().getKind() == FIRToken::kw_module)
5438 return parseModule(circuit,
true, indent);
5439 return emitError(getToken().getLoc(),
"only modules may be public");
5440 case FIRToken::kw_type:
5441 return parseTypeDecl();
5442 case FIRToken::kw_option:
5445 return parseOptionDecl(circuit);
5447 return emitError(getToken().getLoc(),
"unknown toplevel definition");
5452 ParseResult FIRCircuitParser::parseTypeDecl() {
5456 auto loc = getToken().getLoc();
5458 if (getToken().isKeyword())
5459 return emitError(loc) <<
"cannot use keyword '" << getToken().getSpelling()
5460 <<
"' for type alias name";
5462 if (parseId(
id,
"expected type name") ||
5463 parseToken(FIRToken::equal,
"expected '=' in type decl") ||
5469 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type))
5473 <<
"type alias for non-base type " << type
5474 <<
" is currently not supported. Type alias is stripped immediately";
5476 if (!getConstants().aliasMap.insert({id, type}).second)
5477 return emitError(loc) <<
"type alias `" << name.getValue()
5478 <<
"` is already defined";
5483 ParseResult FIRCircuitParser::parseOptionDecl(CircuitOp circuit) {
5486 auto loc = getToken().getLoc();
5488 LocWithInfo info(getToken().getLoc(),
this);
5489 if (parseId(
id,
"expected an option group name") ||
5490 parseToken(FIRToken::colon,
5491 "expected ':' after option group definition") ||
5492 info.parseOptionalInfo())
5495 auto builder = OpBuilder::atBlockEnd(circuit.getBodyBlock());
5496 auto optionOp = builder.create<OptionOp>(info.getLoc(), id);
5497 auto *block =
new Block;
5498 optionOp.getBody().push_back(block);
5499 builder.setInsertionPointToEnd(block);
5501 auto baseIndent = getIndentation();
5503 while (getIndentation() == baseIndent) {
5505 LocWithInfo caseInfo(getToken().getLoc(),
this);
5506 if (parseId(
id,
"expected an option case ID") ||
5507 caseInfo.parseOptionalInfo())
5510 if (!cases.insert(
id).second)
5511 return emitError(loc)
5512 <<
"duplicate option case definition '" <<
id <<
"'";
5514 builder.create<OptionCaseOp>(caseInfo.getLoc(), id);
5521 ParseResult FIRCircuitParser::parseLayer(CircuitOp circuit) {
5522 auto baseIndent = getIndentation();
5525 SmallVector<std::pair<std::optional<unsigned>, LayerOp>> layerStack;
5528 auto parseOne = [&](
Block *block) -> ParseResult {
5529 auto indent = getIndentation();
5530 StringRef id, convention;
5531 LocWithInfo info(getToken().getLoc(),
this);
5533 if (parseId(
id,
"expected layer name") ||
5534 parseToken(FIRToken::comma,
"expected ','") ||
5535 parseGetSpelling(convention))
5538 auto layerConvention = symbolizeLayerConvention(convention);
5539 if (!layerConvention) {
5540 emitError() <<
"unknown convention '" << convention
5541 <<
"' (did you misspell it?)";
5546 hw::OutputFileAttr outputDir;
5547 if (consumeIf(FIRToken::comma)) {
5548 if (getToken().getKind() == FIRToken::string) {
5549 auto text = getToken().getStringValue();
5551 return emitError() <<
"output directory must not be blank";
5552 outputDir = hw::OutputFileAttr::getAsDirectory(getContext(), text);
5553 consumeToken(FIRToken::string);
5557 if (parseToken(FIRToken::colon,
"expected ':' after layer definition") ||
5558 info.parseOptionalInfo())
5560 auto builder = OpBuilder::atBlockEnd(block);
5562 auto layerOp = builder.create<LayerOp>(info.getLoc(), id, *layerConvention);
5563 layerOp->getRegion(0).push_back(
new Block());
5565 layerOp->setAttr(
"output_file", outputDir);
5566 layerStack.push_back({indent, layerOp});
5570 if (parseOne(circuit.getBodyBlock()))
5574 while (getIndentation() > baseIndent) {
5575 switch (getToken().getKind()) {
5576 case FIRToken::kw_declgroup:
5577 case FIRToken::kw_layer: {
5580 while (layerStack.back().first >= getIndentation())
5581 layerStack.pop_back();
5582 auto parentLayer = layerStack.back().second;
5583 if (parseOne(&parentLayer.getBody().front()))
5588 return emitError(
"expected 'layer'"), failure();
5597 FIRCircuitParser::parseModuleBody(
const SymbolTable &circuitSymTbl,
5598 DeferredModuleToParse &deferredModule,
5599 InnerSymFixups &fixups) {
5600 FModuleLike moduleOp = deferredModule.moduleOp;
5601 auto &body = moduleOp->getRegion(0).front();
5602 auto &portLocs = deferredModule.portLocs;
5606 FIRLexer moduleBodyLexer(getLexer().getSourceMgr(), getContext());
5609 deferredModule.lexerCursor.restore(moduleBodyLexer);
5611 FIRModuleContext moduleContext(getConstants(), moduleBodyLexer, version);
5615 auto portList = moduleOp.getPorts();
5616 auto portArgs = body.getArguments();
5617 for (
auto tuple : llvm::zip(portList, portLocs, portArgs)) {
5618 PortInfo &port = std::get<0>(tuple);
5619 llvm::SMLoc loc = std::get<1>(tuple);
5620 BlockArgument portArg = std::get<2>(tuple);
5622 if (moduleContext.addSymbolEntry(port.
getName(), portArg, loc))
5626 FIRStmtParser stmtParser(body, moduleContext, fixups, circuitSymTbl, version);
5629 auto result = stmtParser.parseSimpleStmtBlock(deferredModule.indent);
5635 size_t numVerifPrintfs = 0;
5636 std::optional<Location> printfLoc;
5638 deferredModule.moduleOp.walk([&](PrintFOp printFOp) {
5643 printfLoc = printFOp.getLoc();
5646 if (numVerifPrintfs > 0) {
5648 mlir::emitError(deferredModule.moduleOp.getLoc(),
"module contains ")
5650 <<
" printf-encoded verification operation(s), which are no longer "
5652 diag.attachNote(*printfLoc)
5653 <<
"example printf here, this is now just a printf and nothing more";
5654 diag.attachNote() <<
"For more information, see "
5655 "https://github.com/llvm/circt/issues/6970";
5671 ParseResult FIRCircuitParser::parseCircuit(
5672 SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBufs,
5673 SmallVectorImpl<const llvm::MemoryBuffer *> &omirBufs,
5674 mlir::TimingScope &ts) {
5676 auto indent = getIndentation();
5677 if (parseToken(FIRToken::kw_FIRRTL,
"expected 'FIRRTL'"))
5679 if (!indent.has_value())
5680 return emitError(
"'FIRRTL' must be first token on its line");
5681 if (parseToken(FIRToken::kw_version,
"expected version after 'FIRRTL'") ||
5682 parseVersionLit(
"expected version literal"))
5684 indent = getIndentation();
5686 if (!indent.has_value())
5687 return emitError(
"'circuit' must be first token on its line");
5688 unsigned circuitIndent = *indent;
5690 LocWithInfo info(getToken().getLoc(),
this);
5692 SMLoc inlineAnnotationsLoc;
5693 StringRef inlineAnnotations;
5696 if (parseToken(FIRToken::kw_circuit,
5697 "expected a top-level 'circuit' definition") ||
5698 parseId(name,
"expected circuit name") ||
5699 parseToken(FIRToken::colon,
"expected ':' in circuit definition") ||
5700 parseOptionalAnnotations(inlineAnnotationsLoc, inlineAnnotations) ||
5701 info.parseOptionalInfo())
5705 OpBuilder b(mlirModule.getBodyRegion());
5706 auto circuit = b.create<CircuitOp>(info.getLoc(), name);
5709 auto parseAnnotationTimer = ts.nest(
"Parse annotations");
5715 SmallVector<Attribute> annos;
5716 if (!inlineAnnotations.empty())
5717 if (importAnnotationsRaw(inlineAnnotationsLoc, inlineAnnotations, annos))
5721 for (
auto *annotationsBuf : annotationsBufs)
5722 if (importAnnotationsRaw(info.getFIRLoc(), annotationsBuf->getBuffer(),
5726 parseAnnotationTimer.stop();
5727 auto parseOMIRTimer = ts.nest(
"Parse OMIR");
5731 for (
auto *omirBuf : omirBufs)
5732 if (importOMIR(circuit, info.getFIRLoc(), omirBuf->getBuffer(), annos))
5735 parseOMIRTimer.stop();
5743 auto parseTimer = ts.nest(
"Parse modules");
5744 deferredModules.reserve(16);
5748 switch (getToken().getKind()) {
5756 case FIRToken::error:
5760 emitError(
"unexpected token in circuit");
5763 case FIRToken::kw_class:
5764 case FIRToken::kw_declgroup:
5765 case FIRToken::kw_extclass:
5766 case FIRToken::kw_extmodule:
5767 case FIRToken::kw_intmodule:
5768 case FIRToken::kw_layer:
5769 case FIRToken::kw_formal:
5770 case FIRToken::kw_module:
5771 case FIRToken::kw_option:
5772 case FIRToken::kw_public:
5773 case FIRToken::kw_type: {
5774 auto indent = getIndentation();
5775 if (!indent.has_value())
5776 return emitError(
"'module' must be first token on its line"), failure();
5777 unsigned definitionIndent = *indent;
5779 if (definitionIndent <= circuitIndent)
5780 return emitError(
"module should be indented more"), failure();
5782 if (parseToplevelDefinition(circuit, definitionIndent))
5796 (void)getLexer().translateLocation(info.getFIRLoc());
5802 DenseMap<Attribute, Location> nameToOrigLoc;
5803 for (
auto &op : *circuit.getBodyBlock()) {
5806 op.getAttrOfType<StringAttr>(mlir::SymbolTable::getSymbolAttrName());
5811 auto it = nameToOrigLoc.try_emplace(nameAttr, op.getLoc());
5814 .append(
"redefinition of symbol named '", nameAttr.getValue(),
"'")
5815 .attachNote(it.first->second)
5816 .append(
"see existing symbol definition here");
5822 SymbolTable circuitSymTbl(circuit);
5824 moduleFixups.resize(deferredModules.size());
5829 for (
auto &d : deferredModules)
5830 innerSymbolNamespaces.get(d.moduleOp.getOperation());
5833 auto anyFailed = mlir::failableParallelForEachN(
5834 getContext(), 0, deferredModules.size(), [&](
size_t index) {
5835 if (parseModuleBody(circuitSymTbl, deferredModules[index],
5836 moduleFixups[index]))
5840 if (failed(anyFailed))
5845 for (
auto &fixups : moduleFixups) {
5846 if (failed(fixups.resolve(innerSymbolNamespaces)))
5852 auto parseLayerName = [&](StringRef name) {
5854 auto [head, rest] = name.split(
".");
5855 SmallVector<FlatSymbolRefAttr> nestedRefs;
5856 while (!rest.empty()) {
5858 std::tie(next, rest) = rest.split(
".");
5864 auto parseLayers = [&](
const auto &layers) {
5865 SmallVector<Attribute> layersAttr;
5866 for (
const auto &layer : layers)
5867 layersAttr.push_back(parseLayerName(layer));
5868 if (layersAttr.empty())
5873 if (
auto enableLayers = parseLayers(getConstants().options.enableLayers))
5874 circuit.setEnableLayersAttr(enableLayers);
5875 if (
auto disableLayers = parseLayers(getConstants().options.disableLayers))
5876 circuit.setDisableLayersAttr(disableLayers);
5877 circuit.setDefaultLayerSpecialization(
5878 getConstants().options.defaultLayerSpecialization);
5891 auto sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
5892 SmallVector<const llvm::MemoryBuffer *> annotationsBufs;
5893 unsigned fileID = 1;
5895 annotationsBufs.push_back(
5896 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID() + fileID));
5898 SmallVector<const llvm::MemoryBuffer *> omirBufs;
5899 for (
unsigned e = sourceMgr.getNumBuffers(); fileID < e; ++fileID)
5901 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID() + fileID));
5903 context->loadDialect<CHIRRTLDialect>();
5904 context->loadDialect<FIRRTLDialect, hw::HWDialect>();
5911 SharedParserConstants state(context, options);
5912 FIRLexer lexer(sourceMgr, context);
5914 .parseCircuit(annotationsBufs, omirBufs, ts))
5919 auto circuitVerificationTimer = ts.nest(
"Verify circuit");
5920 if (failed(
verify(*module)))
5927 static mlir::TranslateToMLIRRegistration fromFIR(
5928 "import-firrtl",
"import .fir",
5929 [](llvm::SourceMgr &sourceMgr, MLIRContext *context) {
5930 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.
bool fromOMIRJSON(llvm::json::Value &value, SmallVectorImpl< Attribute > &annotations, llvm::json::Path path, MLIRContext *context)
Convert a JSON value containing OMIR JSON (an array of OMNodes), convert this to an OMIRAnnotation,...
constexpr FIRVersion minimumFIRVersion(2, 0, 0)
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