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"
46 using namespace circt;
47 using namespace firrtl;
48 using namespace chirrtl;
51 using llvm::SourceMgr;
52 using mlir::LocationAttr;
65 struct SharedParserConstants {
67 : context(context), options(options),
68 emptyArrayAttr(ArrayAttr::
get(context, {})),
79 MLIRContext *
const context;
85 llvm::StringMap<FIRRTLType> aliasMap;
88 llvm::DenseMap<StringRef, ClassLike> classMap;
91 const ArrayAttr emptyArrayAttr;
94 const StringAttr loIdentifier, hiIdentifier, amountIdentifier;
95 const StringAttr fieldIndexIdentifier, indexIdentifier;
98 const hw::InnerRefAttr placeholderInnerRef;
101 SharedParserConstants(
const SharedParserConstants &) =
delete;
102 void operator=(
const SharedParserConstants &) =
delete;
115 FIRParser(SharedParserConstants &constants,
FIRLexer &lexer,
117 : version(version), constants(constants), lexer(lexer),
118 locatorFilenameCache(constants.loIdentifier ) {
122 SharedParserConstants &getConstants()
const {
return constants; }
123 MLIRContext *getContext()
const {
return constants.context; }
125 FIRLexer &getLexer() {
return lexer; }
128 std::optional<unsigned> getIndentation()
const {
133 const FIRToken &getToken()
const {
return lexer.getToken(); }
134 StringRef getTokenSpelling()
const {
return getToken().
getSpelling(); }
141 InFlightDiagnostic emitError(
const Twine &message = {}) {
142 return emitError(getToken().getLoc(), message);
144 InFlightDiagnostic emitError(SMLoc loc,
const Twine &message = {});
147 InFlightDiagnostic emitWarning(
const Twine &message = {}) {
148 return emitWarning(getToken().getLoc(), message);
151 InFlightDiagnostic emitWarning(SMLoc loc,
const Twine &message = {});
161 Location translateLocation(llvm::SMLoc loc) {
162 return lexer.translateLocation(loc);
167 ParseResult parseOptionalInfoLocator(LocationAttr &result);
171 ParseResult parseOptionalName(StringAttr &name);
177 ParseResult requireFeature(
FIRVersion minimum, StringRef feature) {
178 return requireFeature(minimum, feature, getToken().getLoc());
181 ParseResult requireFeature(
FIRVersion minimum, StringRef feature, SMLoc loc) {
182 if (version < minimum)
183 return emitError(loc)
184 << feature <<
" are a FIRRTL " << minimum
185 <<
"+ feature, but the specified FIRRTL version was " << version;
189 ParseResult removedFeature(
FIRVersion removedVersion, StringRef feature) {
190 return removedFeature(removedVersion, feature, getToken().getLoc());
193 ParseResult removedFeature(
FIRVersion removedVersion, StringRef feature,
195 if (version >= removedVersion)
196 return emitError(loc)
197 << feature <<
" were removed in FIRRTL " << removedVersion
198 <<
", but the specified FIRRTL version was " << version;
208 ParseResult parseOptionalAnnotations(SMLoc &loc, StringRef &result);
217 if (getToken().isNot(kind))
227 FIRToken consumedToken = getToken();
228 assert(consumedToken.
isNot(FIRToken::eof, FIRToken::error) &&
229 "shouldn't advance past EOF or errors");
231 return consumedToken;
240 FIRToken consumedToken = getToken();
241 assert(consumedToken.
is(kind) &&
"consumed an unexpected token");
243 return consumedToken;
248 ParseResult parseGetSpelling(StringRef &spelling) {
249 spelling = getTokenSpelling();
255 ParseResult parseToken(
FIRToken::Kind expectedToken,
const Twine &message);
260 const std::function<ParseResult()> &parseElement);
267 ParseResult parseIntLit(APInt &result,
const Twine &message);
268 ParseResult parseIntLit(int64_t &result,
const Twine &message);
269 ParseResult parseIntLit(int32_t &result,
const Twine &message);
272 ParseResult parseVersionLit(
const Twine &message);
275 template <
typename T>
276 ParseResult parseOptionalWidth(T &result);
279 ParseResult parseId(StringRef &result,
const Twine &message);
280 ParseResult parseId(StringAttr &result,
const Twine &message);
281 ParseResult parseFieldId(StringRef &result,
const Twine &message);
282 ParseResult parseFieldIdSeq(SmallVectorImpl<StringRef> &result,
283 const Twine &message);
284 ParseResult parseEnumType(
FIRRTLType &result);
285 ParseResult parseListType(
FIRRTLType &result);
288 ParseResult parsePropertyType(
PropertyType &result,
const Twine &message);
290 ParseResult parseRUW(RUWAttr &result);
291 ParseResult parseOptionalRUW(RUWAttr &result);
293 ParseResult parseParameter(StringAttr &resultName, TypedAttr &resultValue,
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({3, 2, 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(
nextFIRVersion,
"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);
1202 ParseResult FIRParser::parseParameter(StringAttr &resultName,
1203 TypedAttr &resultValue,
1205 mlir::Builder builder(getContext());
1207 auto loc = getToken().getLoc();
1210 if (parseId(name,
"expected parameter name") ||
1211 parseToken(FIRToken::equal,
"expected '=' in parameter"))
1215 switch (getToken().getKind()) {
1217 return emitError(
"expected parameter value"), failure();
1218 case FIRToken::integer:
1219 case FIRToken::signed_integer: {
1221 if (parseIntLit(result,
"invalid integer parameter"))
1227 if (result.getBitWidth() < 32)
1228 result = result.sext(32);
1230 value = builder.getIntegerAttr(
1231 builder.getIntegerType(result.getBitWidth(), result.isSignBitSet()),
1235 case FIRToken::string: {
1237 value = builder.getStringAttr(getToken().getStringValue());
1238 consumeToken(FIRToken::string);
1241 case FIRToken::verbatim_string: {
1243 auto text = builder.getStringAttr(getToken().getVerbatimStringValue());
1245 consumeToken(FIRToken::verbatim_string);
1248 case FIRToken::floatingpoint:
1250 if (!llvm::to_float(getTokenSpelling(), v))
1251 return emitError(
"invalid float parameter syntax"), failure();
1253 value = builder.getF64FloatAttr(v);
1254 consumeToken(FIRToken::floatingpoint);
1258 resultName = builder.getStringAttr(name);
1259 resultValue = value;
1275 llvm::StringMap<std::pair<SMLoc, SymbolValueEntry>, llvm::BumpPtrAllocator>;
1283 struct UnbundledValueRestorer {
1285 size_t startingSize;
1287 startingSize = list.size();
1289 ~UnbundledValueRestorer() { list.resize(startingSize); }
1298 struct FIRModuleContext :
public FIRParser {
1299 explicit FIRModuleContext(SharedParserConstants &constants,
FIRLexer &lexer,
1301 : FIRParser(constants, lexer, version) {}
1307 llvm::DenseMap<std::pair<Attribute, Type>, Value> constantCache;
1310 template <
typename OpTy = ConstantOp,
typename... Args>
1311 Value getCachedConstant(ImplicitLocOpBuilder &builder, Attribute attr,
1312 Type type, Args &&...args) {
1313 auto &result = constantCache[{attr, type}];
1319 OpBuilder::InsertPoint savedIP;
1321 auto *parentOp = builder.getInsertionBlock()->getParentOp();
1322 if (!isa<FModuleLike>(parentOp)) {
1323 savedIP = builder.saveInsertionPoint();
1324 while (!isa<FModuleLike>(parentOp)) {
1325 builder.setInsertionPoint(parentOp);
1326 parentOp = builder.getInsertionBlock()->getParentOp();
1330 result = builder.create<OpTy>(type, std::forward<Args>(args)...);
1332 if (savedIP.isSet())
1333 builder.setInsertionPoint(savedIP.getBlock(), savedIP.getPoint());
1344 Value &getCachedSubaccess(Value value,
unsigned index) {
1345 auto &result = subaccessCache[{value, index}];
1348 auto it = scopeMap.find(value.getParentBlock());
1349 if (it != scopeMap.end())
1350 it->second->scopedSubaccesses.push_back({result, index});
1360 ParseResult addSymbolEntry(StringRef name,
SymbolValueEntry entry, SMLoc loc,
1361 bool insertNameIntoGlobalScope =
false);
1362 ParseResult addSymbolEntry(StringRef name, Value value, SMLoc loc,
1363 bool insertNameIntoGlobalScope =
false) {
1365 insertNameIntoGlobalScope);
1370 SMLoc loc,
bool fatal =
true);
1375 StringRef field, SMLoc loc);
1383 assert(index < unbundledValues.size());
1384 return unbundledValues[index];
1394 struct ContextScope {
1395 friend struct FIRModuleContext;
1396 ContextScope(FIRModuleContext &moduleContext, Block *block)
1397 : moduleContext(moduleContext), block(block),
1398 previousScope(moduleContext.currentScope) {
1399 moduleContext.currentScope =
this;
1400 moduleContext.scopeMap[block] =
this;
1405 for (
auto *entryPtr : scopedDecls)
1406 entryPtr->second.first = SMLoc();
1409 for (
auto subaccess : scopedSubaccesses)
1410 moduleContext.subaccessCache.erase(subaccess);
1412 moduleContext.scopeMap.erase(block);
1414 moduleContext.currentScope = previousScope;
1418 void operator=(
const ContextScope &) =
delete;
1419 ContextScope(
const ContextScope &) =
delete;
1421 FIRModuleContext &moduleContext;
1423 ContextScope *previousScope;
1424 std::vector<ModuleSymbolTableEntry *> scopedDecls;
1425 std::vector<std::pair<Value, unsigned>> scopedSubaccesses;
1439 DenseMap<Block *, ContextScope *> scopeMap;
1444 ContextScope *currentScope =
nullptr;
1455 ParseResult FIRModuleContext::addSymbolEntry(StringRef name,
1457 bool insertNameIntoGlobalScope) {
1462 if (entryIt->second.first.isValid()) {
1463 emitError(loc,
"redefinition of name '" + name +
"'")
1464 .attachNote(translateLocation(entryIt->second.first))
1465 <<
"previous definition here";
1471 entryIt->second = {loc, entry};
1472 if (currentScope && !insertNameIntoGlobalScope)
1473 currentScope->scopedDecls.push_back(&*entryIt);
1481 StringRef name, SMLoc loc) {
1482 auto &entry = symbolTable[name];
1483 if (!entry.first.isValid())
1484 return emitError(loc,
"use of unknown declaration '" + name +
"'");
1485 result = entry.second;
1486 assert(result &&
"name in symbol table without definition");
1490 ParseResult FIRModuleContext::resolveSymbolEntry(Value &result,
1492 SMLoc loc,
bool fatal) {
1493 if (!entry.is<Value>()) {
1495 emitError(loc,
"bundle value should only be used from subfield");
1498 result = entry.get<Value>();
1502 ParseResult FIRModuleContext::resolveSymbolEntry(Value &result,
1504 StringRef fieldName,
1507 emitError(loc,
"value should not be used from subfield");
1513 unsigned unbundledId = entry.get<
UnbundledID>() - 1;
1514 assert(unbundledId < unbundledValues.size());
1516 for (
auto elt : ubEntry) {
1517 if (elt.first == fieldAttr) {
1518 result = elt.second;
1523 emitError(loc,
"use of invalid field name '")
1524 << fieldName <<
"' on bundle value";
1550 struct LazyLocationListener :
public OpBuilder::Listener {
1551 LazyLocationListener(OpBuilder &builder) : builder(builder) {
1552 assert(builder.getListener() ==
nullptr);
1553 builder.setListener(
this);
1556 ~LazyLocationListener() {
1557 assert(subOps.empty() &&
"didn't process parsed operations");
1558 assert(builder.getListener() ==
this);
1559 builder.setListener(
nullptr);
1562 void startStatement() {
1563 assert(!isActive &&
"Already processing a statement");
1569 void endStatement(FIRParser &parser) {
1570 assert(isActive &&
"Not parsing a statement");
1574 for (
auto opAndSMLoc : subOps) {
1578 switch (parser.getConstants().options.infoLocatorHandling) {
1579 case ILH::IgnoreInfo:
1581 opAndSMLoc.first->setLoc(parser.translateLocation(opAndSMLoc.second));
1583 case ILH::PreferInfo:
1584 opAndSMLoc.first->setLoc(infoLoc);
1586 case ILH::FusedInfo:
1588 infoLoc.getContext(),
1589 {infoLoc, parser.translateLocation(opAndSMLoc.second)}));
1596 for (
auto opAndSMLoc : subOps)
1597 opAndSMLoc.first->setLoc(parser.translateLocation(opAndSMLoc.second));
1602 infoLoc = LocationAttr();
1603 currentSMLoc = SMLoc();
1608 void setLoc(SMLoc loc) { currentSMLoc = loc; }
1611 void setInfoLoc(LocationAttr loc) {
1612 assert(!infoLoc &&
"Info location multiply specified");
1618 void notifyOperationInserted(Operation *op,
1619 mlir::IRRewriter::InsertPoint)
override {
1620 assert(currentSMLoc != SMLoc() &&
"No .fir file location specified");
1621 assert(isActive &&
"Not parsing a statement");
1622 subOps.push_back({op, currentSMLoc});
1627 bool isActive =
false;
1635 LocationAttr infoLoc;
1642 SmallVector<std::pair<Operation *, SMLoc>, 8> subOps;
1644 void operator=(
const LazyLocationListener &) =
delete;
1645 LazyLocationListener(
const LazyLocationListener &) =
delete;
1653 struct InnerSymFixups {
1655 void add(hw::InnerRefUserOpInterface user, hw::InnerSymTarget target) {
1656 fixups.push_back({user, target});
1661 LogicalResult resolve(hw::InnerSymbolNamespaceCollection &isnc);
1665 hw::InnerRefUserOpInterface innerRefUser;
1666 hw::InnerSymTarget target;
1668 SmallVector<Fixup, 0> fixups;
1673 InnerSymFixups::resolve(hw::InnerSymbolNamespaceCollection &isnc) {
1674 for (
auto &f : fixups) {
1676 f.target, [&isnc](FModuleLike module) -> hw::InnerSymbolNamespace & {
1677 return isnc.get(module);
1679 assert(ref &&
"unable to resolve inner symbol target");
1683 TypeSwitch<Operation *, LogicalResult>(f.innerRefUser.getOperation())
1684 .Case<RWProbeOp>([ref](RWProbeOp op) {
1685 op.setTargetAttr(ref);
1688 .Default([](
auto *op) {
1689 return op->emitError(
"unknown inner-ref user requiring fixup");
1700 struct FIRStmtParser :
public FIRParser {
1701 explicit FIRStmtParser(Block &blockToInsertInto,
1702 FIRModuleContext &moduleContext,
1703 InnerSymFixups &innerSymFixups,
1704 const SymbolTable &circuitSymTbl,
FIRVersion version,
1705 SymbolRefAttr layerSym = {})
1706 : FIRParser(moduleContext.getConstants(), moduleContext.getLexer(),
1709 locationProcessor(this->builder), moduleContext(moduleContext),
1710 innerSymFixups(innerSymFixups), layerSym(layerSym),
1711 circuitSymTbl(circuitSymTbl) {
1712 builder.setInsertionPointToEnd(&blockToInsertInto);
1715 ParseResult parseSimpleStmt(
unsigned stmtIndent);
1716 ParseResult parseSimpleStmtBlock(
unsigned indent);
1719 ParseResult parseSimpleStmtImpl(
unsigned stmtIndent);
1722 void emitInvalidate(Value val,
Flow flow);
1728 void emitInvalidate(Value val) { emitInvalidate(val,
foldFlow(val)); }
1731 ParseResult parseOptionalInfo() {
1733 if (failed(parseOptionalInfoLocator(loc)))
1735 locationProcessor.setInfoLoc(loc);
1740 ParseResult parseExpImpl(Value &result,
const Twine &message,
1741 bool isLeadingStmt);
1742 ParseResult parseExp(Value &result,
const Twine &message) {
1743 return parseExpImpl(result, message,
false);
1745 ParseResult parseExpLeadingStmt(Value &result,
const Twine &message) {
1746 return parseExpImpl(result, message,
true);
1748 ParseResult parseEnumExp(Value &result);
1749 ParseResult parsePathExp(Value &result);
1750 ParseResult parseRefExp(Value &result,
const Twine &message);
1751 ParseResult parseStaticRefExp(Value &result,
const Twine &message);
1752 ParseResult parseRWProbeStaticRefExp(
FieldRef &refResult, Type &type,
1753 const Twine &message);
1756 ParseResult parseIntrinsic(Value &result,
bool isStatement);
1757 ParseResult parseIntrinsicStmt() {
1759 return parseIntrinsic(unused,
true);
1761 ParseResult parseIntrinsicExp(Value &result) {
1762 return parseIntrinsic(result,
false);
1764 ParseResult parseOptionalParams(ArrayAttr &resultParameters);
1766 template <
typename subop>
1767 FailureOr<Value> emitCachedSubAccess(Value base,
1768 ArrayRef<NamedAttribute> attrs,
1769 unsigned indexNo, SMLoc loc);
1770 ParseResult parseOptionalExpPostscript(Value &result,
1771 bool allowDynamic =
true);
1772 ParseResult parsePostFixFieldId(Value &result);
1773 ParseResult parsePostFixIntSubscript(Value &result);
1774 ParseResult parsePostFixDynamicSubscript(Value &result);
1775 ParseResult parsePrimExp(Value &result);
1776 ParseResult parseIntegerLiteralExp(Value &result);
1777 ParseResult parseListExp(Value &result);
1778 ParseResult parseListConcatExp(Value &result);
1780 std::optional<ParseResult> parseExpWithLeadingKeyword(
FIRToken keyword);
1783 ParseResult parseSubBlock(Block &blockToInsertInto,
unsigned indent,
1784 SymbolRefAttr layerSym);
1785 ParseResult parseAttach();
1786 ParseResult parseMemPort(MemDirAttr direction);
1787 ParseResult parsePrintf();
1788 ParseResult parseSkip();
1789 ParseResult parseStop();
1790 ParseResult parseAssert();
1791 ParseResult parseAssume();
1792 ParseResult parseCover();
1793 ParseResult parseWhen(
unsigned whenIndent);
1794 ParseResult parseMatch(
unsigned matchIndent);
1795 ParseResult parseRefDefine();
1796 ParseResult parseRefForce();
1797 ParseResult parseRefForceInitial();
1798 ParseResult parseRefRelease();
1799 ParseResult parseRefReleaseInitial();
1800 ParseResult parseRefRead(Value &result);
1801 ParseResult parseProbe(Value &result);
1802 ParseResult parsePropAssign();
1803 ParseResult parseRWProbe(Value &result);
1804 ParseResult parseLeadingExpStmt(Value lhs);
1805 ParseResult parseConnect();
1806 ParseResult parseInvalidate();
1807 ParseResult parseLayerBlockOrGroup(
unsigned indent);
1810 ParseResult parseInstance();
1811 ParseResult parseInstanceChoice();
1812 ParseResult parseObject();
1813 ParseResult parseCombMem();
1814 ParseResult parseSeqMem();
1815 ParseResult parseMem(
unsigned memIndent);
1816 ParseResult parseNode();
1817 ParseResult parseWire();
1818 ParseResult parseRegister(
unsigned regIndent);
1819 ParseResult parseRegisterWithReset();
1822 FModuleLike getReferencedModule(SMLoc loc, StringRef moduleName);
1825 ImplicitLocOpBuilder builder;
1826 LazyLocationListener locationProcessor;
1829 FIRModuleContext &moduleContext;
1832 InnerSymFixups &innerSymFixups;
1836 SymbolRefAttr layerSym;
1838 const SymbolTable &circuitSymTbl;
1845 void FIRStmtParser::emitInvalidate(Value val,
Flow flow) {
1846 auto tpe = type_dyn_cast<FIRRTLBaseType>(val.getType());
1853 auto props = tpe.getRecursiveTypeProperties();
1854 if (props.isPassive && !props.containsAnalog) {
1857 emitConnect(builder, val, builder.create<InvalidValueOp>(tpe));
1868 TypeSwitch<FIRRTLType>(tpe)
1869 .Case<BundleType>([&](
auto tpe) {
1870 for (
size_t i = 0, e = tpe.getNumElements(); i < e; ++i) {
1871 auto &subfield = moduleContext.getCachedSubaccess(val, i);
1873 OpBuilder::InsertionGuard guard(builder);
1874 builder.setInsertionPointAfterValue(val);
1875 subfield = builder.create<SubfieldOp>(val, i);
1877 emitInvalidate(subfield,
1878 tpe.getElement(i).isFlip ?
swapFlow(flow) : flow);
1881 .Case<FVectorType>([&](
auto tpe) {
1882 auto tpex = tpe.getElementType();
1883 for (
size_t i = 0, e = tpe.getNumElements(); i != e; ++i) {
1884 auto &subindex = moduleContext.getCachedSubaccess(val, i);
1886 OpBuilder::InsertionGuard guard(builder);
1887 builder.setInsertionPointAfterValue(val);
1888 subindex = builder.create<SubindexOp>(tpex, val, i);
1890 emitInvalidate(subindex, flow);
1918 ParseResult FIRStmtParser::parseExpImpl(Value &result,
const Twine &message,
1919 bool isLeadingStmt) {
1920 switch (getToken().getKind()) {
1923 #define TOK_LPKEYWORD_PRIM(SPELLING, CLASS, NUMOPERANDS) \
1924 case FIRToken::lp_##SPELLING:
1925 #include "FIRTokenKinds.def"
1926 if (parsePrimExp(result))
1930 case FIRToken::l_brace_bar:
1932 return emitError(
"unexpected enumeration as start of statement");
1933 if (parseEnumExp(result))
1936 case FIRToken::lp_read:
1938 return emitError(
"unexpected read() as start of statement");
1939 if (parseRefRead(result))
1942 case FIRToken::lp_probe:
1944 return emitError(
"unexpected probe() as start of statement");
1945 if (parseProbe(result))
1948 case FIRToken::lp_rwprobe:
1950 return emitError(
"unexpected rwprobe() as start of statement");
1951 if (parseRWProbe(result))
1955 case FIRToken::kw_UInt:
1956 case FIRToken::kw_SInt:
1957 if (parseIntegerLiteralExp(result))
1960 case FIRToken::kw_String: {
1961 if (requireFeature({3, 1, 0},
"Strings"))
1963 locationProcessor.setLoc(getToken().getLoc());
1964 consumeToken(FIRToken::kw_String);
1966 if (parseToken(FIRToken::l_paren,
"expected '(' in String expression") ||
1967 parseGetSpelling(spelling) ||
1968 parseToken(FIRToken::string,
1969 "expected string literal in String expression") ||
1970 parseToken(FIRToken::r_paren,
"expected ')' in String expression"))
1973 result = moduleContext.getCachedConstant<StringConstantOp>(
1974 builder, attr, builder.getType<StringType>(), attr);
1977 case FIRToken::kw_Integer: {
1978 if (requireFeature({3, 1, 0},
"Integers"))
1980 locationProcessor.setLoc(getToken().getLoc());
1981 consumeToken(FIRToken::kw_Integer);
1983 if (parseToken(FIRToken::l_paren,
"expected '(' in Integer expression") ||
1984 parseIntLit(value,
"expected integer literal in Integer expression") ||
1985 parseToken(FIRToken::r_paren,
"expected ')' in Integer expression"))
1987 APSInt apint(value,
false);
1988 result = moduleContext.getCachedConstant<FIntegerConstantOp>(
1990 builder.getType<FIntegerType>(), apint);
1993 case FIRToken::kw_Bool: {
1996 locationProcessor.setLoc(getToken().getLoc());
1997 consumeToken(FIRToken::kw_Bool);
1998 if (parseToken(FIRToken::l_paren,
"expected '(' in Bool expression"))
2001 if (consumeIf(FIRToken::kw_true))
2003 else if (consumeIf(FIRToken::kw_false))
2006 return emitError(
"expected true or false in Bool expression");
2007 if (parseToken(FIRToken::r_paren,
"expected ')' in Bool expression"))
2009 auto attr = builder.getBoolAttr(value);
2010 result = moduleContext.getCachedConstant<BoolConstantOp>(
2011 builder, attr, builder.getType<BoolType>(), value);
2014 case FIRToken::kw_Double: {
2017 locationProcessor.setLoc(getToken().getLoc());
2018 consumeToken(FIRToken::kw_Double);
2019 if (parseToken(FIRToken::l_paren,
"expected '(' in Double expression"))
2021 auto spelling = getTokenSpelling();
2022 if (parseToken(FIRToken::floatingpoint,
2023 "expected floating point in Double expression") ||
2024 parseToken(FIRToken::r_paren,
"expected ')' in Double expression"))
2029 if (!llvm::to_float(spelling, d))
2030 return emitError(
"invalid double");
2031 auto attr = builder.getF64FloatAttr(d);
2032 result = moduleContext.getCachedConstant<DoubleConstantOp>(
2033 builder, attr, builder.getType<DoubleType>(), attr);
2036 case FIRToken::kw_List: {
2040 return emitError(
"unexpected List<>() as start of statement");
2041 if (parseListExp(result))
2046 case FIRToken::lp_list_concat: {
2048 return emitError(
"unexpected list_create() as start of statement");
2050 parseListConcatExp(result))
2055 case FIRToken::lp_path:
2057 return emitError(
"unexpected path() as start of statement");
2058 if (requireFeature(
nextFIRVersion,
"paths") || parsePathExp(result))
2062 case FIRToken::lp_intrinsic:
2063 if (requireFeature({4, 0, 0},
"generic intrinsics") ||
2064 parseIntrinsicExp(result))
2070 case FIRToken::identifier:
2071 case FIRToken::literal_identifier:
2074 auto loc = getToken().getLoc();
2076 if (parseId(name, message) ||
2077 moduleContext.lookupSymbolEntry(symtabEntry, name, loc))
2081 if (!moduleContext.resolveSymbolEntry(result, symtabEntry, loc,
false))
2089 if (isLeadingStmt && consumeIf(FIRToken::kw_is)) {
2090 if (parseToken(FIRToken::kw_invalid,
"expected 'invalid'") ||
2091 parseOptionalInfo())
2094 locationProcessor.setLoc(loc);
2096 unsigned unbundledId = symtabEntry.get<
UnbundledID>() - 1;
2098 moduleContext.getUnbundledEntry(unbundledId);
2099 for (
auto elt : ubEntry)
2100 emitInvalidate(elt.second);
2108 StringRef fieldName;
2109 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
2110 parseFieldId(fieldName,
"expected field name") ||
2111 moduleContext.resolveSymbolEntry(result, symtabEntry, fieldName, loc))
2117 return parseOptionalExpPostscript(result);
2127 ParseResult FIRStmtParser::parseOptionalExpPostscript(Value &result,
2128 bool allowDynamic) {
2133 if (consumeIf(FIRToken::period)) {
2134 if (parsePostFixFieldId(result))
2141 if (consumeIf(FIRToken::l_square)) {
2142 if (getToken().isAny(FIRToken::integer, FIRToken::string)) {
2143 if (parsePostFixIntSubscript(result))
2148 return emitError(
"subaccess not allowed here");
2149 if (parsePostFixDynamicSubscript(result))
2159 template <
typename subop>
2161 FIRStmtParser::emitCachedSubAccess(Value base, ArrayRef<NamedAttribute> attrs,
2162 unsigned indexNo, SMLoc loc) {
2165 auto resultType = subop::inferReturnType({base}, attrs, {});
2168 (void)subop::inferReturnType({base}, attrs, translateLocation(loc));
2173 auto &value = moduleContext.getCachedSubaccess(base, indexNo);
2179 locationProcessor.setLoc(loc);
2180 OpBuilder::InsertionGuard guard(builder);
2181 builder.setInsertionPointAfterValue(base);
2182 auto op = builder.create<subop>(resultType, base, attrs);
2185 return value = op.getResult();
2192 ParseResult FIRStmtParser::parsePostFixFieldId(Value &result) {
2193 auto loc = getToken().getLoc();
2194 SmallVector<StringRef, 3> fields;
2195 if (parseFieldIdSeq(fields,
"expected field name"))
2197 for (
auto fieldName : fields) {
2198 std::optional<unsigned> indexV;
2199 auto type = result.getType();
2200 if (
auto refTy = type_dyn_cast<RefType>(type))
2201 type = refTy.getType();
2202 if (
auto bundle = type_dyn_cast<BundleType>(type))
2203 indexV = bundle.getElementIndex(fieldName);
2204 else if (
auto bundle = type_dyn_cast<OpenBundleType>(type))
2205 indexV = bundle.getElementIndex(fieldName);
2206 else if (
auto klass = type_dyn_cast<ClassType>(type))
2207 indexV = klass.getElementIndex(fieldName);
2209 return emitError(loc,
"subfield requires bundle or object operand ");
2211 return emitError(loc,
"unknown field '" + fieldName +
"' in type ")
2212 << result.getType();
2213 auto indexNo = *indexV;
2215 FailureOr<Value> subResult;
2216 if (type_isa<RefType>(result.getType())) {
2217 NamedAttribute attrs = {getConstants().indexIdentifier,
2218 builder.getI32IntegerAttr(indexNo)};
2219 subResult = emitCachedSubAccess<RefSubOp>(result, attrs, indexNo, loc);
2220 }
else if (type_isa<ClassType>(type)) {
2221 NamedAttribute attrs = {getConstants().indexIdentifier,
2222 builder.getI32IntegerAttr(indexNo)};
2224 emitCachedSubAccess<ObjectSubfieldOp>(result, attrs, indexNo, loc);
2226 NamedAttribute attrs = {getConstants().fieldIndexIdentifier,
2227 builder.getI32IntegerAttr(indexNo)};
2228 if (type_isa<BundleType>(type))
2230 emitCachedSubAccess<SubfieldOp>(result, attrs, indexNo, loc);
2233 emitCachedSubAccess<OpenSubfieldOp>(result, attrs, indexNo, loc);
2236 if (failed(subResult))
2238 result = *subResult;
2247 ParseResult FIRStmtParser::parsePostFixIntSubscript(Value &result) {
2248 auto loc = getToken().getLoc();
2250 if (parseIntLit(indexNo,
"expected index") ||
2251 parseToken(FIRToken::r_square,
"expected ']'"))
2255 return emitError(loc,
"invalid index specifier"), failure();
2261 NamedAttribute attrs = {getConstants().indexIdentifier,
2262 builder.getI32IntegerAttr(indexNo)};
2264 FailureOr<Value> subResult;
2265 if (type_isa<RefType>(result.getType()))
2266 subResult = emitCachedSubAccess<RefSubOp>(result, attrs, indexNo, loc);
2267 else if (type_isa<FVectorType>(result.getType()))
2268 subResult = emitCachedSubAccess<SubindexOp>(result, attrs, indexNo, loc);
2271 emitCachedSubAccess<OpenSubindexOp>(result, attrs, indexNo, loc);
2273 if (failed(subResult))
2275 result = *subResult;
2283 ParseResult FIRStmtParser::parsePostFixDynamicSubscript(Value &result) {
2284 auto loc = getToken().getLoc();
2286 if (parseExp(index,
"expected subscript index expression") ||
2287 parseToken(FIRToken::r_square,
"expected ']' in subscript"))
2291 auto indexType = type_dyn_cast<FIRRTLBaseType>(index.getType());
2293 return emitError(
"expected base type for index expression");
2294 indexType = indexType.getPassiveType();
2295 locationProcessor.setLoc(loc);
2299 auto resultType = SubaccessOp::inferReturnType({result, index}, {}, {});
2302 (void)SubaccessOp::inferReturnType({result, index}, {},
2303 translateLocation(loc));
2308 auto op = builder.create<SubaccessOp>(resultType, result, index);
2309 result = op.getResult();
2314 ParseResult FIRStmtParser::parsePrimExp(Value &result) {
2315 auto kind = getToken().getKind();
2316 auto loc = getToken().getLoc();
2320 SmallVector<Value, 3> operands;
2321 SmallVector<int64_t, 3> integers;
2323 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2325 if (getToken().isAny(FIRToken::integer, FIRToken::signed_integer,
2326 FIRToken::string)) {
2327 integers.push_back(0);
2328 return parseIntLit(integers.back(),
"expected integer");
2333 if (!integers.empty())
2334 return emitError(
"expected more integer constants"), failure();
2337 if (parseExp(operand,
"expected expression in primitive operand"))
2340 locationProcessor.setLoc(loc);
2342 operands.push_back(operand);
2348 locationProcessor.setLoc(loc);
2350 SmallVector<FIRRTLType, 3> opTypes;
2351 for (
auto v : operands)
2352 opTypes.push_back(type_cast<FIRRTLType>(v.getType()));
2354 unsigned numOperandsExpected;
2355 SmallVector<StringAttr, 2> attrNames;
2360 emitError(loc,
"primitive not supported yet");
2362 #define TOK_LPKEYWORD_PRIM(SPELLING, CLASS, NUMOPERANDS) \
2363 case FIRToken::lp_##SPELLING: \
2364 numOperandsExpected = NUMOPERANDS; \
2366 #include "FIRTokenKinds.def"
2373 case FIRToken::lp_bits:
2374 attrNames.push_back(getConstants().hiIdentifier);
2375 attrNames.push_back(getConstants().loIdentifier);
2377 case FIRToken::lp_head:
2378 case FIRToken::lp_pad:
2379 case FIRToken::lp_shl:
2380 case FIRToken::lp_shr:
2381 case FIRToken::lp_tail:
2382 attrNames.push_back(getConstants().amountIdentifier);
2384 case FIRToken::lp_integer_add:
2385 case FIRToken::lp_integer_mul:
2386 case FIRToken::lp_integer_shr:
2387 case FIRToken::lp_integer_shl:
2388 if (requireFeature({4, 0, 0},
"Integer arithmetic expressions", loc))
2393 if (operands.size() != numOperandsExpected) {
2394 assert(numOperandsExpected <= 3);
2395 static const char *numberName[] = {
"zero",
"one",
"two",
"three"};
2396 const char *optionalS = &
"s"[numOperandsExpected == 1];
2397 return emitError(loc,
"operation requires ")
2398 << numberName[numOperandsExpected] <<
" operand" << optionalS;
2401 if (integers.size() != attrNames.size()) {
2402 emitError(loc,
"expected ") << attrNames.size() <<
" constant arguments";
2406 NamedAttrList attrs;
2407 for (
size_t i = 0, e = attrNames.size(); i != e; ++i)
2408 attrs.append(attrNames[i], builder.getI32IntegerAttr(integers[i]));
2412 emitError(loc,
"primitive not supported yet");
2415 #define TOK_LPKEYWORD_PRIM(SPELLING, CLASS, NUMOPERANDS) \
2416 case FIRToken::lp_##SPELLING: { \
2417 auto resultTy = CLASS::inferReturnType(operands, attrs, {}); \
2420 (void)CLASS::validateAndInferReturnType(operands, attrs, \
2421 translateLocation(loc)); \
2424 result = builder.create<CLASS>(resultTy, operands, attrs); \
2427 #include "FIRTokenKinds.def"
2434 case FIRToken::lp_shr:
2437 if (version <
FIRVersion(4, 0, 0) && type_isa<UIntType>(result.getType()))
2438 result = builder.create<PadPrimOp>(result, 1);
2446 ParseResult FIRStmtParser::parseIntegerLiteralExp(Value &result) {
2447 bool isSigned = getToken().is(FIRToken::kw_SInt);
2448 auto loc = getToken().getLoc();
2454 if (parseOptionalWidth(
width) ||
2455 parseToken(FIRToken::l_paren,
"expected '(' in integer expression") ||
2456 parseIntLit(value,
"expected integer value") ||
2457 parseToken(FIRToken::r_paren,
"expected ')' in integer expression"))
2464 IntegerType::SignednessSemantics signedness =
2465 isSigned ? IntegerType::Signed : IntegerType::Unsigned;
2467 if (!value.isZero())
2468 return emitError(loc,
"zero bit constant must be zero");
2469 value = value.trunc(0);
2470 }
else if (
width != -1) {
2472 bool valueFits = isSigned ? value.isSignedIntN(
width) : value.isIntN(
width);
2474 return emitError(loc,
"initializer too wide for declared width");
2475 value = isSigned ? value.sextOrTrunc(
width) : value.zextOrTrunc(
width);
2480 auto attr = builder.getIntegerAttr(attrType, value);
2483 auto &entry = moduleContext.constantCache[{attr, type}];
2490 locationProcessor.setLoc(loc);
2491 result = moduleContext.getCachedConstant(builder, attr, type, attr);
2496 ParseResult FIRStmtParser::parseListExp(Value &result) {
2497 auto loc = getToken().getLoc();
2499 if (parseListType(type))
2501 auto listType = type_cast<ListType>(type);
2504 if (parseToken(FIRToken::l_paren,
"expected '(' in List expression"))
2507 SmallVector<Value, 3> operands;
2508 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2510 locationProcessor.setLoc(loc);
2511 if (parseExp(operand,
"expected expression in List expression"))
2515 if (!isa<AnyRefType>(elementType) ||
2516 !isa<ClassType>(operand.getType()))
2517 return emitError(loc,
"unexpected expression of type ")
2518 << operand.getType() <<
" in List expression of type "
2520 operand = builder.create<ObjectAnyRefCastOp>(operand);
2523 operands.push_back(operand);
2528 locationProcessor.setLoc(loc);
2529 result = builder.create<ListCreateOp>(listType, operands);
2534 ParseResult FIRStmtParser::parseListConcatExp(Value &result) {
2535 consumeToken(FIRToken::lp_list_concat);
2537 auto loc = getToken().getLoc();
2539 SmallVector<Value, 3> operands;
2540 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2542 locationProcessor.setLoc(loc);
2543 if (parseExp(operand,
"expected expression in List concat expression"))
2546 if (!type_isa<ListType>(operand.getType()))
2547 return emitError(loc,
"unexpected expression of type ")
2548 << operand.getType() <<
" in List concat expression";
2551 type = type_cast<ListType>(operand.getType());
2553 if (operand.getType() != type)
2554 return emitError(loc,
"unexpected expression of type ")
2555 << operand.getType() <<
" in List concat expression of type "
2558 operands.push_back(operand);
2563 if (operands.empty())
2564 return emitError(loc,
"need at least one List to concatenate");
2566 locationProcessor.setLoc(loc);
2567 result = builder.create<ListConcatOp>(type, operands);
2588 std::optional<ParseResult>
2589 FIRStmtParser::parseExpWithLeadingKeyword(
FIRToken keyword) {
2590 switch (getToken().getKind()) {
2593 return std::nullopt;
2595 case FIRToken::period:
2596 case FIRToken::l_square:
2597 case FIRToken::kw_is:
2598 case FIRToken::less_equal:
2604 auto loc = keyword.
getLoc();
2606 if (moduleContext.lookupSymbolEntry(symtabEntry, keyword.
getSpelling(), loc))
2607 return ParseResult(failure());
2613 if (moduleContext.resolveSymbolEntry(lhs, symtabEntry, loc,
false)) {
2616 if (!consumeIf(FIRToken::period))
2617 return ParseResult(failure());
2619 StringRef fieldName;
2620 if (parseFieldId(fieldName,
"expected field name") ||
2621 moduleContext.resolveSymbolEntry(lhs, symtabEntry, fieldName, loc))
2622 return ParseResult(failure());
2626 if (parseOptionalExpPostscript(lhs))
2627 return ParseResult(failure());
2629 return parseLeadingExpStmt(lhs);
2635 ParseResult FIRStmtParser::parseSimpleStmtBlock(
unsigned indent) {
2638 if (getToken().isAny(FIRToken::eof, FIRToken::error))
2641 auto subIndent = getIndentation();
2642 if (!subIndent.has_value())
2643 return emitError(
"expected statement to be on its own line"), failure();
2645 if (*subIndent <= indent)
2649 if (parseSimpleStmt(*subIndent))
2654 ParseResult FIRStmtParser::parseSimpleStmt(
unsigned stmtIndent) {
2655 locationProcessor.startStatement();
2656 auto result = parseSimpleStmtImpl(stmtIndent);
2657 locationProcessor.endStatement(*
this);
2678 ParseResult FIRStmtParser::parseSimpleStmtImpl(
unsigned stmtIndent) {
2679 auto kind = getToken().getKind();
2682 case FIRToken::kw_invalidate:
2683 case FIRToken::kw_connect:
2684 case FIRToken::kw_regreset:
2688 kind = FIRToken::identifier;
2695 case FIRToken::kw_attach:
2696 return parseAttach();
2697 case FIRToken::kw_infer:
2698 return parseMemPort(MemDirAttr::Infer);
2699 case FIRToken::kw_read:
2700 return parseMemPort(MemDirAttr::Read);
2701 case FIRToken::kw_write:
2702 return parseMemPort(MemDirAttr::Write);
2703 case FIRToken::kw_rdwr:
2704 return parseMemPort(MemDirAttr::ReadWrite);
2705 case FIRToken::kw_connect:
2706 return parseConnect();
2707 case FIRToken::kw_propassign:
2708 if (requireFeature({3, 1, 0},
"properties"))
2710 return parsePropAssign();
2711 case FIRToken::kw_invalidate:
2712 return parseInvalidate();
2713 case FIRToken::lp_printf:
2714 return parsePrintf();
2715 case FIRToken::kw_skip:
2717 case FIRToken::lp_stop:
2719 case FIRToken::lp_assert:
2720 return parseAssert();
2721 case FIRToken::lp_assume:
2722 return parseAssume();
2723 case FIRToken::lp_cover:
2724 return parseCover();
2725 case FIRToken::kw_when:
2726 return parseWhen(stmtIndent);
2727 case FIRToken::kw_match:
2728 return parseMatch(stmtIndent);
2729 case FIRToken::kw_define:
2730 return parseRefDefine();
2731 case FIRToken::lp_force:
2732 return parseRefForce();
2733 case FIRToken::lp_force_initial:
2734 return parseRefForceInitial();
2735 case FIRToken::lp_release:
2736 return parseRefRelease();
2737 case FIRToken::lp_release_initial:
2738 return parseRefReleaseInitial();
2739 case FIRToken::kw_group:
2740 if (requireFeature({3, 2, 0},
"optional groups") ||
2741 removedFeature({4, 0, 0},
"optional groups"))
2743 return parseLayerBlockOrGroup(stmtIndent);
2744 case FIRToken::kw_layerblock:
2745 if (requireFeature({4, 0, 0},
"layers"))
2747 return parseLayerBlockOrGroup(stmtIndent);
2748 case FIRToken::lp_intrinsic:
2749 if (requireFeature({4, 0, 0},
"generic intrinsics"))
2751 return parseIntrinsicStmt();
2755 if (parseExpLeadingStmt(lhs,
"unexpected token in module"))
2762 return parseLeadingExpStmt(lhs);
2766 case FIRToken::kw_inst:
2767 return parseInstance();
2768 case FIRToken::kw_instchoice:
2769 return parseInstanceChoice();
2770 case FIRToken::kw_object:
2771 return parseObject();
2772 case FIRToken::kw_cmem:
2773 return parseCombMem();
2774 case FIRToken::kw_smem:
2775 return parseSeqMem();
2776 case FIRToken::kw_mem:
2777 return parseMem(stmtIndent);
2778 case FIRToken::kw_node:
2780 case FIRToken::kw_wire:
2782 case FIRToken::kw_reg:
2783 return parseRegister(stmtIndent);
2784 case FIRToken::kw_regreset:
2785 return parseRegisterWithReset();
2789 ParseResult FIRStmtParser::parseSubBlock(Block &blockToInsertInto,
2791 SymbolRefAttr layerSym) {
2793 auto suiteScope = std::make_unique<FIRModuleContext::ContextScope>(
2794 moduleContext, &blockToInsertInto);
2799 UnbundledValueRestorer x(moduleContext.unbundledValues);
2803 auto subParser = std::make_unique<FIRStmtParser>(
2804 blockToInsertInto, moduleContext, innerSymFixups, circuitSymTbl, version,
2808 auto stmtIndent = getIndentation();
2811 if (!stmtIndent.has_value())
2812 return subParser->parseSimpleStmt(indent);
2814 if (*stmtIndent <= indent)
2815 return emitError(
"statement must be indented more than previous statement"),
2819 return subParser->parseSimpleStmtBlock(indent);
2823 ParseResult FIRStmtParser::parseAttach() {
2824 auto startTok = consumeToken(FIRToken::kw_attach);
2827 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2830 if (parseToken(FIRToken::l_paren,
"expected '(' after attach"))
2833 SmallVector<Value, 4> operands;
2834 operands.push_back({});
2835 if (parseExp(operands.back(),
"expected operand in attach"))
2838 while (consumeIf(FIRToken::comma)) {
2839 operands.push_back({});
2840 if (parseExp(operands.back(),
"expected operand in attach"))
2843 if (parseToken(FIRToken::r_paren,
"expected close paren"))
2846 if (parseOptionalInfo())
2849 locationProcessor.setLoc(startTok.getLoc());
2850 builder.create<AttachOp>(operands);
2857 ParseResult FIRStmtParser::parseMemPort(MemDirAttr direction) {
2858 auto startTok = consumeToken();
2859 auto startLoc = startTok.getLoc();
2863 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2869 Value memory, indexExp, clock;
2870 if (parseToken(FIRToken::kw_mport,
"expected 'mport' in memory port") ||
2871 parseId(
id,
"expected result name") ||
2872 parseToken(FIRToken::equal,
"expected '=' in memory port") ||
2873 parseId(memName,
"expected memory name") ||
2874 moduleContext.lookupSymbolEntry(memorySym, memName, startLoc) ||
2875 moduleContext.resolveSymbolEntry(memory, memorySym, startLoc) ||
2876 parseToken(FIRToken::l_square,
"expected '[' in memory port") ||
2877 parseExp(indexExp,
"expected index expression") ||
2878 parseToken(FIRToken::r_square,
"expected ']' in memory port") ||
2879 parseToken(FIRToken::comma,
"expected ','") ||
2880 parseExp(clock,
"expected clock expression") || parseOptionalInfo())
2883 auto memVType = type_dyn_cast<CMemoryType>(memory.getType());
2885 return emitError(startLoc,
2886 "memory port should have behavioral memory type");
2887 auto resultType = memVType.getElementType();
2889 ArrayAttr annotations = getConstants().emptyArrayAttr;
2890 locationProcessor.setLoc(startLoc);
2893 Value memoryPort, memoryData;
2895 OpBuilder::InsertionGuard guard(builder);
2896 builder.setInsertionPointAfterValue(memory);
2897 auto memoryPortOp = builder.create<MemoryPortOp>(
2900 memoryData = memoryPortOp.getResult(0);
2901 memoryPort = memoryPortOp.getResult(1);
2905 builder.create<MemoryPortAccessOp>(memoryPort, indexExp, clock);
2907 return moduleContext.addSymbolEntry(
id, memoryData, startLoc,
true);
2911 ParseResult FIRStmtParser::parsePrintf() {
2912 auto startTok = consumeToken(FIRToken::lp_printf);
2914 Value clock, condition;
2915 StringRef formatString;
2916 if (parseExp(clock,
"expected clock expression in printf") ||
2917 parseToken(FIRToken::comma,
"expected ','") ||
2918 parseExp(condition,
"expected condition in printf") ||
2919 parseToken(FIRToken::comma,
"expected ','") ||
2920 parseGetSpelling(formatString) ||
2921 parseToken(FIRToken::string,
"expected format string in printf"))
2924 SmallVector<Value, 4> operands;
2925 while (consumeIf(FIRToken::comma)) {
2926 operands.push_back({});
2927 if (parseExp(operands.back(),
"expected operand in printf"))
2930 if (parseToken(FIRToken::r_paren,
"expected ')'"))
2934 if (parseOptionalName(name))
2937 if (parseOptionalInfo())
2940 locationProcessor.setLoc(startTok.getLoc());
2943 builder.create<PrintFOp>(clock, condition,
2944 builder.getStringAttr(formatStrUnescaped), operands,
2950 ParseResult FIRStmtParser::parseSkip() {
2951 auto startTok = consumeToken(FIRToken::kw_skip);
2955 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
2958 if (parseOptionalInfo())
2961 locationProcessor.setLoc(startTok.getLoc());
2962 builder.create<SkipOp>();
2967 ParseResult FIRStmtParser::parseStop() {
2968 auto startTok = consumeToken(FIRToken::lp_stop);
2970 Value clock, condition;
2973 if (parseExp(clock,
"expected clock expression in 'stop'") ||
2974 parseToken(FIRToken::comma,
"expected ','") ||
2975 parseExp(condition,
"expected condition in 'stop'") ||
2976 parseToken(FIRToken::comma,
"expected ','") ||
2977 parseIntLit(exitCode,
"expected exit code in 'stop'") ||
2978 parseToken(FIRToken::r_paren,
"expected ')' in 'stop'") ||
2979 parseOptionalName(name) || parseOptionalInfo())
2982 locationProcessor.setLoc(startTok.getLoc());
2983 builder.create<StopOp>(clock, condition, builder.getI32IntegerAttr(exitCode),
2989 ParseResult FIRStmtParser::parseAssert() {
2990 auto startTok = consumeToken(FIRToken::lp_assert);
2992 Value clock, predicate, enable;
2993 StringRef formatString;
2995 if (parseExp(clock,
"expected clock expression in 'assert'") ||
2996 parseToken(FIRToken::comma,
"expected ','") ||
2997 parseExp(predicate,
"expected predicate in 'assert'") ||
2998 parseToken(FIRToken::comma,
"expected ','") ||
2999 parseExp(enable,
"expected enable in 'assert'") ||
3000 parseToken(FIRToken::comma,
"expected ','") ||
3001 parseGetSpelling(formatString) ||
3002 parseToken(FIRToken::string,
"expected format string in 'assert'"))
3005 SmallVector<Value, 4> operands;
3006 while (!consumeIf(FIRToken::r_paren)) {
3007 operands.push_back({});
3008 if (parseToken(FIRToken::comma,
"expected ','") ||
3009 parseExp(operands.back(),
"expected operand in 'assert'"))
3013 if (parseOptionalName(name) || parseOptionalInfo())
3016 locationProcessor.setLoc(startTok.getLoc());
3018 builder.create<AssertOp>(clock, predicate, enable, formatStrUnescaped,
3019 operands, name.getValue());
3024 ParseResult FIRStmtParser::parseAssume() {
3025 auto startTok = consumeToken(FIRToken::lp_assume);
3027 Value clock, predicate, enable;
3028 StringRef formatString;
3030 if (parseExp(clock,
"expected clock expression in 'assume'") ||
3031 parseToken(FIRToken::comma,
"expected ','") ||
3032 parseExp(predicate,
"expected predicate in 'assume'") ||
3033 parseToken(FIRToken::comma,
"expected ','") ||
3034 parseExp(enable,
"expected enable in 'assume'") ||
3035 parseToken(FIRToken::comma,
"expected ','") ||
3036 parseGetSpelling(formatString) ||
3037 parseToken(FIRToken::string,
"expected format string in 'assume'"))
3040 SmallVector<Value, 4> operands;
3041 while (!consumeIf(FIRToken::r_paren)) {
3042 operands.push_back({});
3043 if (parseToken(FIRToken::comma,
"expected ','") ||
3044 parseExp(operands.back(),
"expected operand in 'assume'"))
3048 if (parseOptionalName(name) || parseOptionalInfo())
3051 locationProcessor.setLoc(startTok.getLoc());
3053 builder.create<AssumeOp>(clock, predicate, enable, formatStrUnescaped,
3054 operands, name.getValue());
3059 ParseResult FIRStmtParser::parseCover() {
3060 auto startTok = consumeToken(FIRToken::lp_cover);
3062 Value clock, predicate, enable;
3065 if (parseExp(clock,
"expected clock expression in 'cover'") ||
3066 parseToken(FIRToken::comma,
"expected ','") ||
3067 parseExp(predicate,
"expected predicate in 'cover'") ||
3068 parseToken(FIRToken::comma,
"expected ','") ||
3069 parseExp(enable,
"expected enable in 'cover'") ||
3070 parseToken(FIRToken::comma,
"expected ','") ||
3071 parseGetSpelling(message) ||
3072 parseToken(FIRToken::string,
"expected message in 'cover'") ||
3073 parseToken(FIRToken::r_paren,
"expected ')' in 'cover'") ||
3074 parseOptionalName(name) || parseOptionalInfo())
3077 locationProcessor.setLoc(startTok.getLoc());
3079 builder.create<CoverOp>(clock, predicate, enable, messageUnescaped,
3080 ValueRange{}, name.getValue());
3086 ParseResult FIRStmtParser::parseWhen(
unsigned whenIndent) {
3087 auto startTok = consumeToken(FIRToken::kw_when);
3091 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3095 if (parseExp(condition,
"expected condition in 'when'") ||
3096 parseToken(FIRToken::colon,
"expected ':' in when") ||
3097 parseOptionalInfo())
3100 locationProcessor.setLoc(startTok.getLoc());
3102 auto whenStmt = builder.create<WhenOp>(condition,
false);
3105 if (parseSubBlock(whenStmt.getThenBlock(), whenIndent, layerSym))
3109 if (getToken().isNot(FIRToken::kw_else))
3114 auto elseIndent = getIndentation();
3115 if (elseIndent && *elseIndent < whenIndent)
3118 consumeToken(FIRToken::kw_else);
3121 whenStmt.createElseRegion();
3127 if (getToken().is(FIRToken::kw_when)) {
3129 auto subParser = std::make_unique<FIRStmtParser>(
3130 whenStmt.getElseBlock(), moduleContext, innerSymFixups, circuitSymTbl,
3133 return subParser->parseSimpleStmt(whenIndent);
3137 LocationAttr elseLoc;
3138 if (parseToken(FIRToken::colon,
"expected ':' after 'else'") ||
3139 parseOptionalInfoLocator(elseLoc) ||
3140 parseSubBlock(whenStmt.getElseBlock(), whenIndent, layerSym))
3149 ParseResult FIRStmtParser::parseEnumExp(Value &value) {
3150 auto startLoc = getToken().getLoc();
3151 locationProcessor.setLoc(startLoc);
3153 if (parseEnumType(type))
3157 auto enumType = type_dyn_cast<FEnumType>(type);
3159 return emitError(startLoc,
3160 "expected enumeration type in enumeration expression");
3163 if (parseToken(FIRToken::l_paren,
"expected '(' in enumeration expression") ||
3164 parseId(tag,
"expected enumeration tag"))
3168 if (consumeIf(FIRToken::r_paren)) {
3171 auto type =
IntType::get(builder.getContext(),
false, 0,
true);
3173 auto attr = builder.getIntegerAttr(attrType, APInt(0, 0,
false));
3174 input = builder.create<ConstantOp>(type, attr);
3177 if (parseToken(FIRToken::comma,
"expected ','") ||
3178 parseExp(input,
"expected expression in enumeration value") ||
3179 parseToken(FIRToken::r_paren,
"expected closing ')'"))
3183 value = builder.create<FEnumCreateOp>(enumType, tag, input);
3191 ParseResult FIRStmtParser::parseMatch(
unsigned matchIndent) {
3192 auto startTok = consumeToken(FIRToken::kw_match);
3194 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3198 if (parseExp(input,
"expected expression in 'match'") ||
3199 parseToken(FIRToken::colon,
"expected ':' in 'match'") ||
3200 parseOptionalInfo())
3203 auto enumType = type_dyn_cast<FEnumType>(input.getType());
3205 return mlir::emitError(
3207 "expected enumeration type for 'match' statement, but got ")
3210 locationProcessor.setLoc(startTok.getLoc());
3212 SmallVector<Attribute> tags;
3213 SmallVector<std::unique_ptr<Region>> regions;
3215 auto tagLoc = getToken().getLoc();
3218 auto caseIndent = getIndentation();
3219 if (!caseIndent || *caseIndent <= matchIndent)
3223 StringRef tagSpelling;
3224 if (parseId(tagSpelling,
"expected enumeration tag in match statement"))
3226 auto tagIndex = enumType.getElementIndex(tagSpelling);
3228 return emitError(tagLoc,
"tag ")
3229 << tagSpelling <<
" not a member of enumeration " << enumType;
3231 tags.push_back(tag);
3234 auto *caseBlock = ®ions.emplace_back(
new Region)->emplaceBlock();
3237 FIRModuleContext::ContextScope scope(moduleContext, caseBlock);
3242 UnbundledValueRestorer x(moduleContext.unbundledValues);
3245 if (consumeIf(FIRToken::l_paren)) {
3246 StringAttr identifier;
3247 if (parseId(identifier,
"expected identifier for 'case' binding"))
3251 auto dataType = enumType.getElementType(*tagIndex);
3252 caseBlock->addArgument(dataType, LocWithInfo(tagLoc,
this).getLoc());
3254 if (moduleContext.addSymbolEntry(identifier, caseBlock->getArgument(0),
3258 if (parseToken(FIRToken::r_paren,
"expected ')' in match statement case"))
3262 auto dataType =
IntType::get(builder.getContext(),
false, 0);
3263 caseBlock->addArgument(dataType, LocWithInfo(tagLoc,
this).getLoc());
3266 if (parseToken(FIRToken::colon,
"expected ':' in match statement case"))
3270 auto subParser = std::make_unique<FIRStmtParser>(
3271 *caseBlock, moduleContext, innerSymFixups, circuitSymTbl, version,
3273 if (subParser->parseSimpleStmtBlock(*caseIndent))
3277 builder.create<MatchOp>(input,
ArrayAttr::get(getContext(), tags), regions);
3283 ParseResult FIRStmtParser::parseRefExp(Value &result,
const Twine &message) {
3284 auto token = getToken().getKind();
3285 if (token == FIRToken::lp_probe)
3286 return parseProbe(result);
3287 if (token == FIRToken::lp_rwprobe)
3288 return parseRWProbe(result);
3293 return parseStaticRefExp(result, message);
3300 ParseResult FIRStmtParser::parseStaticRefExp(Value &result,
3301 const Twine &message) {
3302 auto parseIdOrInstance = [&]() -> ParseResult {
3304 auto loc = getToken().getLoc();
3306 if (parseId(
id, message) ||
3307 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
3311 if (!moduleContext.resolveSymbolEntry(result, symtabEntry, loc,
false))
3317 StringRef fieldName;
3319 parseToken(FIRToken::period,
"expected '.' in field reference") ||
3320 parseFieldId(fieldName,
"expected field name") ||
3321 moduleContext.resolveSymbolEntry(result, symtabEntry, fieldName, loc));
3323 return failure(parseIdOrInstance() ||
3324 parseOptionalExpPostscript(result,
false));
3335 ParseResult FIRStmtParser::parseRWProbeStaticRefExp(
FieldRef &refResult,
3337 const Twine &message) {
3338 auto loc = getToken().getLoc();
3342 if (parseId(
id, message) ||
3343 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
3355 if (
auto unbundledId = dyn_cast<UnbundledID>(symtabEntry)) {
3357 auto &ubEntry = moduleContext.getUnbundledEntry(unbundledId - 1);
3359 StringRef fieldName;
3360 auto loc = getToken().getLoc();
3361 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
3362 parseFieldId(fieldName,
"expected field name"))
3368 for (
auto &elt : ubEntry) {
3369 if (elt.first == fieldAttr) {
3372 auto &instResult = elt.second;
3375 auto *defining = instResult.getDefiningOp();
3377 if (isa<WireOp>(defining)) {
3378 result = instResult;
3383 auto type = instResult.getType();
3387 bool forceable =
static_cast<bool>(
3390 return emitError(loc,
"unable to force instance result of type ")
3394 auto annotations = getConstants().emptyArrayAttr;
3395 StringAttr sym = {};
3396 SmallString<64> name;
3397 (
id +
"_" + fieldName +
"_bounce").
toVector(name);
3398 locationProcessor.setLoc(loc);
3399 OpBuilder::InsertionGuard guard(builder);
3400 builder.setInsertionPoint(defining);
3401 auto bounce = builder.create<WireOp>(
3402 type, name, NameKindEnum::InterestingName, annotations, sym);
3403 auto bounceVal = bounce.getData();
3406 instResult.replaceAllUsesWith(bounceVal);
3409 builder.setInsertionPointAfter(defining);
3417 result = instResult = bounce.getDataRaw();
3423 emitError(loc,
"use of invalid field name '")
3424 << fieldName <<
"' on bundle value";
3429 result = symtabEntry.get<Value>();
3433 assert(isa<BlockArgument>(result) ||
3434 result.getDefiningOp<hw::InnerSymbolOpInterface>());
3440 type = result.getType();
3442 if (consumeIf(FIRToken::period)) {
3443 SmallVector<StringRef, 3> fields;
3444 if (parseFieldIdSeq(fields,
"expected field name"))
3446 for (
auto fieldName : fields) {
3447 if (
auto bundle = type_dyn_cast<BundleType>(type)) {
3448 if (
auto index = bundle.getElementIndex(fieldName)) {
3449 refResult = refResult.
getSubField(bundle.getFieldID(*index));
3450 type = bundle.getElementTypePreservingConst(*index);
3453 }
else if (
auto bundle = type_dyn_cast<OpenBundleType>(type)) {
3454 if (
auto index = bundle.getElementIndex(fieldName)) {
3455 refResult = refResult.
getSubField(bundle.getFieldID(*index));
3456 type = bundle.getElementTypePreservingConst(*index);
3460 return emitError(loc,
"subfield requires bundle operand")
3461 <<
"got " << type <<
"\n";
3463 return emitError(loc,
3464 "unknown field '" + fieldName +
"' in bundle type ")
3469 if (consumeIf(FIRToken::l_square)) {
3470 auto loc = getToken().
getLoc();
3472 if (parseIntLit(index,
"expected index") ||
3473 parseToken(FIRToken::r_square,
"expected ']'"))
3477 return emitError(loc,
"invalid index specifier");
3479 if (
auto vector = type_dyn_cast<FVectorType>(type)) {
3480 if ((
unsigned)index < vector.getNumElements()) {
3481 refResult = refResult.
getSubField(vector.getFieldID(index));
3482 type = vector.getElementTypePreservingConst();
3485 }
else if (
auto vector = type_dyn_cast<OpenVectorType>(type)) {
3486 if ((
unsigned)index < vector.getNumElements()) {
3487 refResult = refResult.
getSubField(vector.getFieldID(index));
3488 type = vector.getElementTypePreservingConst();
3492 return emitError(loc,
"subindex requires vector operand");
3494 return emitError(loc,
"out of range index '")
3495 << index <<
"' for vector type " << type;
3503 ParseResult FIRStmtParser::parseIntrinsic(Value &result,
bool isStatement) {
3504 auto startTok = consumeToken(FIRToken::lp_intrinsic);
3505 StringRef intrinsic;
3506 ArrayAttr parameters;
3509 if (parseId(intrinsic,
"expected intrinsic identifier") ||
3510 parseOptionalParams(parameters))
3513 if (consumeIf(FIRToken::colon)) {
3514 if (
parseType(type,
"expected intrinsic return type"))
3516 }
else if (!isStatement)
3517 return emitError(
"expected ':' in intrinsic expression");
3519 SmallVector<Value> operands;
3520 auto loc = startTok.getLoc();
3521 if (consumeIf(FIRToken::comma)) {
3522 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
3524 if (parseExp(operand,
"expected operand in intrinsic"))
3526 operands.push_back(operand);
3527 locationProcessor.setLoc(loc);
3532 if (parseToken(FIRToken::r_paren,
"expected ')' in intrinsic"))
3537 if (parseOptionalInfo())
3540 locationProcessor.setLoc(loc);
3542 auto op = builder.create<GenericIntrinsicOp>(
3543 type, builder.getStringAttr(intrinsic), operands, parameters);
3545 result = op.getResult();
3550 ParseResult FIRStmtParser::parseOptionalParams(ArrayAttr &resultParameters) {
3551 if (!consumeIf(FIRToken::less))
3554 SmallVector<Attribute, 8> parameters;
3555 SmallPtrSet<StringAttr, 8> seen;
3556 if (parseListUntil(FIRToken::greater, [&]() -> ParseResult {
3560 if (parseParameter(name, value, loc))
3562 if (!seen.insert(name).second)
3563 return emitError(loc,
"redefinition of parameter '" +
3564 name.getValue() +
"'");
3576 ParseResult FIRStmtParser::parsePathExp(Value &result) {
3577 auto startTok = consumeToken(FIRToken::lp_path);
3578 locationProcessor.setLoc(startTok.getLoc());
3580 if (parseGetSpelling(target) ||
3581 parseToken(FIRToken::string,
3582 "expected target string in path expression") ||
3583 parseToken(FIRToken::r_paren,
"expected ')' in path expression"))
3585 result = builder.create<UnresolvedPathOp>(
3591 ParseResult FIRStmtParser::parseRefDefine() {
3592 auto startTok = consumeToken(FIRToken::kw_define);
3595 if (parseStaticRefExp(target,
3596 "expected static reference expression in 'define'") ||
3597 parseToken(FIRToken::equal,
3598 "expected '=' after define reference expression") ||
3599 parseRefExp(src,
"expected reference expression in 'define'") ||
3600 parseOptionalInfo())
3604 if (!type_isa<RefType>(target.getType()))
3605 return emitError(startTok.getLoc(),
"expected reference-type expression in "
3606 "'define' target (LHS), got ")
3607 << target.getType();
3608 if (!type_isa<RefType>(src.getType()))
3609 return emitError(startTok.getLoc(),
"expected reference-type expression in "
3610 "'define' source (RHS), got ")
3615 if (isa_and_nonnull<RefSubOp>(target.getDefiningOp()))
3616 return emitError(startTok.getLoc(),
3617 "cannot define into a sub-element of a reference");
3619 locationProcessor.setLoc(startTok.getLoc());
3622 return emitError(startTok.getLoc(),
"cannot define reference of type ")
3623 << target.getType() <<
" with incompatible reference of type "
3633 ParseResult FIRStmtParser::parseRefRead(Value &result) {
3634 auto startTok = consumeToken(FIRToken::lp_read);
3637 if (parseRefExp(ref,
"expected reference expression in 'read'") ||
3638 parseToken(FIRToken::r_paren,
"expected ')' in 'read'"))
3641 locationProcessor.setLoc(startTok.getLoc());
3644 if (!type_isa<RefType>(ref.getType()))
3645 return emitError(startTok.getLoc(),
3646 "expected reference-type expression in 'read', got ")
3649 result = builder.create<RefResolveOp>(ref);
3655 ParseResult FIRStmtParser::parseProbe(Value &result) {
3656 auto startTok = consumeToken(FIRToken::lp_probe);
3659 if (parseStaticRefExp(staticRef,
3660 "expected static reference expression in 'probe'") ||
3661 parseToken(FIRToken::r_paren,
"expected ')' in 'probe'"))
3664 locationProcessor.setLoc(startTok.getLoc());
3667 if (!type_isa<FIRRTLBaseType>(staticRef.getType()))
3668 return emitError(startTok.getLoc(),
3669 "expected base-type expression in 'probe', got ")
3670 << staticRef.getType();
3674 if (isa_and_nonnull<MemOp, CombMemOp, SeqMemOp, MemoryPortOp,
3675 MemoryDebugPortOp, MemoryPortAccessOp>(
3676 staticRef.getDefiningOp()))
3677 return emitError(startTok.getLoc(),
"cannot probe memories or their ports");
3679 result = builder.create<RefSendOp>(staticRef);
3685 ParseResult FIRStmtParser::parseRWProbe(Value &result) {
3686 auto startTok = consumeToken(FIRToken::lp_rwprobe);
3689 Type parsedTargetType;
3690 if (parseRWProbeStaticRefExp(
3691 staticRef, parsedTargetType,
3692 "expected static reference expression in 'rwprobe'") ||
3693 parseToken(FIRToken::r_paren,
"expected ')' in 'rwprobe'"))
3696 locationProcessor.setLoc(startTok.getLoc());
3702 auto targetType = type_dyn_cast<FIRRTLBaseType>(parsedTargetType);
3704 return emitError(startTok.getLoc(),
3705 "expected base-type expression in 'rwprobe', got ")
3706 << parsedTargetType;
3709 auto *definingOp = root.getDefiningOp();
3711 if (isa_and_nonnull<MemOp, CombMemOp, SeqMemOp, MemoryPortOp,
3712 MemoryDebugPortOp, MemoryPortAccessOp>(definingOp))
3713 return emitError(startTok.getLoc(),
"cannot probe memories or their ports");
3717 return emitError(startTok.getLoc(),
"cannot force target of type ")
3721 auto op = builder.create<RWProbeOp>(forceableType,
3722 getConstants().placeholderInnerRef);
3729 ParseResult FIRStmtParser::parseRefForce() {
3730 auto startTok = consumeToken(FIRToken::lp_force);
3732 Value clock, pred, dest, src;
3733 if (parseExp(clock,
"expected clock expression in force") ||
3734 parseToken(FIRToken::comma,
"expected ','") ||
3735 parseExp(pred,
"expected predicate expression in force") ||
3736 parseToken(FIRToken::comma,
"expected ','") ||
3737 parseRefExp(dest,
"expected destination reference expression in force") ||
3738 parseToken(FIRToken::comma,
"expected ','") ||
3739 parseExp(src,
"expected source expression in force") ||
3740 parseToken(FIRToken::r_paren,
"expected ')' in force") ||
3741 parseOptionalInfo())
3745 auto ref = type_dyn_cast<RefType>(dest.getType());
3746 if (!ref || !ref.getForceable())
3749 "expected rwprobe-type expression for force destination, got ")
3751 auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(src.getType());
3753 return emitError(startTok.getLoc(),
3754 "expected base-type for force source, got ")
3756 if (!srcBaseType.isPassive())
3757 return emitError(startTok.getLoc(),
3758 "expected passive value for force source, got ")
3761 locationProcessor.setLoc(startTok.getLoc());
3764 auto noConstSrcType = srcBaseType.getAllConstDroppedType();
3765 if (noConstSrcType != ref.getType()) {
3767 auto compatibleRWProbe =
RefType::get(noConstSrcType,
true, ref.getLayer());
3769 dest = builder.create<RefCastOp>(compatibleRWProbe, dest);
3771 return emitError(startTok.getLoc(),
"incompatible force source of type ")
3772 << src.getType() <<
" cannot target destination "
3776 builder.create<RefForceOp>(clock, pred, dest, src);
3782 ParseResult FIRStmtParser::parseRefForceInitial() {
3783 auto startTok = consumeToken(FIRToken::lp_force_initial);
3787 dest,
"expected destination reference expression in force_initial") ||
3788 parseToken(FIRToken::comma,
"expected ','") ||
3789 parseExp(src,
"expected source expression in force_initial") ||
3790 parseToken(FIRToken::r_paren,
"expected ')' in force_initial") ||
3791 parseOptionalInfo())
3795 auto ref = type_dyn_cast<RefType>(dest.getType());
3796 if (!ref || !ref.getForceable())
3797 return emitError(startTok.getLoc(),
"expected rwprobe-type expression for "
3798 "force_initial destination, got ")
3800 auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(src.getType());
3802 return emitError(startTok.getLoc(),
3803 "expected base-type expression for force_initial "
3806 if (!srcBaseType.isPassive())
3807 return emitError(startTok.getLoc(),
3808 "expected passive value for force_initial source, got ")
3811 locationProcessor.setLoc(startTok.getLoc());
3814 auto noConstSrcType = srcBaseType.getAllConstDroppedType();
3815 if (noConstSrcType != ref.getType()) {
3817 auto compatibleRWProbe =
RefType::get(noConstSrcType,
true, ref.getLayer());
3819 dest = builder.create<RefCastOp>(compatibleRWProbe, dest);
3821 return emitError(startTok.getLoc(),
3822 "incompatible force_initial source of type ")
3823 << src.getType() <<
" cannot target destination "
3827 auto value = APInt::getAllOnes(1);
3830 value.getBitWidth(),
3831 IntegerType::Unsigned),
3833 auto pred = moduleContext.getCachedConstant(builder, attr, type, attr);
3834 builder.create<RefForceInitialOp>(pred, dest, src);
3840 ParseResult FIRStmtParser::parseRefRelease() {
3841 auto startTok = consumeToken(FIRToken::lp_release);
3843 Value clock, pred, dest;
3844 if (parseExp(clock,
"expected clock expression in release") ||
3845 parseToken(FIRToken::comma,
"expected ','") ||
3846 parseExp(pred,
"expected predicate expression in release") ||
3847 parseToken(FIRToken::comma,
"expected ','") ||
3849 "expected destination reference expression in release") ||
3850 parseToken(FIRToken::r_paren,
"expected ')' in release") ||
3851 parseOptionalInfo())
3855 if (
auto ref = type_dyn_cast<RefType>(dest.getType());
3856 !ref || !ref.getForceable())
3859 "expected rwprobe-type expression for release destination, got ")
3862 locationProcessor.setLoc(startTok.getLoc());
3864 builder.create<RefReleaseOp>(clock, pred, dest);
3870 ParseResult FIRStmtParser::parseRefReleaseInitial() {
3871 auto startTok = consumeToken(FIRToken::lp_release_initial);
3876 "expected destination reference expression in release_initial") ||
3877 parseToken(FIRToken::r_paren,
"expected ')' in release_initial") ||
3878 parseOptionalInfo())
3882 if (
auto ref = type_dyn_cast<RefType>(dest.getType());
3883 !ref || !ref.getForceable())
3884 return emitError(startTok.getLoc(),
"expected rwprobe-type expression for "
3885 "release_initial destination, got ")
3888 locationProcessor.setLoc(startTok.getLoc());
3890 auto value = APInt::getAllOnes(1);
3893 value.getBitWidth(),
3894 IntegerType::Unsigned),
3896 auto pred = moduleContext.getCachedConstant(builder, attr, type, attr);
3897 builder.create<RefReleaseInitialOp>(pred, dest);
3903 ParseResult FIRStmtParser::parseConnect() {
3904 auto startTok = consumeToken(FIRToken::kw_connect);
3905 auto loc = startTok.getLoc();
3908 if (parseExp(lhs,
"expected connect expression") ||
3909 parseToken(FIRToken::comma,
"expected ','") ||
3910 parseExp(rhs,
"expected connect expression") || parseOptionalInfo())
3913 auto lhsType = type_dyn_cast<FIRRTLBaseType>(lhs.getType());
3914 auto rhsType = type_dyn_cast<FIRRTLBaseType>(rhs.getType());
3915 if (!lhsType || !rhsType)
3916 return emitError(loc,
"cannot connect reference or property types");
3918 if (lhsType.containsReference() || rhsType.containsReference())
3919 return emitError(loc,
"cannot connect types containing references");
3922 return emitError(loc,
"cannot connect non-equivalent type ")
3923 << rhsType <<
" to " << lhsType;
3925 locationProcessor.setLoc(loc);
3931 ParseResult FIRStmtParser::parsePropAssign() {
3932 auto startTok = consumeToken(FIRToken::kw_propassign);
3933 auto loc = startTok.getLoc();
3936 if (parseExp(lhs,
"expected propassign expression") ||
3937 parseToken(FIRToken::comma,
"expected ','") ||
3938 parseExp(rhs,
"expected propassign expression") || parseOptionalInfo())
3941 auto lhsType = type_dyn_cast<PropertyType>(lhs.getType());
3942 auto rhsType = type_dyn_cast<PropertyType>(rhs.getType());
3943 if (!lhsType || !rhsType)
3944 return emitError(loc,
"can only propassign property types");
3945 locationProcessor.setLoc(loc);
3946 if (lhsType != rhsType) {
3948 if (isa<AnyRefType>(lhsType) && isa<ClassType>(rhsType))
3949 rhs = builder.create<ObjectAnyRefCastOp>(rhs);
3951 return emitError(loc,
"cannot propassign non-equivalent type ")
3952 << rhsType <<
" to " << lhsType;
3954 builder.create<PropAssignOp>(lhs, rhs);
3959 ParseResult FIRStmtParser::parseInvalidate() {
3960 auto startTok = consumeToken(FIRToken::kw_invalidate);
3963 if (parseExp(lhs,
"expected connect expression") || parseOptionalInfo())
3966 locationProcessor.setLoc(startTok.getLoc());
3967 emitInvalidate(lhs);
3971 ParseResult FIRStmtParser::parseLayerBlockOrGroup(
unsigned indent) {
3973 auto startTok = consumeToken();
3974 assert(startTok.isAny(FIRToken::kw_layerblock, FIRToken::kw_group) &&
3975 "consumed an unexpected token");
3976 auto loc = startTok.getLoc();
3979 if (parseId(
id,
"expected layer identifer") ||
3980 parseToken(FIRToken::colon,
"expected ':' at end of layer block") ||
3981 parseOptionalInfo())
3984 locationProcessor.setLoc(loc);
3986 StringRef rootLayer;
3987 SmallVector<FlatSymbolRefAttr> nestedLayers;
3991 rootLayer = layerSym.getRootReference();
3992 auto nestedRefs = layerSym.getNestedReferences();
3993 nestedLayers.append(nestedRefs.begin(), nestedRefs.end());
3997 auto layerBlockOp = builder.create<LayerBlockOp>(
3999 layerBlockOp->getRegion(0).push_back(
new Block());
4001 if (getIndentation() > indent)
4002 if (parseSubBlock(layerBlockOp.getRegion().front(), indent,
4003 layerBlockOp.getLayerName()))
4011 ParseResult FIRStmtParser::parseLeadingExpStmt(Value lhs) {
4012 auto loc = getToken().getLoc();
4015 if (consumeIf(FIRToken::kw_is)) {
4016 if (parseToken(FIRToken::kw_invalid,
"expected 'invalid'") ||
4017 parseOptionalInfo())
4020 locationProcessor.setLoc(loc);
4021 emitInvalidate(lhs);
4025 if (parseToken(FIRToken::less_equal,
"expected '<=' in statement"))
4029 if (parseExp(rhs,
"unexpected token in statement") || parseOptionalInfo())
4032 locationProcessor.setLoc(loc);
4034 auto lhsType = type_dyn_cast<FIRRTLBaseType>(lhs.getType());
4035 auto rhsType = type_dyn_cast<FIRRTLBaseType>(rhs.getType());
4036 if (!lhsType || !rhsType)
4037 return emitError(loc,
"cannot connect reference or property types");
4039 if (lhsType.containsReference() || rhsType.containsReference())
4040 return emitError(loc,
"cannot connect types containing references");
4043 return emitError(loc,
"cannot connect non-equivalent type ")
4044 << rhsType <<
" to " << lhsType;
4053 ParseResult FIRStmtParser::parseInstance() {
4054 auto startTok = consumeToken(FIRToken::kw_inst);
4058 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4062 StringRef moduleName;
4063 if (parseId(
id,
"expected instance name") ||
4064 parseToken(FIRToken::kw_of,
"expected 'of' in instance") ||
4065 parseId(moduleName,
"expected module name") || parseOptionalInfo())
4068 locationProcessor.setLoc(startTok.getLoc());
4071 auto referencedModule = getReferencedModule(startTok.getLoc(), moduleName);
4072 if (!referencedModule)
4075 SmallVector<PortInfo> modulePorts = referencedModule.getPorts();
4077 auto annotations = getConstants().emptyArrayAttr;
4078 SmallVector<Attribute, 4> portAnnotations(modulePorts.size(), annotations);
4080 hw::InnerSymAttr sym = {};
4081 auto result = builder.create<InstanceOp>(
4082 referencedModule, id, NameKindEnum::InterestingName,
4083 annotations.getValue(), portAnnotations,
false, sym);
4089 unbundledValueEntry.reserve(modulePorts.size());
4090 for (
size_t i = 0, e = modulePorts.size(); i != e; ++i)
4091 unbundledValueEntry.push_back({modulePorts[i].name, result.getResult(i)});
4095 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4096 auto entryId =
UnbundledID(moduleContext.unbundledValues.size());
4097 return moduleContext.addSymbolEntry(
id, entryId, startTok.getLoc());
4102 ParseResult FIRStmtParser::parseInstanceChoice() {
4103 auto startTok = consumeToken(FIRToken::kw_instchoice);
4104 SMLoc loc = startTok.getLoc();
4107 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4110 if (requireFeature({4, 0, 0},
"option groups/instance choices"))
4114 StringRef defaultModuleName;
4115 StringRef optionGroupName;
4116 if (parseId(
id,
"expected instance name") ||
4117 parseToken(FIRToken::kw_of,
"expected 'of' in instance") ||
4118 parseId(defaultModuleName,
"expected module name") ||
4119 parseToken(FIRToken::comma,
"expected ','") ||
4120 parseId(optionGroupName,
"expected option group name") ||
4121 parseToken(FIRToken::colon,
"expected ':' after instchoice") ||
4122 parseOptionalInfo())
4125 locationProcessor.setLoc(startTok.getLoc());
4129 auto defaultModule = getReferencedModule(loc, defaultModuleName);
4133 SmallVector<PortInfo> modulePorts = defaultModule.getPorts();
4136 auto optionGroup = circuitSymTbl.lookup<OptionOp>(optionGroupName);
4138 return emitError(loc,
4139 "use of undefined option group '" + optionGroupName +
"'");
4141 auto baseIndent = getIndentation();
4142 SmallVector<std::pair<OptionCaseOp, FModuleLike>> caseModules;
4143 while (getIndentation() == baseIndent) {
4145 StringRef caseModuleName;
4146 if (parseId(caseId,
"expected a case identifier") ||
4147 parseToken(FIRToken::equal_greater,
4148 "expected '=> in instance choice definition") ||
4149 parseId(caseModuleName,
"expected module name"))
4152 auto caseModule = getReferencedModule(loc, caseModuleName);
4156 for (
const auto &[defaultPort, casePort] :
4157 llvm::zip(modulePorts, caseModule.getPorts())) {
4158 if (defaultPort.name != casePort.name)
4159 return emitError(loc,
"instance case module port '")
4160 << casePort.name.getValue()
4161 <<
"' does not match the default module port '"
4162 << defaultPort.name.getValue() <<
"'";
4163 if (defaultPort.type != casePort.type)
4164 return emitError(loc,
"instance case port '")
4165 << casePort.name.getValue()
4166 <<
"' type does not match the default module port";
4170 dyn_cast_or_null<OptionCaseOp>(optionGroup.lookupSymbol(caseId));
4172 return emitError(loc,
"use of undefined option case '" + caseId +
"'");
4173 caseModules.emplace_back(optionCase, caseModule);
4176 auto annotations = getConstants().emptyArrayAttr;
4177 SmallVector<Attribute, 4> portAnnotations(modulePorts.size(), annotations);
4181 auto result = builder.create<InstanceChoiceOp>(
4182 defaultModule, caseModules, id, NameKindEnum::InterestingName,
4183 annotations.getValue(), portAnnotations, sym);
4187 unbundledValueEntry.reserve(modulePorts.size());
4188 for (
size_t i = 0, e = modulePorts.size(); i != e; ++i)
4189 unbundledValueEntry.push_back({modulePorts[i].name, result.getResult(i)});
4191 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4192 auto entryId =
UnbundledID(moduleContext.unbundledValues.size());
4193 return moduleContext.addSymbolEntry(
id, entryId, startTok.getLoc());
4196 FModuleLike FIRStmtParser::getReferencedModule(SMLoc loc,
4197 StringRef moduleName) {
4198 auto referencedModule = circuitSymTbl.lookup<FModuleLike>(moduleName);
4199 if (!referencedModule) {
4201 "use of undefined module name '" + moduleName +
"' in instance");
4204 if (isa<ClassOp /* ClassLike */>(referencedModule)) {
4205 emitError(loc,
"cannot create instance of class '" + moduleName +
4206 "', did you mean object?");
4209 return referencedModule;
4213 ParseResult FIRStmtParser::parseObject() {
4214 auto startTok = consumeToken(FIRToken::kw_object);
4218 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4225 StringRef className;
4226 if (parseId(
id,
"expected object name") ||
4227 parseToken(FIRToken::kw_of,
"expected 'of' in object") ||
4228 parseId(className,
"expected class name") || parseOptionalInfo())
4231 locationProcessor.setLoc(startTok.getLoc());
4234 const auto &classMap = getConstants().classMap;
4235 auto lookup = classMap.find(className);
4236 if (lookup == classMap.end())
4237 return emitError(startTok.getLoc(),
"use of undefined class name '" +
4238 className +
"' in object");
4239 auto referencedClass = lookup->getSecond();
4240 auto result = builder.create<ObjectOp>(referencedClass, id);
4241 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4245 ParseResult FIRStmtParser::parseCombMem() {
4247 auto startTok = consumeToken(FIRToken::kw_cmem);
4251 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4256 if (parseId(
id,
"expected cmem name") ||
4257 parseToken(FIRToken::colon,
"expected ':' in cmem") ||
4258 parseType(type,
"expected cmem type") || parseOptionalInfo())
4261 locationProcessor.setLoc(startTok.getLoc());
4264 auto vectorType = type_dyn_cast<FVectorType>(type);
4266 return emitError(
"cmem requires vector type");
4268 auto annotations = getConstants().emptyArrayAttr;
4269 StringAttr sym = {};
4270 auto result = builder.create<CombMemOp>(
4271 vectorType.getElementType(), vectorType.getNumElements(), id,
4272 NameKindEnum::InterestingName, annotations, sym);
4273 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4277 ParseResult FIRStmtParser::parseSeqMem() {
4279 auto startTok = consumeToken(FIRToken::kw_smem);
4283 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4288 RUWAttr ruw = RUWAttr::Undefined;
4290 if (parseId(
id,
"expected smem name") ||
4291 parseToken(FIRToken::colon,
"expected ':' in smem") ||
4295 if (consumeIf(FIRToken::comma)) {
4300 if (parseOptionalInfo()) {
4304 locationProcessor.setLoc(startTok.getLoc());
4307 auto vectorType = type_dyn_cast<FVectorType>(type);
4309 return emitError(
"smem requires vector type");
4311 auto annotations = getConstants().emptyArrayAttr;
4312 StringAttr sym = {};
4313 auto result = builder.create<SeqMemOp>(
4314 vectorType.getElementType(), vectorType.getNumElements(), ruw, id,
4315 NameKindEnum::InterestingName, annotations, sym);
4316 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4328 ParseResult FIRStmtParser::parseMem(
unsigned memIndent) {
4329 auto startTok = consumeToken(FIRToken::kw_mem);
4333 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4337 if (parseId(
id,
"expected mem name") ||
4338 parseToken(FIRToken::colon,
"expected ':' in mem") || parseOptionalInfo())
4342 int64_t depth = -1, readLatency = -1, writeLatency = -1;
4343 RUWAttr ruw = RUWAttr::Undefined;
4345 SmallVector<std::pair<StringAttr, Type>, 4> ports;
4349 auto nextIndent = getIndentation();
4350 if (!nextIndent || *nextIndent <= memIndent)
4353 auto spelling = getTokenSpelling();
4354 if (parseToken(FIRToken::identifier,
"unexpected token in 'mem'") ||
4355 parseToken(FIRToken::equal_greater,
"expected '=>' in 'mem'"))
4358 if (spelling ==
"data-type") {
4360 return emitError(
"'mem' type specified multiple times"), failure();
4362 if (
parseType(type,
"expected type in data-type declaration"))
4366 if (spelling ==
"depth") {
4367 if (parseIntLit(depth,
"expected integer in depth specification"))
4371 if (spelling ==
"read-latency") {
4372 if (parseIntLit(readLatency,
"expected integer latency"))
4376 if (spelling ==
"write-latency") {
4377 if (parseIntLit(writeLatency,
"expected integer latency"))
4381 if (spelling ==
"read-under-write") {
4382 if (getToken().isNot(FIRToken::kw_old, FIRToken::kw_new,
4383 FIRToken::kw_undefined))
4384 return emitError(
"expected specifier"), failure();
4386 if (parseOptionalRUW(ruw))
4391 MemOp::PortKind portKind;
4392 if (spelling ==
"reader")
4393 portKind = MemOp::PortKind::Read;
4394 else if (spelling ==
"writer")
4395 portKind = MemOp::PortKind::Write;
4396 else if (spelling ==
"readwriter")
4397 portKind = MemOp::PortKind::ReadWrite;
4399 return emitError(
"unexpected field in 'mem' declaration"), failure();
4402 if (parseId(portName,
"expected port name"))
4404 auto baseType = type_dyn_cast<FIRRTLBaseType>(type);
4406 return emitError(
"unexpected type, must be base type");
4407 ports.push_back({builder.getStringAttr(portName),
4408 MemOp::getTypeForPort(depth, baseType, portKind)});
4410 while (!getIndentation().has_value()) {
4411 if (parseId(portName,
"expected port name"))
4413 ports.push_back({builder.getStringAttr(portName),
4414 MemOp::getTypeForPort(depth, baseType, portKind)});
4425 llvm::array_pod_sort(ports.begin(), ports.end(),
4426 [](
const std::pair<StringAttr, Type> *lhs,
4427 const std::pair<StringAttr, Type> *rhs) ->
int {
4428 return lhs->first.getValue().compare(
4429 rhs->first.getValue());
4432 auto annotations = getConstants().emptyArrayAttr;
4433 SmallVector<Attribute, 4> resultNames;
4434 SmallVector<Type, 4> resultTypes;
4435 SmallVector<Attribute, 4> resultAnnotations;
4436 for (
auto p : ports) {
4437 resultNames.push_back(p.first);
4438 resultTypes.push_back(p.second);
4439 resultAnnotations.push_back(annotations);
4442 locationProcessor.setLoc(startTok.getLoc());
4444 auto result = builder.create<MemOp>(
4445 resultTypes, readLatency, writeLatency, depth, ruw,
4446 builder.getArrayAttr(resultNames), id, NameKindEnum::InterestingName,
4447 annotations, builder.getArrayAttr(resultAnnotations), hw::InnerSymAttr(),
4448 MemoryInitAttr(), StringAttr());
4451 unbundledValueEntry.reserve(result.getNumResults());
4452 for (
size_t i = 0, e = result.getNumResults(); i != e; ++i)
4453 unbundledValueEntry.push_back({resultNames[i], result.getResult(i)});
4455 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
4456 auto entryID =
UnbundledID(moduleContext.unbundledValues.size());
4457 return moduleContext.addSymbolEntry(
id, entryID, startTok.getLoc());
4461 ParseResult FIRStmtParser::parseNode() {
4462 auto startTok = consumeToken(FIRToken::kw_node);
4466 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4471 if (parseId(
id,
"expected node name") ||
4472 parseToken(FIRToken::equal,
"expected '=' in node") ||
4473 parseExp(initializer,
"expected expression for node") ||
4474 parseOptionalInfo())
4477 locationProcessor.setLoc(startTok.getLoc());
4489 auto initializerType = type_cast<FIRRTLType>(initializer.getType());
4490 auto initializerBaseType =
4491 type_dyn_cast<FIRRTLBaseType>(initializer.getType());
4492 if (type_isa<AnalogType>(initializerType) ||
4493 !(initializerBaseType && initializerBaseType.isPassive())) {
4494 emitError(startTok.getLoc())
4495 <<
"Node cannot be analog and must be passive or passive under a flip "
4496 << initializer.getType();
4500 auto annotations = getConstants().emptyArrayAttr;
4501 StringAttr sym = {};
4503 auto result = builder.create<NodeOp>(
4504 initializer, id, NameKindEnum::InterestingName, annotations, sym);
4505 return moduleContext.addSymbolEntry(
id, result.getResult(),
4510 ParseResult FIRStmtParser::parseWire() {
4511 auto startTok = consumeToken(FIRToken::kw_wire);
4515 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4520 if (parseId(
id,
"expected wire name") ||
4521 parseToken(FIRToken::colon,
"expected ':' in wire") ||
4522 parseType(type,
"expected wire type") || parseOptionalInfo())
4525 locationProcessor.setLoc(startTok.getLoc());
4527 auto annotations = getConstants().emptyArrayAttr;
4528 StringAttr sym = {};
4531 auto namekind = isa<PropertyType, RefType>(type)
4532 ? NameKindEnum::DroppableName
4533 : NameKindEnum::InterestingName;
4535 auto result = builder.create<WireOp>(type, id, namekind, annotations, sym);
4536 return moduleContext.addSymbolEntry(
id, result.getResult(),
4550 ParseResult FIRStmtParser::parseRegister(
unsigned regIndent) {
4551 auto startTok = consumeToken(FIRToken::kw_reg);
4555 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4564 if (parseId(
id,
"expected reg name") ||
4565 parseToken(FIRToken::colon,
"expected ':' in reg") ||
4567 parseToken(FIRToken::comma,
"expected ','") ||
4568 parseExp(clock,
"expected expression for register clock"))
4571 if (!type_isa<FIRRTLBaseType>(type))
4572 return emitError(startTok.getLoc(),
"register must have base type");
4575 Value resetSignal, resetValue;
4576 if (consumeIf(FIRToken::kw_with)) {
4577 if (parseToken(FIRToken::colon,
"expected ':' in reg"))
4585 bool hasExtraLParen = consumeIf(FIRToken::l_paren);
4587 auto indent = getIndentation();
4588 if (!indent || *indent <= regIndent)
4589 if (!hasExtraLParen)
4590 return emitError(
"expected indented reset specifier in reg"), failure();
4592 if (parseToken(FIRToken::kw_reset,
"expected 'reset' in reg") ||
4593 parseToken(FIRToken::equal_greater,
"expected => in reset specifier") ||
4594 parseToken(FIRToken::l_paren,
"expected '(' in reset specifier") ||
4595 parseExp(resetSignal,
"expected expression for reset signal") ||
4596 parseToken(FIRToken::comma,
"expected ','"))
4604 if (getTokenSpelling() ==
id) {
4606 if (parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4608 resetSignal = Value();
4610 if (parseExp(resetValue,
"expected expression for reset value") ||
4611 parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4615 if (hasExtraLParen &&
4616 parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
4622 if (parseOptionalInfo())
4625 locationProcessor.setLoc(startTok.getLoc());
4627 ArrayAttr annotations = getConstants().emptyArrayAttr;
4629 StringAttr sym = {};
4633 .create<RegResetOp>(type, clock, resetSignal, resetValue, id,
4634 NameKindEnum::InterestingName, annotations, sym)
4638 .create<RegOp>(type, clock, id, NameKindEnum::InterestingName,
4641 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4649 ParseResult FIRStmtParser::parseRegisterWithReset() {
4650 auto startTok = consumeToken(FIRToken::kw_regreset);
4654 Value clock, resetSignal, resetValue;
4656 if (parseId(
id,
"expected reg name") ||
4657 parseToken(FIRToken::colon,
"expected ':' in reg") ||
4659 parseToken(FIRToken::comma,
"expected ','") ||
4660 parseExp(clock,
"expected expression for register clock") ||
4661 parseToken(FIRToken::comma,
"expected ','") ||
4662 parseExp(resetSignal,
"expected expression for register reset") ||
4663 parseToken(FIRToken::comma,
"expected ','") ||
4664 parseExp(resetValue,
"expected expression for register reset value") ||
4665 parseOptionalInfo())
4668 if (!type_isa<FIRRTLBaseType>(type))
4669 return emitError(startTok.getLoc(),
"register must have base type");
4671 locationProcessor.setLoc(startTok.getLoc());
4675 .create<RegResetOp>(type, clock, resetSignal, resetValue, id,
4676 NameKindEnum::InterestingName,
4677 getConstants().emptyArrayAttr, StringAttr{})
4680 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
4690 struct FIRCircuitParser :
public FIRParser {
4691 explicit FIRCircuitParser(SharedParserConstants &state,
FIRLexer &lexer,
4693 : FIRParser(state, lexer, version), mlirModule(mlirModule) {}
4696 parseCircuit(SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBuf,
4697 SmallVectorImpl<const llvm::MemoryBuffer *> &omirBuf,
4698 mlir::TimingScope &ts);
4703 ParseResult importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
4704 SmallVectorImpl<Attribute> &attrs);
4708 ParseResult importOMIR(CircuitOp circuit, SMLoc loc, StringRef annotationStr,
4709 SmallVectorImpl<Attribute> &attrs);
4711 ParseResult parseToplevelDefinition(CircuitOp circuit,
unsigned indent);
4713 ParseResult parseClass(CircuitOp circuit,
unsigned indent);
4714 ParseResult parseExtClass(CircuitOp circuit,
unsigned indent);
4715 ParseResult parseExtModule(CircuitOp circuit,
unsigned indent);
4716 ParseResult parseIntModule(CircuitOp circuit,
unsigned indent);
4717 ParseResult parseModule(CircuitOp circuit,
bool isPublic,
unsigned indent);
4718 ParseResult parseFormal(CircuitOp circuit,
unsigned indent);
4720 ParseResult parseLayerName(SymbolRefAttr &result);
4721 ParseResult parseOptionalEnabledLayers(ArrayAttr &result);
4722 ParseResult
parsePortList(SmallVectorImpl<PortInfo> &resultPorts,
4723 SmallVectorImpl<SMLoc> &resultPortLocs,
4726 ParseResult parseRefList(ArrayRef<PortInfo> portList,
4727 ArrayAttr &internalPathsResult);
4729 ParseResult skipToModuleEnd(
unsigned indent);
4731 ParseResult parseTypeDecl();
4733 ParseResult parseOptionDecl(CircuitOp circuit);
4735 ParseResult parseLayer(CircuitOp circuit);
4737 struct DeferredModuleToParse {
4738 FModuleLike moduleOp;
4739 SmallVector<SMLoc> portLocs;
4744 ParseResult parseModuleBody(
const SymbolTable &circuitSymTbl,
4745 DeferredModuleToParse &deferredModule,
4746 InnerSymFixups &fixups);
4748 SmallVector<DeferredModuleToParse, 0> deferredModules;
4750 SmallVector<InnerSymFixups, 0> moduleFixups;
4752 hw::InnerSymbolNamespaceCollection innerSymbolNamespaces;
4754 ModuleOp mlirModule;
4759 FIRCircuitParser::importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
4760 SmallVectorImpl<Attribute> &attrs) {
4762 auto annotations = json::parse(annotationsStr);
4763 if (
auto err = annotations.takeError()) {
4764 handleAllErrors(std::move(err), [&](
const json::ParseError &a) {
4765 auto diag = emitError(loc,
"Failed to parse JSON Annotations");
4766 diag.attachNote() << a.message();
4771 json::Path::Root root;
4772 llvm::StringMap<ArrayAttr> thisAnnotationMap;
4775 auto diag = emitError(loc,
"Invalid/unsupported annotation format");
4776 std::string jsonErrorMessage =
4777 "See inline comments for problem area in JSON:\n";
4778 llvm::raw_string_ostream s(jsonErrorMessage);
4779 root.printErrorContext(annotations.get(), s);
4780 diag.attachNote() << jsonErrorMessage;
4787 ParseResult FIRCircuitParser::importOMIR(CircuitOp circuit, SMLoc loc,
4788 StringRef annotationsStr,
4789 SmallVectorImpl<Attribute> &annos) {
4791 auto annotations = json::parse(annotationsStr);
4792 if (
auto err = annotations.takeError()) {
4793 handleAllErrors(std::move(err), [&](
const json::ParseError &a) {
4794 auto diag = emitError(loc,
"Failed to parse OMIR file");
4795 diag.attachNote() << a.message();
4800 json::Path::Root root;
4801 if (!
fromOMIRJSON(annotations.get(), annos, root, circuit.getContext())) {
4802 auto diag = emitError(loc,
"Invalid/unsupported OMIR format");
4803 std::string jsonErrorMessage =
4804 "See inline comments for problem area in JSON:\n";
4805 llvm::raw_string_ostream s(jsonErrorMessage);
4806 root.printErrorContext(annotations.get(), s);
4807 diag.attachNote() << jsonErrorMessage;
4814 ParseResult FIRCircuitParser::parseLayerName(SymbolRefAttr &result) {
4815 auto *context = getContext();
4816 SmallVector<StringRef> strings;
4819 if (parseId(name,
"expected layer name"))
4821 strings.push_back(name);
4822 }
while (consumeIf(FIRToken::period));
4824 SmallVector<FlatSymbolRefAttr> nested;
4825 nested.reserve(strings.size() - 1);
4826 for (
unsigned i = 1, e = strings.size(); i < e; ++i)
4833 ParseResult FIRCircuitParser::parseOptionalEnabledLayers(ArrayAttr &result) {
4834 if (getToken().getKind() != FIRToken::kw_enablelayer) {
4839 if (requireFeature({4, 0, 0},
"modules with layers enabled"))
4842 SmallVector<Attribute> layers;
4844 SymbolRefAttr layer;
4846 if (parseLayerName(layer))
4848 layers.push_back(layer);
4849 }
while (getToken().getKind() == FIRToken::kw_enablelayer);
4860 SmallVectorImpl<SMLoc> &resultPortLocs,
4863 while (getToken().isAny(FIRToken::kw_input, FIRToken::kw_output) &&
4865 getIndentation() > indent) {
4871 auto backtrackState = getLexer().getCursor();
4873 bool isOutput = getToken().is(FIRToken::kw_output);
4878 if (!getToken().isAny(FIRToken::identifier, FIRToken::literal_identifier) &&
4879 !getToken().isKeyword()) {
4880 backtrackState.restore(getLexer());
4886 LocWithInfo info(getToken().getLoc(),
this);
4887 if (parseId(name,
"expected port name") ||
4888 parseToken(FIRToken::colon,
"expected ':' in port definition") ||
4889 parseType(type,
"expected a type in port declaration") ||
4890 info.parseOptionalInfo())
4893 StringAttr innerSym = {};
4894 resultPorts.push_back(
4895 {name, type,
direction::get(isOutput), innerSym, info.getLoc()});
4896 resultPortLocs.push_back(info.getFIRLoc());
4901 for (
auto portAndLoc : llvm::zip(resultPorts, resultPortLocs)) {
4902 PortInfo &port = std::get<0>(portAndLoc);
4903 auto &entry = portIds[port.
name];
4904 if (!entry.isValid()) {
4905 entry = std::get<1>(portAndLoc);
4909 emitError(std::get<1>(portAndLoc),
4910 "redefinition of name '" + port.
getName() +
"'")
4911 .attachNote(translateLocation(entry))
4912 <<
"previous definition here";
4921 ParseResult FIRCircuitParser::parseRefList(ArrayRef<PortInfo> portList,
4922 ArrayAttr &internalPathsResult) {
4923 struct RefStatementInfo {
4925 InternalPathAttr resolvedPath;
4929 SmallVector<RefStatementInfo> refStatements;
4930 SmallPtrSet<StringAttr, 8> seenNames;
4931 SmallPtrSet<StringAttr, 8> seenRefs;
4934 if (getToken().is(FIRToken::kw_ref) &&
4935 removedFeature({4, 0, 0},
"ref statements"))
4939 while (consumeIf(FIRToken::kw_ref)) {
4940 auto loc = getToken().getLoc();
4944 if (parseId(refName,
"expected ref name"))
4946 if (consumeIf(FIRToken::period) || consumeIf(FIRToken::l_square))
4948 loc,
"ref statements for aggregate elements not yet supported");
4949 if (parseToken(FIRToken::kw_is,
"expected 'is' in ref statement"))
4952 if (!seenRefs.insert(refName).second)
4953 return emitError(loc,
"duplicate ref statement for '" + refName.strref() +
4956 auto kind = getToken().getKind();
4957 if (kind != FIRToken::string)
4958 return emitError(loc,
"expected string in ref statement");
4962 consumeToken(FIRToken::string);
4964 refStatements.push_back(RefStatementInfo{refName, resolved, loc});
4968 SmallVector<Attribute> internalPaths(portList.size(),
4971 llvm::SmallBitVector usedRefs(refStatements.size());
4972 size_t matchedPaths = 0;
4973 for (
auto [idx, port] : llvm::enumerate(portList)) {
4974 if (!type_isa<RefType>(port.
type))
4980 return mlir::emitError(
4982 "references in ports must be output on extmodule and intmodule");
4984 llvm::find_if(refStatements, [pname = port.
name](
const auto &r) {
4985 return r.refName == pname;
4988 if (refStmtIt == refStatements.end()) {
4989 if (!refStatements.empty())
4990 return mlir::emitError(port.
loc,
"no ref statement found for ref port ")
4995 usedRefs.set(std::distance(refStatements.begin(), refStmtIt));
4996 internalPaths[idx] = refStmtIt->resolvedPath;
5000 if (!refStatements.empty() && matchedPaths != refStatements.size()) {
5001 assert(matchedPaths < refStatements.size());
5003 auto idx = usedRefs.find_first_unset();
5005 return emitError(refStatements[idx].loc,
"unused ref statement");
5009 internalPathsResult =
ArrayAttr::get(getContext(), internalPaths);
5015 ParseResult FIRCircuitParser::skipToModuleEnd(
unsigned indent) {
5017 switch (getToken().getKind()) {
5021 case FIRToken::error:
5025 case FIRToken::kw_class:
5026 case FIRToken::kw_declgroup:
5027 case FIRToken::kw_extclass:
5028 case FIRToken::kw_extmodule:
5029 case FIRToken::kw_intmodule:
5030 case FIRToken::kw_formal:
5031 case FIRToken::kw_module:
5032 case FIRToken::kw_public:
5033 case FIRToken::kw_layer:
5034 case FIRToken::kw_option:
5035 case FIRToken::kw_type:
5039 if (getIndentation() == indent)
5052 SmallVector<Attribute, 8> parameters;
5053 SmallPtrSet<StringAttr, 8> seen;
5054 while (consumeIf(FIRToken::kw_parameter)) {
5058 if (parseParameter(name, value, loc))
5060 if (!seen.insert(name).second)
5061 return emitError(loc,
5062 "redefinition of parameter '" + name.getValue() +
"'");
5070 ParseResult FIRCircuitParser::parseClass(CircuitOp circuit,
unsigned indent) {
5072 SmallVector<PortInfo, 8> portList;
5073 SmallVector<SMLoc> portLocs;
5074 LocWithInfo info(getToken().getLoc(),
this);
5079 consumeToken(FIRToken::kw_class);
5080 if (parseId(name,
"expected class name") ||
5081 parseToken(FIRToken::colon,
"expected ':' in class definition") ||
5082 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5085 if (name == circuit.getName())
5086 return mlir::emitError(info.getLoc(),
5087 "class cannot be the top of a circuit");
5089 for (
auto &portInfo : portList)
5090 if (!isa<PropertyType>(portInfo.type))
5091 return mlir::emitError(portInfo.loc,
5092 "ports on classes must be properties");
5095 auto builder = circuit.getBodyBuilder();
5096 auto classOp = builder.create<ClassOp>(info.getLoc(), name, portList);
5097 classOp.setPrivate();
5098 deferredModules.emplace_back(
5099 DeferredModuleToParse{classOp, portLocs, getLexer().getCursor(), indent});
5102 getConstants().classMap[name.getValue()] = classOp;
5103 return skipToModuleEnd(indent);
5107 ParseResult FIRCircuitParser::parseExtClass(CircuitOp circuit,
5110 SmallVector<PortInfo, 8> portList;
5111 SmallVector<SMLoc> portLocs;
5112 LocWithInfo info(getToken().getLoc(),
this);
5117 consumeToken(FIRToken::kw_extclass);
5118 if (parseId(name,
"expected extclass name") ||
5119 parseToken(FIRToken::colon,
"expected ':' in extclass definition") ||
5120 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5123 if (name == circuit.getName())
5124 return mlir::emitError(info.getLoc(),
5125 "extclass cannot be the top of a circuit");
5127 for (
auto &portInfo : portList)
5128 if (!isa<PropertyType>(portInfo.type))
5129 return mlir::emitError(portInfo.loc,
5130 "ports on extclasses must be properties");
5133 auto builder = circuit.getBodyBuilder();
5134 auto extClassOp = builder.create<ExtClassOp>(info.getLoc(), name, portList);
5137 getConstants().classMap[name.getValue()] = extClassOp;
5138 return skipToModuleEnd(indent);
5145 ParseResult FIRCircuitParser::parseExtModule(CircuitOp circuit,
5149 SmallVector<PortInfo, 8> portList;
5150 SmallVector<SMLoc> portLocs;
5151 LocWithInfo info(getToken().getLoc(),
this);
5152 consumeToken(FIRToken::kw_extmodule);
5153 if (parseId(name,
"expected extmodule name") ||
5154 parseOptionalEnabledLayers(layers) ||
5155 parseToken(FIRToken::colon,
"expected ':' in extmodule definition") ||
5156 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5160 if (consumeIf(FIRToken::kw_defname)) {
5161 if (parseToken(FIRToken::equal,
"expected '=' in defname") ||
5162 parseId(defName,
"expected defname name"))
5166 ArrayAttr parameters;
5167 ArrayAttr internalPaths;
5172 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
5173 if (
auto ftype = type_dyn_cast<FIRRTLType>(pi.type)) {
5174 if (ftype.hasUninferredWidth())
5175 return emitError(loc,
"extmodule port must have known width");
5180 auto builder = circuit.getBodyBuilder();
5181 auto isMainModule = (name == circuit.getName());
5183 (isMainModule && getConstants().options.scalarizePublicModules) ||
5184 getConstants().options.scalarizeExtModules
5185 ? Convention::Scalarized
5186 : Convention::Internal;
5189 auto extModuleOp = builder.create<FExtModuleOp>(
5190 info.getLoc(), name, conventionAttr, portList, defName, annotations,
5191 parameters, internalPaths, layers);
5192 auto visibility = isMainModule ? SymbolTable::Visibility::Public
5193 : SymbolTable::Visibility::Private;
5194 SymbolTable::setSymbolVisibility(extModuleOp, visibility);
5202 ParseResult FIRCircuitParser::parseIntModule(CircuitOp circuit,
5207 SmallVector<PortInfo, 8> portList;
5208 SmallVector<SMLoc> portLocs;
5209 LocWithInfo info(getToken().getLoc(),
this);
5210 consumeToken(FIRToken::kw_intmodule);
5211 if (parseId(name,
"expected intmodule name") ||
5212 parseOptionalEnabledLayers(layers) ||
5213 parseToken(FIRToken::colon,
"expected ':' in intmodule definition") ||
5214 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent) ||
5215 parseToken(FIRToken::kw_intrinsic,
"expected 'intrinsic'") ||
5216 parseToken(FIRToken::equal,
"expected '=' in intrinsic") ||
5217 parseId(intName,
"expected intrinsic name"))
5220 ArrayAttr parameters;
5221 ArrayAttr internalPaths;
5225 ArrayAttr annotations = getConstants().emptyArrayAttr;
5226 auto builder = circuit.getBodyBuilder();
5228 .create<FIntModuleOp>(info.getLoc(), name, portList, intName, annotations,
5229 parameters, internalPaths, layers)
5235 ParseResult FIRCircuitParser::parseModule(CircuitOp circuit,
bool isPublic,
5238 SmallVector<PortInfo, 8> portList;
5239 SmallVector<SMLoc> portLocs;
5241 auto modLoc = getToken().getLoc();
5242 LocWithInfo info(modLoc,
this);
5243 consumeToken(FIRToken::kw_module);
5244 if (parseId(name,
"expected module name") ||
5245 parseOptionalEnabledLayers(layers) ||
5246 parseToken(FIRToken::colon,
"expected ':' in module definition") ||
5247 info.parseOptionalInfo() ||
parsePortList(portList, portLocs, indent))
5251 if (name == circuit.getName()) {
5252 if (!isPublic && removedFeature({4, 0, 0},
"private main modules", modLoc))
5257 if (isPublic && version >=
FIRVersion{4, 0, 0}) {
5258 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
5259 if (
auto ftype = type_dyn_cast<FIRRTLType>(pi.type)) {
5260 if (ftype.hasUninferredWidth())
5261 return emitError(loc,
"public module port must have known width");
5262 if (ftype.hasUninferredReset())
5263 return emitError(loc,
5264 "public module port must have concrete reset type");
5269 ArrayAttr annotations = getConstants().emptyArrayAttr;
5270 auto convention = Convention::Internal;
5271 if (isPublic && getConstants().options.scalarizePublicModules)
5272 convention = Convention::Scalarized;
5273 if (!isPublic && getConstants().options.scalarizeInternalModules)
5274 convention = Convention::Scalarized;
5276 auto builder = circuit.getBodyBuilder();
5277 auto moduleOp = builder.create<FModuleOp>(info.getLoc(), name, conventionAttr,
5278 portList, annotations, layers);
5280 auto visibility = isPublic ? SymbolTable::Visibility::Public
5281 : SymbolTable::Visibility::Private;
5282 SymbolTable::setSymbolVisibility(moduleOp, visibility);
5286 deferredModules.emplace_back(DeferredModuleToParse{
5287 moduleOp, portLocs, getLexer().getCursor(), indent});
5289 if (skipToModuleEnd(indent))
5294 ParseResult FIRCircuitParser::parseFormal(CircuitOp circuit,
unsigned indent) {
5295 consumeToken(FIRToken::kw_formal);
5296 StringRef id, moduleName, boundSpelling;
5298 LocWithInfo info(getToken().getLoc(),
this);
5301 if (parseId(
id,
"expected a formal test name") ||
5302 parseToken(FIRToken::kw_of,
5303 "expected keyword 'of' after formal test name") ||
5304 parseId(moduleName,
"expected the name of a module") ||
5305 parseToken(FIRToken::comma,
"expected ','") ||
5306 parseGetSpelling(boundSpelling) ||
5307 parseToken(FIRToken::identifier,
5308 "expected parameter 'bound' after ','") ||
5309 parseToken(FIRToken::equal,
"expected '=' after 'bound'") ||
5310 parseIntLit(bound,
"expected integer in bound specification") ||
5311 info.parseOptionalInfo())
5315 if (boundSpelling !=
"bound" || bound <= 0)
5316 return emitError(
"Invalid parameter given to formal test: ")
5317 << boundSpelling <<
" = " << bound,
5321 auto builder = circuit.getBodyBuilder();
5322 builder.create<firrtl::FormalOp>(info.getLoc(), id, moduleName, bound);
5327 ParseResult FIRCircuitParser::parseToplevelDefinition(CircuitOp circuit,
5329 switch (getToken().getKind()) {
5330 case FIRToken::kw_class:
5331 return parseClass(circuit, indent);
5332 case FIRToken::kw_declgroup:
5333 if (requireFeature({3, 2, 0},
"optional groups") ||
5334 removedFeature({4, 0, 0},
"optional groups"))
5336 return parseLayer(circuit);
5337 case FIRToken::kw_extclass:
5338 return parseExtClass(circuit, indent);
5339 case FIRToken::kw_extmodule:
5340 return parseExtModule(circuit, indent);
5341 case FIRToken::kw_formal:
5342 if (requireFeature({4, 0, 0},
"inline formal tests"))
5344 return parseFormal(circuit, indent);
5345 case FIRToken::kw_intmodule:
5346 if (removedFeature({4, 0, 0},
"intrinsic modules"))
5348 return parseIntModule(circuit, indent);
5349 case FIRToken::kw_layer:
5350 if (requireFeature({4, 0, 0},
"layers"))
5352 return parseLayer(circuit);
5353 case FIRToken::kw_module:
5354 return parseModule(circuit,
false, indent);
5355 case FIRToken::kw_public:
5356 if (requireFeature({4, 0, 0},
"public modules"))
5359 if (getToken().getKind() == FIRToken::kw_module)
5360 return parseModule(circuit,
true, indent);
5361 return emitError(getToken().getLoc(),
"only modules may be public");
5362 case FIRToken::kw_type:
5363 return parseTypeDecl();
5364 case FIRToken::kw_option:
5365 if (requireFeature({4, 0, 0},
"option groups/instance choices"))
5367 return parseOptionDecl(circuit);
5369 return emitError(getToken().getLoc(),
"unknown toplevel definition");
5374 ParseResult FIRCircuitParser::parseTypeDecl() {
5378 auto loc = getToken().getLoc();
5380 if (getToken().isKeyword())
5381 return emitError(loc) <<
"cannot use keyword '" << getToken().getSpelling()
5382 <<
"' for type alias name";
5384 if (parseId(
id,
"expected type name") ||
5385 parseToken(FIRToken::equal,
"expected '=' in type decl") ||
5391 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type))
5395 <<
"type alias for non-base type " << type
5396 <<
" is currently not supported. Type alias is stripped immediately";
5398 if (!getConstants().aliasMap.insert({id, type}).second)
5399 return emitError(loc) <<
"type alias `" << name.getValue()
5400 <<
"` is already defined";
5405 ParseResult FIRCircuitParser::parseOptionDecl(CircuitOp circuit) {
5408 auto loc = getToken().getLoc();
5410 LocWithInfo info(getToken().getLoc(),
this);
5411 if (parseId(
id,
"expected an option group name") ||
5412 parseToken(FIRToken::colon,
5413 "expected ':' after option group definition") ||
5414 info.parseOptionalInfo())
5417 auto builder = OpBuilder::atBlockEnd(circuit.getBodyBlock());
5418 auto optionOp = builder.create<OptionOp>(info.getLoc(), id);
5419 auto *block =
new Block;
5420 optionOp.getBody().push_back(block);
5421 builder.setInsertionPointToEnd(block);
5423 auto baseIndent = getIndentation();
5425 while (getIndentation() == baseIndent) {
5427 LocWithInfo caseInfo(getToken().getLoc(),
this);
5428 if (parseId(
id,
"expected an option case ID") ||
5429 caseInfo.parseOptionalInfo())
5432 if (!cases.insert(
id).second)
5433 return emitError(loc)
5434 <<
"duplicate option case definition '" <<
id <<
"'";
5436 builder.create<OptionCaseOp>(caseInfo.getLoc(), id);
5443 ParseResult FIRCircuitParser::parseLayer(CircuitOp circuit) {
5444 auto baseIndent = getIndentation();
5447 SmallVector<std::pair<std::optional<unsigned>, LayerOp>> layerStack;
5450 auto parseOne = [&](
Block *block) -> ParseResult {
5451 auto indent = getIndentation();
5452 StringRef id, convention;
5453 LocWithInfo info(getToken().getLoc(),
this);
5455 if (parseId(
id,
"expected layer name") ||
5456 parseToken(FIRToken::comma,
"expected ','") ||
5457 parseGetSpelling(convention))
5460 auto layerConvention = symbolizeLayerConvention(convention);
5461 if (!layerConvention) {
5462 emitError() <<
"unknown convention '" << convention
5463 <<
"' (did you misspell it?)";
5468 hw::OutputFileAttr outputDir;
5469 if (consumeIf(FIRToken::comma)) {
5470 if (getToken().getKind() == FIRToken::string) {
5471 auto text = getToken().getStringValue();
5473 return emitError() <<
"output directory must not be blank";
5474 outputDir = hw::OutputFileAttr::getAsDirectory(getContext(), text);
5475 consumeToken(FIRToken::string);
5479 if (parseToken(FIRToken::colon,
"expected ':' after layer definition") ||
5480 info.parseOptionalInfo())
5482 auto builder = OpBuilder::atBlockEnd(block);
5484 auto layerOp = builder.create<LayerOp>(info.getLoc(), id, *layerConvention);
5485 layerOp->getRegion(0).push_back(
new Block());
5487 layerOp->setAttr(
"output_file", outputDir);
5488 layerStack.push_back({indent, layerOp});
5492 if (parseOne(circuit.getBodyBlock()))
5496 while (getIndentation() > baseIndent) {
5497 switch (getToken().getKind()) {
5498 case FIRToken::kw_declgroup:
5499 case FIRToken::kw_layer: {
5502 while (layerStack.back().first >= getIndentation())
5503 layerStack.pop_back();
5504 auto parentLayer = layerStack.back().second;
5505 if (parseOne(&parentLayer.getBody().front()))
5510 return emitError(
"expected 'layer'"), failure();
5519 FIRCircuitParser::parseModuleBody(
const SymbolTable &circuitSymTbl,
5520 DeferredModuleToParse &deferredModule,
5521 InnerSymFixups &fixups) {
5522 FModuleLike moduleOp = deferredModule.moduleOp;
5523 auto &body = moduleOp->getRegion(0).front();
5524 auto &portLocs = deferredModule.portLocs;
5528 FIRLexer moduleBodyLexer(getLexer().getSourceMgr(), getContext());
5531 deferredModule.lexerCursor.restore(moduleBodyLexer);
5533 FIRModuleContext moduleContext(getConstants(), moduleBodyLexer, version);
5537 auto portList = moduleOp.getPorts();
5538 auto portArgs = body.getArguments();
5539 for (
auto tuple : llvm::zip(portList, portLocs, portArgs)) {
5540 PortInfo &port = std::get<0>(tuple);
5541 llvm::SMLoc loc = std::get<1>(tuple);
5542 BlockArgument portArg = std::get<2>(tuple);
5544 if (moduleContext.addSymbolEntry(port.
getName(), portArg, loc))
5548 FIRStmtParser stmtParser(body, moduleContext, fixups, circuitSymTbl, version);
5551 auto result = stmtParser.parseSimpleStmtBlock(deferredModule.indent);
5557 size_t numVerifPrintfs = 0;
5558 std::optional<Location> printfLoc;
5560 deferredModule.moduleOp.walk([&](PrintFOp printFOp) {
5565 printfLoc = printFOp.getLoc();
5568 if (numVerifPrintfs > 0) {
5570 mlir::emitError(deferredModule.moduleOp.getLoc(),
"module contains ")
5572 <<
" printf-encoded verification operation(s), which are no longer "
5574 diag.attachNote(*printfLoc)
5575 <<
"example printf here, this is now just a printf and nothing more";
5576 diag.attachNote() <<
"For more information, see "
5577 "https://github.com/llvm/circt/issues/6970";
5593 ParseResult FIRCircuitParser::parseCircuit(
5594 SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBufs,
5595 SmallVectorImpl<const llvm::MemoryBuffer *> &omirBufs,
5596 mlir::TimingScope &ts) {
5598 auto indent = getIndentation();
5599 if (parseToken(FIRToken::kw_FIRRTL,
"expected 'FIRRTL'"))
5601 if (!indent.has_value())
5602 return emitError(
"'FIRRTL' must be first token on its line");
5603 if (parseToken(FIRToken::kw_version,
"expected version after 'FIRRTL'") ||
5604 parseVersionLit(
"expected version literal"))
5606 indent = getIndentation();
5608 if (!indent.has_value())
5609 return emitError(
"'circuit' must be first token on its line");
5610 unsigned circuitIndent = *indent;
5612 LocWithInfo info(getToken().getLoc(),
this);
5614 SMLoc inlineAnnotationsLoc;
5615 StringRef inlineAnnotations;
5618 if (parseToken(FIRToken::kw_circuit,
5619 "expected a top-level 'circuit' definition") ||
5620 parseId(name,
"expected circuit name") ||
5621 parseToken(FIRToken::colon,
"expected ':' in circuit definition") ||
5622 parseOptionalAnnotations(inlineAnnotationsLoc, inlineAnnotations) ||
5623 info.parseOptionalInfo())
5627 OpBuilder b(mlirModule.getBodyRegion());
5628 auto circuit = b.create<CircuitOp>(info.getLoc(), name);
5631 auto parseAnnotationTimer = ts.nest(
"Parse annotations");
5637 SmallVector<Attribute> annos;
5638 if (!inlineAnnotations.empty())
5639 if (importAnnotationsRaw(inlineAnnotationsLoc, inlineAnnotations, annos))
5643 for (
auto *annotationsBuf : annotationsBufs)
5644 if (importAnnotationsRaw(info.getFIRLoc(), annotationsBuf->getBuffer(),
5648 parseAnnotationTimer.stop();
5649 auto parseOMIRTimer = ts.nest(
"Parse OMIR");
5653 for (
auto *omirBuf : omirBufs)
5654 if (importOMIR(circuit, info.getFIRLoc(), omirBuf->getBuffer(), annos))
5657 parseOMIRTimer.stop();
5665 auto parseTimer = ts.nest(
"Parse modules");
5666 deferredModules.reserve(16);
5670 switch (getToken().getKind()) {
5678 case FIRToken::error:
5682 emitError(
"unexpected token in circuit");
5685 case FIRToken::kw_class:
5686 case FIRToken::kw_declgroup:
5687 case FIRToken::kw_extclass:
5688 case FIRToken::kw_extmodule:
5689 case FIRToken::kw_intmodule:
5690 case FIRToken::kw_layer:
5691 case FIRToken::kw_formal:
5692 case FIRToken::kw_module:
5693 case FIRToken::kw_option:
5694 case FIRToken::kw_public:
5695 case FIRToken::kw_type: {
5696 auto indent = getIndentation();
5697 if (!indent.has_value())
5698 return emitError(
"'module' must be first token on its line"), failure();
5699 unsigned definitionIndent = *indent;
5701 if (definitionIndent <= circuitIndent)
5702 return emitError(
"module should be indented more"), failure();
5704 if (parseToplevelDefinition(circuit, definitionIndent))
5718 (void)getLexer().translateLocation(info.getFIRLoc());
5724 DenseMap<Attribute, Location> nameToOrigLoc;
5725 for (
auto &op : *circuit.getBodyBlock()) {
5728 op.getAttrOfType<StringAttr>(mlir::SymbolTable::getSymbolAttrName());
5733 auto it = nameToOrigLoc.try_emplace(nameAttr, op.getLoc());
5736 .append(
"redefinition of symbol named '", nameAttr.getValue(),
"'")
5737 .attachNote(it.first->second)
5738 .append(
"see existing symbol definition here");
5744 SymbolTable circuitSymTbl(circuit);
5746 moduleFixups.resize(deferredModules.size());
5751 for (
auto &d : deferredModules)
5752 innerSymbolNamespaces.get(d.moduleOp.getOperation());
5755 auto anyFailed = mlir::failableParallelForEachN(
5756 getContext(), 0, deferredModules.size(), [&](
size_t index) {
5757 if (parseModuleBody(circuitSymTbl, deferredModules[index],
5758 moduleFixups[index]))
5762 if (failed(anyFailed))
5767 for (
auto &fixups : moduleFixups) {
5768 if (failed(fixups.resolve(innerSymbolNamespaces)))
5774 auto parseLayerName = [&](StringRef name) {
5776 auto [head, rest] = name.split(
".");
5777 SmallVector<FlatSymbolRefAttr> nestedRefs;
5778 while (!rest.empty()) {
5780 std::tie(next, rest) = rest.split(
".");
5786 auto parseLayers = [&](
const auto &layers) {
5787 SmallVector<Attribute> layersAttr;
5788 for (
const auto &layer : layers)
5789 layersAttr.push_back(parseLayerName(layer));
5790 if (layersAttr.empty())
5795 if (
auto enableLayers = parseLayers(getConstants().options.enableLayers))
5796 circuit.setEnableLayersAttr(enableLayers);
5797 if (
auto disableLayers = parseLayers(getConstants().options.disableLayers))
5798 circuit.setDisableLayersAttr(disableLayers);
5799 circuit.setDefaultLayerSpecialization(
5800 getConstants().options.defaultLayerSpecialization);
5813 auto sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
5814 SmallVector<const llvm::MemoryBuffer *> annotationsBufs;
5815 unsigned fileID = 1;
5817 annotationsBufs.push_back(
5818 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID() + fileID));
5820 SmallVector<const llvm::MemoryBuffer *> omirBufs;
5821 for (
unsigned e = sourceMgr.getNumBuffers(); fileID < e; ++fileID)
5823 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID() + fileID));
5825 context->loadDialect<CHIRRTLDialect>();
5826 context->loadDialect<FIRRTLDialect, hw::HWDialect>();
5833 SharedParserConstants state(context, options);
5834 FIRLexer lexer(sourceMgr, context);
5836 .parseCircuit(annotationsBufs, omirBufs, ts))
5841 auto circuitVerificationTimer = ts.nest(
"Verify circuit");
5842 if (failed(
verify(*module)))
5849 static mlir::TranslateToMLIRRegistration fromFIR(
5850 "import-firrtl",
"import .fir",
5851 [](llvm::SourceMgr &sourceMgr, MLIRContext *context) {
5852 mlir::TimingScope ts;
assert(baseType &&"element must be base type")
static ParseResult parseParameterList(OpAsmParser &parser, SmallVector< Attribute > ¶meters)
Parse an parameter list if present.
std::vector< UnbundledValueEntry > UnbundledValuesList
SmallVector< std::pair< Attribute, Value > > UnbundledValueEntry
llvm::StringMap< std::pair< SMLoc, SymbolValueEntry >, llvm::BumpPtrAllocator > ModuleSymbolTable
llvm::PointerUnion< Value, UnbundledID > SymbolValueEntry
llvm::DenseMap< std::pair< Value, unsigned >, Value > SubaccessCache
ModuleSymbolTable::MapEntryTy ModuleSymbolTableEntry
llvm::PointerEmbeddedInt< unsigned, 31 > UnbundledID
static ParseResult parseType(Type &result, StringRef name, AsmParser &parser)
Parse a type defined by this dialect.
static std::vector< mlir::Value > toVector(mlir::ValueRange range)
static ParseResult parsePortList(OpAsmParser &p, SmallVectorImpl< module_like_impl::PortParse > &result)
This helper class is used to handle Info records, which specify higher level symbolic source location...
std::optional< Location > infoLoc
This is the location specified by the @ marker if present.
LocWithInfo(SMLoc firLoc, FIRParser *parser)
void setDefaultLoc(Location loc)
If we didn't parse an info locator for the specified value, this sets a default, overriding a fall ba...
SMLoc firLoc
This is the designated location in the .fir file for use when there is no @ info marker.
ParseResult parseOptionalInfo()
Parse an @info marker if present and update our location.
This class represents a reference to a specific field or element of an aggregate value.
FieldRef getSubField(unsigned subFieldID) const
Get a reference to a subfield.
Value getValue() const
Get the Value which created this location.
Location getLoc() const
Get the location associated with the value of this field ref.
This is the state captured for a lexer cursor.
This implements a lexer for .fir files.
std::optional< unsigned > getIndentation(const FIRToken &tok) const
Return the indentation level of the specified token or None if this token is preceded by another toke...
This represents a specific token for .fir files.
StringRef getSpelling() const
std::string getStringValue() const
Given a token containing a string literal, return its value, including removing the quote characters ...
llvm::SMLoc getLoc() const
static IntType get(MLIRContext *context, bool isSigned, int32_t widthOrSentinel=-1, bool isConst=false)
Return an SIntType or UIntType with the specified signedness, width, and constness.
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
mlir::Type innerType(mlir::Type type)
RefType getForceableResultType(bool forceable, Type type)
Return null or forceable reference result type.
Flow swapFlow(Flow flow)
Get a flow's reverse.
void registerFromFIRFileTranslation()
std::pair< bool, std::optional< mlir::LocationAttr > > maybeStringToLocation(llvm::StringRef spelling, bool skipParsing, mlir::StringAttr &locatorFilenameCache, FileLineColLoc &fileLineColLocCache, MLIRContext *context)
Flow foldFlow(Value val, Flow accumulatedFlow=Flow::Source)
Compute the flow for a Value, val, as determined by the FIRRTL specification.
constexpr const char * rawAnnotations
mlir::OwningOpRef< mlir::ModuleOp > importFIRFile(llvm::SourceMgr &sourceMgr, mlir::MLIRContext *context, mlir::TimingScope &ts, FIRParserOptions options={})
bool areTypesRefCastable(Type dstType, Type srcType)
Return true if destination ref type can be cast from source ref type, per FIRRTL spec rules they must...
bool areTypesEquivalent(FIRRTLType destType, FIRRTLType srcType, bool destOuterTypeIsConst=false, bool srcOuterTypeIsConst=false, bool requireSameWidths=false)
Returns whether the two types are equivalent.
hw::InnerRefAttr getInnerRefTo(const hw::InnerSymTarget &target, GetNamespaceCallback getNamespace)
Obtain an inner reference to the target (operation or port), adding an inner symbol as necessary.
bool isRecognizedPrintfEncodedVerif(PrintFOp printOp)
Classifier for legacy verif intent captured in printf + when's.
hw::InnerSymTarget getTargetFor(FieldRef ref)
Return the inner sym target for the specified value and fieldID.
bool fromOMIRJSON(llvm::json::Value &value, SmallVectorImpl< Attribute > &annotations, llvm::json::Path path, MLIRContext *context)
Convert a JSON value containing OMIR JSON (an array of OMNodes), convert this to an OMIRAnnotation,...
constexpr FIRVersion minimumFIRVersion(2, 0, 0)
void emitConnect(OpBuilder &builder, Location loc, Value lhs, Value rhs)
Emit a connect between two values.
bool importAnnotationsFromJSONRaw(llvm::json::Value &value, SmallVectorImpl< Attribute > &annotations, llvm::json::Path path, MLIRContext *context)
Deserialize a JSON value into FIRRTL Annotations.
constexpr FIRVersion nextFIRVersion(3, 3, 0)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
unsigned numAnnotationFiles
The number of annotation files that were specified on the command line.
InfoLocHandling
Specify how @info locators should be handled.
@ IgnoreInfo
If this is set to true, the @info locators are ignored, and the locations are set to the location in ...
The FIRRTL specification version.
This holds the name and type that describes the module's ports.
bool isOutput() const
Return true if this is a simple output-only port.
StringRef getName() const