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/LogicalResult.h"
43#include "llvm/Support/SourceMgr.h"
44#include "llvm/Support/raw_ostream.h"
54using mlir::LocationAttr;
67struct SharedParserConstants {
68 SharedParserConstants(MLIRContext *
context, FIRParserOptions options)
71 loIdentifier(StringAttr::get(
context,
"lo")),
72 hiIdentifier(StringAttr::get(
context,
"hi")),
73 amountIdentifier(StringAttr::get(
context,
"amount")),
75 hw::InnerRefAttr::get(StringAttr::get(
context,
"module"),
76 StringAttr::get(
context,
"placeholder"))) {}
82 const FIRParserOptions options;
85 llvm::StringMap<FIRRTLType> aliasMap;
88 llvm::DenseMap<StringRef, ClassLike> classMap;
91 llvm::DenseMap<StringRef, DomainOp> domainMap;
94 const ArrayAttr emptyArrayAttr;
97 const StringAttr loIdentifier, hiIdentifier, amountIdentifier;
100 const hw::InnerRefAttr placeholderInnerRef;
103 SharedParserConstants(
const SharedParserConstants &) =
delete;
104 void operator=(
const SharedParserConstants &) =
delete;
117 FIRParser(SharedParserConstants &constants, FIRLexer &lexer,
119 : version(version), constants(constants), lexer(lexer),
120 locatorFilenameCache(constants.loIdentifier ) {
124 SharedParserConstants &getConstants()
const {
return constants; }
125 MLIRContext *getContext()
const {
return constants.context; }
127 FIRLexer &getLexer() {
return lexer; }
130 std::optional<unsigned> getIndentation()
const {
131 return lexer.getIndentation(getToken());
135 const FIRToken &getToken()
const {
return lexer.getToken(); }
136 StringRef getTokenSpelling()
const {
return getToken().getSpelling(); }
143 InFlightDiagnostic emitError(
const Twine &message = {}) {
144 return emitError(getToken().
getLoc(), message);
146 InFlightDiagnostic emitError(SMLoc loc,
const Twine &message = {});
149 InFlightDiagnostic emitWarning(
const Twine &message = {}) {
150 return emitWarning(getToken().
getLoc(), message);
153 InFlightDiagnostic emitWarning(SMLoc loc,
const Twine &message = {});
163 Location translateLocation(llvm::SMLoc loc) {
164 return lexer.translateLocation(loc);
169 ParseResult parseOptionalInfoLocator(LocationAttr &result);
173 ParseResult parseOptionalName(StringAttr &name);
179 ParseResult requireFeature(FIRVersion minimum, StringRef feature) {
180 return requireFeature(minimum, feature, getToken().
getLoc());
183 ParseResult requireFeature(FIRVersion minimum, StringRef feature, SMLoc loc) {
184 if (version < minimum)
185 return emitError(loc)
186 << feature <<
" are a FIRRTL " << minimum
187 <<
"+ feature, but the specified FIRRTL version was " << version;
191 ParseResult removedFeature(FIRVersion removedVersion, StringRef feature) {
192 return removedFeature(removedVersion, feature, getToken().
getLoc());
195 ParseResult removedFeature(FIRVersion removedVersion, StringRef feature,
197 if (version >= removedVersion)
198 return emitError(loc)
199 << feature <<
" were removed in FIRRTL " << removedVersion
200 <<
", but the specified FIRRTL version was " << version;
210 ParseResult parseOptionalAnnotations(SMLoc &loc, StringRef &result);
219 if (getToken().isNot(kind))
228 FIRToken consumeToken() {
229 FIRToken consumedToken = getToken();
230 assert(consumedToken.
isNot(FIRToken::eof, FIRToken::error) &&
231 "shouldn't advance past EOF or errors");
233 return consumedToken;
242 FIRToken consumedToken = getToken();
243 assert(consumedToken.
is(kind) &&
"consumed an unexpected token");
245 return consumedToken;
250 ParseResult parseGetSpelling(StringRef &spelling) {
251 spelling = getTokenSpelling();
257 ParseResult parseToken(
FIRToken::Kind expectedToken,
const Twine &message);
262 const std::function<ParseResult()> &parseElement);
269 ParseResult parseIntLit(APInt &result,
const Twine &message);
270 ParseResult parseIntLit(int64_t &result,
const Twine &message);
271 ParseResult parseIntLit(int32_t &result,
const Twine &message);
274 ParseResult parseVersionLit(
const Twine &message);
277 ParseResult parseWidth(int32_t &result);
280 ParseResult parseId(StringRef &result,
const Twine &message);
281 ParseResult parseId(StringAttr &result,
const Twine &message);
282 ParseResult parseFieldId(StringRef &result,
const Twine &message);
283 ParseResult parseFieldIdSeq(SmallVectorImpl<StringRef> &result,
284 const Twine &message);
285 ParseResult parseEnumType(FIRRTLType &result);
286 ParseResult parseListType(FIRRTLType &result);
287 ParseResult parseRegistryType(FIRRTLType &result);
288 ParseResult
parseType(FIRRTLType &result,
const Twine &message);
290 ParseResult parsePropertyType(PropertyType &result,
const Twine &message);
292 ParseResult parseRUW(RUWBehavior &result);
293 ParseResult parseOptionalRUW(RUWBehavior &result);
295 ParseResult parseParameter(StringAttr &resultName, Attribute &resultValue,
296 SMLoc &resultLoc,
bool allowAggregates =
false);
297 ParseResult parseParameterValue(Attribute &resultValue,
298 bool allowAggregates =
false);
304 FIRParser(
const FIRParser &) =
delete;
305 void operator=(
const FIRParser &) =
delete;
309 SharedParserConstants &constants;
313 StringAttr locatorFilenameCache;
315 FileLineColLoc fileLineColLocCache;
324InFlightDiagnostic FIRParser::emitError(SMLoc loc,
const Twine &message) {
325 auto diag = mlir::emitError(translateLocation(loc), message);
329 if (getToken().is(FIRToken::error))
334InFlightDiagnostic FIRParser::emitWarning(SMLoc loc,
const Twine &message) {
335 return mlir::emitWarning(translateLocation(loc), message);
345 const Twine &message) {
346 if (consumeIf(expectedToken))
348 return emitError(message);
355 const std::function<ParseResult()> &parseElement) {
356 if (consumeIf(rightToken))
362 while (consumeIf(FIRToken::comma)) {
367 if (parseToken(rightToken,
"expected ','"))
399 if (failed(
parser->parseOptionalInfoLocator(loc)))
403 switch (
parser->constants.options.infoLocatorHandling) {
404 case ILH::IgnoreInfo:
405 assert(0 &&
"Should not return info locations if ignoring");
407 case ILH::PreferInfo:
411 infoLoc = FusedLoc::get(loc.getContext(),
412 {loc, parser->translateLocation(firLoc)});
439ParseResult FIRParser::parseOptionalInfoLocator(LocationAttr &result) {
440 if (getToken().isNot(FIRToken::fileinfo))
443 auto loc = getToken().getLoc();
445 auto spelling = getTokenSpelling();
446 consumeToken(FIRToken::fileinfo);
450 constants.options.infoLocatorHandling ==
452 locatorFilenameCache, fileLineColLocCache, getContext());
455 if (!locationPair.first) {
456 mlir::emitWarning(translateLocation(loc),
457 "ignoring unknown @ info record format");
464 FIRParserOptions::InfoLocHandling::IgnoreInfo)
468 result = *locationPair.second;
476ParseResult FIRParser::parseOptionalName(StringAttr &name) {
478 if (getToken().isNot(FIRToken::colon)) {
479 name = StringAttr::get(getContext(),
"");
483 consumeToken(FIRToken::colon);
485 if (parseId(nameRef,
"expected result name"))
488 name = StringAttr::get(getContext(), nameRef);
499ParseResult FIRParser::parseOptionalAnnotations(SMLoc &loc, StringRef &result) {
501 if (getToken().isNot(FIRToken::inlineannotation))
504 loc = getToken().getLoc();
506 result = getTokenSpelling().drop_front(2).drop_back(1);
507 consumeToken(FIRToken::inlineannotation);
525ParseResult FIRParser::parseIntLit(APInt &result,
const Twine &message) {
526 auto spelling = getTokenSpelling();
527 bool isNegative =
false;
528 switch (getToken().getKind()) {
529 case FIRToken::signed_integer:
530 isNegative = spelling[0] ==
'-';
531 assert(spelling[0] ==
'+' || spelling[0] ==
'-');
532 spelling = spelling.drop_front();
534 case FIRToken::integer:
535 if (spelling.getAsInteger(10, result))
536 return emitError(message),
failure();
540 if (result.isNegative())
541 result = result.zext(result.getBitWidth() + 1);
550 if (result.getBitWidth() > 32 && result.getSignificantBits() <= 32)
551 result = result.trunc(32);
555 case FIRToken::radix_specified_integer: {
556 if (requireFeature({2, 4, 0},
"radix-specified integer literals"))
558 if (spelling[0] ==
'-') {
560 spelling = spelling.drop_front();
562 unsigned base = llvm::StringSwitch<unsigned>(spelling.take_front(2))
567 spelling = spelling.drop_front(2);
568 if (spelling.getAsInteger(base, result))
569 return emitError(
"invalid character in integer literal"),
failure();
570 if (result.isNegative())
571 result = result.zext(result.getBitWidth() + 1);
577 case FIRToken::string: {
578 if (FIRVersion(3, 0, 0) <= version)
580 "String-encoded integer literals are unsupported after FIRRTL 3.0.0");
583 assert(spelling.front() ==
'"' && spelling.back() ==
'"');
584 spelling = spelling.drop_back().drop_front();
588 switch (spelling.empty() ?
' ' : spelling.front()) {
599 return emitError(
"expected base specifier (h/o/b) in integer literal"),
602 spelling = spelling.drop_front();
605 bool isNegative =
false;
606 if (!spelling.empty() && spelling.front() ==
'+')
607 spelling = spelling.drop_front();
608 else if (!spelling.empty() && spelling.front() ==
'-') {
610 spelling = spelling.drop_front();
614 if (spelling.empty())
615 return emitError(
"expected digits in integer literal"),
failure();
617 if (spelling.getAsInteger(base, result))
618 return emitError(
"invalid character in integer literal"),
failure();
623 if (result.isNegative())
624 result = result.zext(result.getBitWidth() + 1);
629 consumeToken(FIRToken::string);
634 return emitError(
"expected integer literal"),
failure();
638ParseResult FIRParser::parseIntLit(int64_t &result,
const Twine &message) {
640 auto loc = getToken().getLoc();
641 if (parseIntLit(value, message))
644 result = (int64_t)value.getLimitedValue(INT64_MAX);
646 return emitError(loc,
"value is too big to handle"),
failure();
650ParseResult FIRParser::parseIntLit(int32_t &result,
const Twine &message) {
652 auto loc = getToken().getLoc();
653 if (parseIntLit(value, message))
656 result = (int32_t)value.getLimitedValue(INT32_MAX);
658 return emitError(loc,
"value is too big to handle"),
failure();
664ParseResult FIRParser::parseVersionLit(
const Twine &message) {
665 auto spelling = getTokenSpelling();
666 if (getToken().getKind() != FIRToken::version)
667 return emitError(message),
failure();
670 return emitError(
"failed to parse version string"),
failure();
675 consumeToken(FIRToken::version);
681ParseResult FIRParser::parseWidth(int32_t &result) {
682 auto widthLoc = getToken().getLoc();
683 if (parseIntLit(result,
"expected width") ||
684 parseToken(FIRToken::greater,
"expected '>'"))
687 return emitError(widthLoc,
"invalid width specifier"),
failure();
695ParseResult FIRParser::parseId(StringRef &result,
const Twine &message) {
696 switch (getToken().getKind()) {
698 case FIRToken::identifier:
699 case FIRToken::literal_identifier:
701#define TOK_KEYWORD(spelling) case FIRToken::kw_##spelling:
702#include "FIRTokenKinds.def"
707 if (getToken().getKind() == FIRToken::literal_identifier)
708 result = getTokenSpelling().drop_front().drop_back();
710 result = getTokenSpelling();
720ParseResult FIRParser::parseId(StringAttr &result,
const Twine &message) {
722 if (parseId(name, message))
725 result = StringAttr::get(getContext(), name);
734ParseResult FIRParser::parseFieldId(StringRef &result,
const Twine &message) {
736 result = getTokenSpelling();
737 if (consumeIf(FIRToken::integer))
743 if (parseId(result, message))
755ParseResult FIRParser::parseFieldIdSeq(SmallVectorImpl<StringRef> &result,
756 const Twine &message) {
758 StringRef tmp = getTokenSpelling();
760 if (consumeIf(FIRToken::integer)) {
761 result.push_back(tmp);
765 if (consumeIf(FIRToken::floatingpoint)) {
769 auto [a, b] = tmp.split(
".");
775 if (consumeIf(FIRToken::version)) {
777 auto [a,
d] = tmp.split(
".");
778 auto [b, c] =
d.split(
".");
786 if (parseId(tmp, message))
788 result.push_back(tmp);
794ParseResult FIRParser::parseEnumType(FIRRTLType &result) {
795 if (parseToken(FIRToken::l_brace_bar,
796 "expected leading '{|' in enumeration type"))
798 SmallVector<StringAttr> names;
799 SmallVector<APInt> values;
800 SmallVector<FIRRTLBaseType> types;
801 SmallVector<SMLoc> locs;
802 if (parseListUntil(FIRToken::r_brace_bar, [&]() -> ParseResult {
803 auto fieldLoc = getToken().getLoc();
804 locs.push_back(fieldLoc);
808 if (parseId(nameStr,
"expected valid identifier for enumeration tag"))
810 auto name = StringAttr::get(getContext(), nameStr);
811 names.push_back(name);
817 if (consumeIf(FIRToken::equal)) {
818 if (parseIntLit(value,
"expected integer value for enumeration tag"))
820 if (value.isNegative())
821 return emitError(fieldLoc,
"enum tag value must be non-negative");
822 }
else if (values.empty()) {
828 auto &prev = values.back();
829 if (prev.isMaxValue())
830 value = prev.zext(prev.getBitWidth() + 1);
835 values.push_back(std::move(value));
839 if (consumeIf(FIRToken::colon)) {
840 FIRRTLType parsedType;
841 if (
parseType(parsedType,
"expected enumeration type"))
845 return emitError(fieldLoc,
"field must be a base type");
848 type = UIntType::get(getContext(), 0);
850 types.push_back(type);
852 auto r = type.getRecursiveTypeProperties();
854 return emitError(fieldLoc) <<
"enum field " << name <<
" not passive";
855 if (r.containsAnalog)
856 return emitError(fieldLoc)
857 <<
"enum field " << name <<
" contains analog";
858 if (r.hasUninferredWidth)
859 return emitError(fieldLoc)
860 <<
"enum field " << name <<
" has uninferred width";
861 if (r.hasUninferredReset)
862 return emitError(fieldLoc)
863 <<
"enum field " << name <<
" has uninferred reset";
869 SmallPtrSet<StringAttr, 4> nameSet;
870 for (
auto [name, loc] : llvm::zip(names, locs))
871 if (!nameSet.insert(name).second)
872 return emitError(loc,
873 "duplicate variant name in enum: " + name.getValue());
876 unsigned bitwidth = 0;
877 for (
auto &value : values)
878 bitwidth = std::max(bitwidth, value.getActiveBits());
880 IntegerType::get(getContext(), bitwidth, IntegerType::Unsigned);
884 SmallPtrSet<IntegerAttr, 4> valueSet;
885 SmallVector<FEnumType::EnumElement, 4> elements;
886 for (
auto [name, value, type, loc] : llvm::zip(names, values, types, locs)) {
887 auto tagValue = value.zextOrTrunc(bitwidth);
888 auto attr = IntegerAttr::get(tagType, tagValue);
890 if (!valueSet.insert(attr).second)
891 return emitError(loc,
"duplicate variant value in enum: ") << attr;
892 elements.push_back({name, attr, type});
895 llvm::sort(elements);
896 result = FEnumType::get(getContext(), elements);
900ParseResult FIRParser::parsePropertyType(PropertyType &result,
901 const Twine &message) {
902 auto loc = getToken().getLoc();
909 return emitError(loc,
"expected property type");
915ParseResult FIRParser::parseListType(FIRRTLType &result) {
916 consumeToken(FIRToken::kw_List);
919 if (parseToken(FIRToken::less,
"expected '<' in List type") ||
920 parsePropertyType(
elementType,
"expected List element type") ||
921 parseToken(FIRToken::greater,
"expected '>' in List type"))
929ParseResult FIRParser::parseRegistryType(FIRRTLType &result) {
930 consumeToken(FIRToken::kw_Registry);
933 if (parseToken(FIRToken::less,
"expected '<' in Registry type") ||
934 parsePropertyType(
elementType,
"expected Registry element type") ||
935 parseToken(FIRToken::greater,
"expected '>' in Registry type"))
938 result = RegistryType::get(getContext(),
elementType);
962ParseResult FIRParser::parseType(FIRRTLType &result,
const Twine &message) {
963 auto typeLoc = getToken().getLoc();
964 switch (getToken().getKind()) {
966 return emitError(message),
failure();
968 case FIRToken::kw_Clock:
969 consumeToken(FIRToken::kw_Clock);
970 result = ClockType::get(getContext());
973 case FIRToken::kw_Inst: {
974 if (requireFeature({6, 0, 0},
"Inst types"))
977 consumeToken(FIRToken::kw_Inst);
978 if (parseToken(FIRToken::less,
"expected < in Inst type"))
981 auto loc = getToken().getLoc();
983 if (parseId(
id,
"expected class name in Inst type"))
987 const auto &classMap = getConstants().classMap;
988 auto lookup = classMap.find(
id);
989 if (lookup == classMap.end())
990 return emitError(loc) <<
"unknown class '" <<
id <<
"'";
992 auto classOp = lookup->second;
994 if (parseToken(FIRToken::greater,
"expected > in Inst type"))
997 result = classOp.getInstanceType();
1001 case FIRToken::kw_AnyRef: {
1002 if (requireFeature({6, 0, 0},
"AnyRef types"))
1005 consumeToken(FIRToken::kw_AnyRef);
1006 result = AnyRefType::get(getContext());
1010 case FIRToken::kw_Reset:
1011 consumeToken(FIRToken::kw_Reset);
1012 result = ResetType::get(getContext());
1015 case FIRToken::kw_AsyncReset:
1016 consumeToken(FIRToken::kw_AsyncReset);
1017 result = AsyncResetType::get(getContext());
1020 case FIRToken::kw_UInt:
1021 consumeToken(FIRToken::kw_UInt);
1023 result = UIntType::get(getContext(), -1);
1026 case FIRToken::kw_SInt:
1027 consumeToken(FIRToken::kw_SInt);
1029 result = SIntType::get(getContext(), -1);
1032 case FIRToken::kw_Analog:
1033 consumeToken(FIRToken::kw_Analog);
1035 result = AnalogType::get(getContext(), -1);
1038 case FIRToken::langle_UInt:
1039 case FIRToken::langle_SInt:
1040 case FIRToken::langle_Analog: {
1043 auto kind = getToken().getKind();
1047 if (parseWidth(width))
1050 if (kind == FIRToken::langle_SInt)
1051 result = SIntType::get(getContext(), width);
1052 else if (kind == FIRToken::langle_UInt)
1053 result = UIntType::get(getContext(), width);
1055 assert(kind == FIRToken::langle_Analog);
1056 result = AnalogType::get(getContext(), width);
1061 case FIRToken::kw_Domain: {
1067 auto loc = getToken().getLoc();
1068 StringRef domainKindStr;
1069 if (parseToken(FIRToken::kw_of,
"expected 'of' after Domain type") ||
1070 parseId(domainKindStr,
"expected domain kind"))
1074 const auto &domainMap = getConstants().domainMap;
1075 auto lookup = domainMap.find(domainKindStr);
1076 if (lookup == domainMap.end())
1077 return emitError(loc) <<
"unknown domain '" << domainKindStr <<
"'";
1079 result = DomainType::getFromDomainOp(lookup->second);
1083 case FIRToken::kw_Probe:
1084 case FIRToken::kw_RWProbe: {
1085 auto kind = getToken().getKind();
1086 auto loc = getToken().getLoc();
1091 if (parseToken(FIRToken::less,
"expected '<' in reference type") ||
1092 parseType(type,
"expected probe data type"))
1095 SmallVector<StringRef> layers;
1096 if (consumeIf(FIRToken::comma)) {
1097 if (requireFeature({4, 0, 0},
"colored probes"))
1102 loc = getToken().getLoc();
1103 if (parseId(layer,
"expected layer name"))
1105 layers.push_back(layer);
1106 }
while (consumeIf(FIRToken::period));
1109 if (!consumeIf(FIRToken::greater))
1110 return emitError(loc,
"expected '>' to end reference type");
1112 bool forceable = kind == FIRToken::kw_RWProbe;
1116 return emitError(loc,
"invalid probe inner type, must be base-type");
1119 return emitError(loc,
"probe inner type must be passive");
1121 if (forceable &&
innerType.containsConst())
1122 return emitError(loc,
"rwprobe cannot contain const");
1124 SymbolRefAttr layer;
1125 if (!layers.empty()) {
1127 llvm::map_range(ArrayRef(layers).drop_front(), [&](StringRef a) {
1128 return FlatSymbolRefAttr::get(getContext(), a);
1130 layer = SymbolRefAttr::get(getContext(), layers.front(),
1131 llvm::to_vector(nestedLayers));
1134 result = RefType::get(innerType, forceable, layer);
1138 case FIRToken::l_brace: {
1139 consumeToken(FIRToken::l_brace);
1141 SmallVector<OpenBundleType::BundleElement, 4> elements;
1142 SmallPtrSet<StringAttr, 4> nameSet;
1143 bool bundleCompatible =
true;
1144 if (parseListUntil(FIRToken::r_brace, [&]() -> ParseResult {
1145 bool isFlipped = consumeIf(FIRToken::kw_flip);
1147 auto loc = getToken().getLoc();
1148 StringRef fieldNameStr;
1149 if (parseFieldId(fieldNameStr,
"expected bundle field name") ||
1150 parseToken(FIRToken::colon,
"expected ':' in bundle"))
1152 auto fieldName = StringAttr::get(getContext(), fieldNameStr);
1155 if (!nameSet.insert(fieldName).second)
1156 return emitError(loc,
"duplicate field name in bundle: " +
1157 fieldName.getValue());
1160 if (
parseType(type,
"expected bundle field type"))
1163 elements.push_back({fieldName, isFlipped, type});
1164 bundleCompatible &= isa<BundleType::ElementType>(type);
1171 if (bundleCompatible) {
1172 auto bundleElements = llvm::map_range(elements, [](
auto element) {
1173 return BundleType::BundleElement{
1174 element.name, element.isFlip,
1175 cast<BundleType::ElementType>(element.type)};
1177 result = BundleType::get(getContext(), llvm::to_vector(bundleElements));
1179 result = OpenBundleType::getChecked(
1180 [&]() {
return emitError(typeLoc); }, getContext(),
1181 ArrayRef<OpenBundleType::BundleElement>(elements));
1188 case FIRToken::l_brace_bar: {
1189 if (parseEnumType(result))
1194 case FIRToken::identifier: {
1196 auto loc = getToken().getLoc();
1197 if (parseId(
id,
"expected a type alias name"))
1199 auto it = constants.aliasMap.find(
id);
1200 if (it == constants.aliasMap.end()) {
1201 emitError(loc) <<
"type identifier `" <<
id <<
"` is not declared";
1204 result = it->second;
1208 case FIRToken::kw_const: {
1209 consumeToken(FIRToken::kw_const);
1210 auto nextToken = getToken();
1211 auto loc = nextToken.getLoc();
1214 if (nextToken.is(FIRToken::kw_const))
1215 return emitError(loc,
"'const' can only be specified once on a type");
1222 return emitError(loc,
"only hardware types can be 'const'");
1224 result = baseType.getConstType(
true);
1228 case FIRToken::kw_String:
1229 if (requireFeature({3, 1, 0},
"Strings"))
1231 consumeToken(FIRToken::kw_String);
1232 result = StringType::get(getContext());
1234 case FIRToken::kw_Integer:
1235 if (requireFeature({3, 1, 0},
"Integers"))
1237 consumeToken(FIRToken::kw_Integer);
1238 result = FIntegerType::get(getContext());
1240 case FIRToken::kw_Bool:
1241 if (requireFeature({6, 0, 0},
"Bools"))
1243 consumeToken(FIRToken::kw_Bool);
1244 result = BoolType::get(getContext());
1246 case FIRToken::kw_Double:
1247 if (requireFeature({6, 0, 0},
"Doubles"))
1249 consumeToken(FIRToken::kw_Double);
1250 result = DoubleType::get(getContext());
1252 case FIRToken::kw_Path:
1253 if (requireFeature({6, 0, 0},
"Paths"))
1255 consumeToken(FIRToken::kw_Path);
1256 result = PathType::get(getContext());
1258 case FIRToken::kw_List:
1259 if (requireFeature({4, 0, 0},
"Lists") || parseListType(result))
1263 case FIRToken::langle_List: {
1266 if (requireFeature({4, 0, 0},
"Lists"))
1271 if (parsePropertyType(
elementType,
"expected List element type") ||
1272 parseToken(FIRToken::greater,
"expected '>' in List type"))
1275 result = ListType::get(getContext(),
elementType);
1279 case FIRToken::kw_Registry:
1281 parseRegistryType(result))
1285 case FIRToken::langle_Registry: {
1293 if (parsePropertyType(
elementType,
"expected Registry element type") ||
1294 parseToken(FIRToken::greater,
"expected '>' in Registry type"))
1297 result = RegistryType::get(getContext(),
elementType);
1303 while (consumeIf(FIRToken::l_square)) {
1304 auto sizeLoc = getToken().getLoc();
1306 if (parseIntLit(size,
"expected width") ||
1307 parseToken(FIRToken::r_square,
"expected ]"))
1311 return emitError(sizeLoc,
"invalid size specifier"),
failure();
1315 result = FVectorType::get(baseType, size);
1317 result = OpenVectorType::getChecked([&]() {
return emitError(typeLoc); },
1328ParseResult FIRParser::parseRUW(RUWBehavior &result) {
1329 switch (getToken().getKind()) {
1331 case FIRToken::kw_old:
1332 result = RUWBehavior::Old;
1333 consumeToken(FIRToken::kw_old);
1335 case FIRToken::kw_new:
1336 result = RUWBehavior::New;
1337 consumeToken(FIRToken::kw_new);
1339 case FIRToken::kw_undefined:
1340 result = RUWBehavior::Undefined;
1341 consumeToken(FIRToken::kw_undefined);
1351ParseResult FIRParser::parseOptionalRUW(RUWBehavior &result) {
1352 switch (getToken().getKind()) {
1356 case FIRToken::kw_old:
1357 result = RUWBehavior::Old;
1358 consumeToken(FIRToken::kw_old);
1360 case FIRToken::kw_new:
1361 result = RUWBehavior::New;
1362 consumeToken(FIRToken::kw_new);
1364 case FIRToken::kw_undefined:
1365 result = RUWBehavior::Undefined;
1366 consumeToken(FIRToken::kw_undefined);
1374ParseResult FIRParser::parseParameter(StringAttr &resultName,
1375 Attribute &resultValue, SMLoc &resultLoc,
1376 bool allowAggregates) {
1377 auto loc = getToken().getLoc();
1381 if (parseId(name,
"expected parameter name") ||
1382 parseToken(FIRToken::equal,
"expected '=' in parameter"))
1387 if (parseParameterValue(value, allowAggregates))
1390 resultName = StringAttr::get(getContext(), name);
1391 resultValue = value;
1402ParseResult FIRParser::parseParameterValue(Attribute &value,
1403 bool allowAggregates) {
1404 mlir::Builder builder(getContext());
1405 switch (getToken().getKind()) {
1408 case FIRToken::integer:
1409 case FIRToken::signed_integer: {
1411 if (parseIntLit(result,
"invalid integer parameter"))
1417 if (result.getBitWidth() < 32)
1418 result = result.sext(32);
1420 value = builder.getIntegerAttr(
1421 builder.getIntegerType(result.getBitWidth(), result.isSignBitSet()),
1427 case FIRToken::string: {
1429 value = builder.getStringAttr(getToken().getStringValue());
1430 consumeToken(FIRToken::string);
1435 case FIRToken::verbatim_string: {
1437 auto text = builder.getStringAttr(getToken().getVerbatimStringValue());
1438 value = hw::ParamVerbatimAttr::get(text);
1439 consumeToken(FIRToken::verbatim_string);
1444 case FIRToken::floatingpoint: {
1446 if (!llvm::to_float(getTokenSpelling(), v))
1447 return emitError(
"invalid float parameter syntax"),
failure();
1449 value = builder.getF64FloatAttr(v);
1450 consumeToken(FIRToken::floatingpoint);
1455 case FIRToken::l_square: {
1456 if (!allowAggregates)
1457 return emitError(
"expected non-aggregate parameter value");
1460 SmallVector<Attribute> elements;
1461 auto parseElement = [&] {
1462 return parseParameterValue(elements.emplace_back(),
1465 if (parseListUntil(FIRToken::r_square, parseElement))
1468 value = builder.getArrayAttr(elements);
1473 case FIRToken::l_brace: {
1474 if (!allowAggregates)
1475 return emitError(
"expected non-aggregate parameter value");
1478 NamedAttrList fields;
1479 auto parseField = [&]() -> ParseResult {
1480 StringAttr fieldName;
1481 Attribute fieldValue;
1483 if (parseParameter(fieldName, fieldValue, fieldLoc,
1486 if (fields.set(fieldName, fieldValue))
1487 return emitError(fieldLoc)
1488 <<
"redefinition of parameter '" << fieldName.getValue() <<
"'";
1491 if (parseListUntil(FIRToken::r_brace, parseField))
1494 value = fields.getDictionary(getContext());
1499 return emitError(
"expected parameter value");
1514 llvm::StringMap<std::pair<SMLoc, SymbolValueEntry>, llvm::BumpPtrAllocator>;
1522struct UnbundledValueRestorer {
1524 size_t startingSize;
1526 startingSize = list.size();
1528 ~UnbundledValueRestorer() { list.resize(startingSize); }
1537struct FIRModuleContext :
public FIRParser {
1538 explicit FIRModuleContext(Block *topLevelBlock,
1539 SharedParserConstants &constants,
FIRLexer &lexer,
1541 : FIRParser(constants, lexer, version), topLevelBlock(topLevelBlock) {}
1544 template <
typename OpTy = ConstantOp,
typename... Args>
1545 Value getCachedConstant(ImplicitLocOpBuilder &builder, Attribute attr,
1546 Type type, Args &&...args) {
1547 auto &result = constantCache[{attr, type}];
1553 OpBuilder::InsertPoint savedIP;
1556 if (builder.getInsertionBlock() != topLevelBlock) {
1557 savedIP = builder.saveInsertionPoint();
1558 auto *block = builder.getInsertionBlock();
1560 auto *op = block->getParentOp();
1561 if (!op || !op->getBlock()) {
1563 builder.setInsertionPointToEnd(topLevelBlock);
1566 if (op->getBlock() == topLevelBlock) {
1567 builder.setInsertionPoint(op);
1570 block = op->getBlock();
1574 result = OpTy::create(builder, type, std::forward<Args>(args)...);
1576 if (savedIP.isSet())
1577 builder.setInsertionPoint(savedIP.getBlock(), savedIP.getPoint());
1588 Value &getCachedSubaccess(Value value,
unsigned index) {
1589 auto &result = subaccessCache[{value, index}];
1592 auto it = scopeMap.find(value.getParentBlock());
1593 if (it != scopeMap.end())
1594 it->second->scopedSubaccesses.push_back({result, index});
1604 ParseResult addSymbolEntry(StringRef name,
SymbolValueEntry entry, SMLoc loc,
1605 bool insertNameIntoGlobalScope =
false);
1606 ParseResult addSymbolEntry(StringRef name, Value value, SMLoc loc,
1607 bool insertNameIntoGlobalScope =
false) {
1609 insertNameIntoGlobalScope);
1613 void removeSymbolEntry(StringRef name);
1617 SMLoc loc,
bool fatal =
true);
1622 StringRef field, SMLoc loc);
1630 assert(index < unbundledValues.size());
1631 return unbundledValues[index];
1641 struct ContextScope {
1642 friend struct FIRModuleContext;
1643 ContextScope(FIRModuleContext &moduleContext, Block *block)
1644 : moduleContext(moduleContext), block(block),
1645 previousScope(moduleContext.currentScope) {
1646 moduleContext.currentScope =
this;
1647 moduleContext.scopeMap[block] =
this;
1652 for (
auto *entryPtr : scopedDecls)
1653 entryPtr->second.first = SMLoc();
1656 for (
auto subaccess : scopedSubaccesses)
1657 moduleContext.subaccessCache.erase(subaccess);
1659 moduleContext.scopeMap.erase(block);
1661 moduleContext.currentScope = previousScope;
1665 void operator=(
const ContextScope &) =
delete;
1666 ContextScope(
const ContextScope &) =
delete;
1668 FIRModuleContext &moduleContext;
1670 ContextScope *previousScope;
1671 std::vector<ModuleSymbolTableEntry *> scopedDecls;
1672 std::vector<std::pair<Value, unsigned>> scopedSubaccesses;
1677 Block *topLevelBlock;
1683 llvm::DenseMap<std::pair<Attribute, Type>, Value> constantCache;
1695 DenseMap<Block *, ContextScope *> scopeMap;
1700 ContextScope *currentScope =
nullptr;
1706void FIRModuleContext::removeSymbolEntry(StringRef name) {
1707 symbolTable.erase(name);
1716ParseResult FIRModuleContext::addSymbolEntry(StringRef name,
1718 bool insertNameIntoGlobalScope) {
1721 auto [entryIt, inserted] =
1726 if (entryIt->second.first.isValid()) {
1728 emitError(loc,
"redefinition of name '" + name +
"' ")
1729 .attachNote(translateLocation(entryIt->second.first))
1730 <<
"previous definition here.";
1733 emitError(loc,
"redefinition of name '" + name +
"' ")
1734 <<
"- FIRRTL has flat namespace and requires all "
1735 <<
"declarations in a module to have unique names.";
1742 entryIt->second = {loc, entry};
1743 if (currentScope && !insertNameIntoGlobalScope)
1744 currentScope->scopedDecls.push_back(&*entryIt);
1751 StringRef name, SMLoc loc) {
1752 auto &entry = symbolTable[name];
1753 if (!entry.first.isValid())
1754 return emitError(loc,
"use of unknown declaration '" + name +
"'");
1755 result = entry.second;
1756 assert(result &&
"name in symbol table without definition");
1760ParseResult FIRModuleContext::resolveSymbolEntry(Value &result,
1762 SMLoc loc,
bool fatal) {
1763 if (!isa<Value>(entry)) {
1765 emitError(loc,
"bundle value should only be used from subfield");
1768 result = cast<Value>(entry);
1772ParseResult FIRModuleContext::resolveSymbolEntry(Value &result,
1774 StringRef fieldName,
1776 if (!isa<UnbundledID>(entry)) {
1777 emitError(loc,
"value should not be used from subfield");
1781 auto fieldAttr = StringAttr::get(getContext(), fieldName);
1783 unsigned unbundledId = cast<UnbundledID>(entry) - 1;
1784 assert(unbundledId < unbundledValues.size());
1786 for (
auto elt : ubEntry) {
1787 if (elt.first == fieldAttr) {
1788 result = elt.second;
1793 emitError(loc,
"use of invalid field name '")
1794 << fieldName <<
"' on bundle value";
1820struct LazyLocationListener :
public OpBuilder::Listener {
1821 LazyLocationListener(OpBuilder &builder) : builder(builder) {
1822 assert(builder.getListener() ==
nullptr);
1823 builder.setListener(
this);
1826 ~LazyLocationListener() {
1827 assert(subOps.empty() &&
"didn't process parsed operations");
1828 assert(builder.getListener() ==
this);
1829 builder.setListener(
nullptr);
1832 void startStatement() {
1833 assert(!isActive &&
"Already processing a statement");
1842 Location
getLoc(FIRParser &parser, SMLoc loc) {
1844 switch (parser.getConstants().options.infoLocatorHandling) {
1845 case ILH::IgnoreInfo:
1848 case ILH::PreferInfo:
1852 case ILH::FusedInfo:
1854 return FusedLoc::get(infoLoc.getContext(),
1855 {infoLoc, parser.translateLocation(loc)});
1858 return parser.translateLocation(loc);
1863 void endStatement(FIRParser &parser) {
1864 assert(isActive &&
"Not parsing a statement");
1868 for (
auto opAndSMLoc : subOps)
1869 opAndSMLoc.first->setLoc(
getLoc(parser, opAndSMLoc.second));
1873 infoLoc = LocationAttr();
1874 currentSMLoc = SMLoc();
1879 void setLoc(SMLoc loc) { currentSMLoc = loc; }
1882 void setInfoLoc(LocationAttr loc) {
1883 assert(!infoLoc &&
"Info location multiply specified");
1889 void notifyOperationInserted(Operation *op,
1890 mlir::IRRewriter::InsertPoint)
override {
1891 assert(currentSMLoc != SMLoc() &&
"No .fir file location specified");
1892 assert(isActive &&
"Not parsing a statement");
1893 subOps.push_back({op, currentSMLoc});
1898 bool isActive =
false;
1906 LocationAttr infoLoc;
1913 SmallVector<std::pair<Operation *, SMLoc>, 8> subOps;
1915 void operator=(
const LazyLocationListener &) =
delete;
1916 LazyLocationListener(
const LazyLocationListener &) =
delete;
1924struct InnerSymFixups {
1926 void add(hw::InnerRefUserOpInterface user, hw::InnerSymTarget target) {
1927 fixups.push_back({user, target});
1932 LogicalResult
resolve(hw::InnerSymbolNamespaceCollection &isnc);
1936 hw::InnerRefUserOpInterface innerRefUser;
1937 hw::InnerSymTarget target;
1939 SmallVector<Fixup, 0> fixups;
1944InnerSymFixups::resolve(hw::InnerSymbolNamespaceCollection &isnc) {
1945 for (
auto &f : fixups) {
1947 f.target, [&isnc](FModuleLike module) -> hw::InnerSymbolNamespace & {
1948 return isnc.get(module);
1950 assert(ref &&
"unable to resolve inner symbol target");
1954 TypeSwitch<Operation *, LogicalResult>(f.innerRefUser.getOperation())
1955 .Case<RWProbeOp>([ref](RWProbeOp op) {
1956 op.setTargetAttr(ref);
1959 .Default([](
auto *op) {
1960 return op->emitError(
"unknown inner-ref user requiring fixup");
1971struct FIRStmtParser :
public FIRParser {
1972 explicit FIRStmtParser(Block &blockToInsertInto,
1973 FIRModuleContext &moduleContext,
1974 InnerSymFixups &innerSymFixups,
1975 const SymbolTable &circuitSymTbl, FIRVersion version,
1976 SymbolRefAttr layerSym = {})
1977 : FIRParser(moduleContext.getConstants(), moduleContext.getLexer(),
1979 builder(UnknownLoc::
get(getContext()), getContext()),
1980 locationProcessor(this->builder), moduleContext(moduleContext),
1981 innerSymFixups(innerSymFixups), layerSym(layerSym),
1982 circuitSymTbl(circuitSymTbl) {
1983 builder.setInsertionPointToEnd(&blockToInsertInto);
1986 ParseResult parseSimpleStmt(
unsigned stmtIndent);
1987 ParseResult parseSimpleStmtBlock(
unsigned indent);
1990 ParseResult parseSimpleStmtImpl(
unsigned stmtIndent);
1993 void emitInvalidate(Value val,
Flow flow);
1999 void emitInvalidate(Value val) { emitInvalidate(val,
foldFlow(val)); }
2002 ParseResult parseOptionalInfo() {
2004 if (failed(parseOptionalInfoLocator(loc)))
2006 locationProcessor.setInfoLoc(loc);
2011 ParseResult parseExpImpl(Value &result,
const Twine &message,
2012 bool isLeadingStmt);
2013 ParseResult parseExp(Value &result,
const Twine &message) {
2014 return parseExpImpl(result, message,
false);
2016 ParseResult parseExpLeadingStmt(Value &result,
const Twine &message) {
2017 return parseExpImpl(result, message,
true);
2021 Value emitImplicitAnyRefCast(Value value, Type expectedType) {
2022 if (!isa<AnyRefType>(expectedType))
2024 if (isa<ClassType>(value.getType()))
2025 return ObjectAnyRefCastOp::create(builder, value);
2026 if (isa<DomainType>(value.getType()))
2027 return DomainAnyRefCastOp::create(builder, value);
2031 ParseResult parseEnumExp(Value &result);
2032 ParseResult parsePathExp(Value &result);
2033 ParseResult parseDomainExp(Value &result);
2034 ParseResult parseRefExp(Value &result,
const Twine &message);
2035 ParseResult parseStaticRefExp(Value &result,
const Twine &message);
2036 ParseResult parseRWProbeStaticRefExp(FieldRef &refResult, Type &type,
2037 const Twine &message);
2040 ParseResult parseIntrinsic(Value &result,
bool isStatement);
2041 ParseResult parseIntrinsicStmt() {
2043 return parseIntrinsic(unused,
true);
2045 ParseResult parseIntrinsicExp(Value &result) {
2046 return parseIntrinsic(result,
false);
2048 ParseResult parseOptionalParams(ArrayAttr &resultParameters);
2050 template <
typename subop>
2051 FailureOr<Value> emitCachedSubAccess(Value base,
unsigned indexNo, SMLoc loc);
2052 ParseResult parseOptionalExpPostscript(Value &result,
2053 bool allowDynamic =
true);
2054 ParseResult parsePostFixFieldId(Value &result);
2055 ParseResult parsePostFixIntSubscript(Value &result);
2056 ParseResult parsePostFixDynamicSubscript(Value &result);
2058 parseIntegerLiteralExp(Value &result,
bool isSigned,
2059 std::optional<int32_t> allocatedWidth = {});
2060 ParseResult parseListExp(Value &result);
2061 ParseResult parseListConcatExp(Value &result);
2062 ParseResult parseCatExp(Value &result);
2063 ParseResult parseStringConcatExp(Value &result);
2064 ParseResult parsePropEqExp(Value &result);
2065 ParseResult parseObjectEqExp(Value &result);
2066 ParseResult parseListContainsExp(Value &result);
2067 ParseResult parseUnsafeDomainCast(Value &result);
2068 ParseResult parseUnknownProperty(Value &result);
2070 template <
typename T,
size_t M,
size_t N,
size_t... Ms,
size_t... Ns>
2071 ParseResult parsePrim(std::index_sequence<Ms...>, std::index_sequence<Ns...>,
2073 auto loc = getToken().getLoc();
2074 locationProcessor.setLoc(loc);
2077 auto vals = std::array<Value, M>();
2078 auto ints = std::array<int64_t, N>();
2082 for (
size_t i = 0; i < M; ++i) {
2084 if (parseToken(FIRToken::comma,
"expected ','"))
2086 if (parseExp(vals[i],
"expected expression in primitive operand"))
2092 for (
size_t i = 0; i < N; ++i) {
2094 if (parseToken(FIRToken::comma,
"expected ','"))
2096 if (parseIntLit(ints[i],
"expected integer in primitive operand"))
2101 if (parseToken(FIRToken::r_paren,
"expected ')'"))
2105 auto type = T::inferReturnType(cast<FIRRTLType>(vals[Ms].getType())...,
2109 T::inferReturnType(cast<FIRRTLType>(vals[Ms].getType())..., ints[Ns]...,
2110 translateLocation(loc));
2115 auto op = T::create(builder, type, vals[Ms]..., ints[Ns]...);
2116 result = op.getResult();
2120 template <
typename T,
unsigned M,
unsigned N>
2121 ParseResult parsePrimExp(Value &result) {
2122 auto ms = std::make_index_sequence<M>();
2123 auto ns = std::make_index_sequence<N>();
2124 return parsePrim<T, M, N>(ms, ns, result);
2127 std::optional<ParseResult> parseExpWithLeadingKeyword(FIRToken keyword);
2130 ParseResult parseSubBlock(Block &blockToInsertInto,
unsigned indent,
2131 SymbolRefAttr layerSym);
2132 ParseResult parseAttach();
2133 ParseResult parseMemPort(MemDirAttr direction);
2139 ArrayRef<Value> specOperands,
2140 StringAttr &formatStringResult,
2141 SmallVectorImpl<Value> &operands);
2142 ParseResult parsePrintf();
2143 ParseResult parseFPrintf();
2144 ParseResult parseFFlush();
2145 ParseResult parseSkip();
2146 ParseResult parseStop();
2147 ParseResult parseAssert();
2148 ParseResult parseAssume();
2149 ParseResult parseCover();
2150 ParseResult parseWhen(
unsigned whenIndent);
2151 ParseResult parseMatch(
unsigned matchIndent);
2152 ParseResult parseDomainInstantiation();
2153 ParseResult parseDomainDefine();
2154 ParseResult parseRefDefine();
2155 ParseResult parseRefForce();
2156 ParseResult parseRefForceInitial();
2157 ParseResult parseRefRelease();
2158 ParseResult parseRefReleaseInitial();
2159 ParseResult parseRefRead(Value &result);
2160 ParseResult parseProbe(Value &result);
2161 ParseResult parsePropAssert();
2162 ParseResult parsePropAssign();
2163 ParseResult parseRWProbe(Value &result);
2164 ParseResult parseLeadingExpStmt(Value lhs);
2165 ParseResult parseConnect();
2166 ParseResult parseInvalidate();
2167 ParseResult parseLayerBlockOrGroup(
unsigned indent);
2170 ParseResult parseInstance();
2171 ParseResult parseInstanceChoice();
2172 ParseResult parseObject();
2173 ParseResult parseCombMem();
2174 ParseResult parseSeqMem();
2175 ParseResult parseMem(
unsigned memIndent);
2176 ParseResult parseNode();
2177 ParseResult parseWire();
2178 ParseResult parseRegister(
unsigned regIndent);
2179 ParseResult parseRegisterWithReset();
2180 ParseResult parseContract(
unsigned blockIndent);
2183 FModuleLike getReferencedModule(SMLoc loc, StringRef moduleName);
2186 ImplicitLocOpBuilder builder;
2187 LazyLocationListener locationProcessor;
2190 FIRModuleContext &moduleContext;
2193 InnerSymFixups &innerSymFixups;
2197 SymbolRefAttr layerSym;
2199 const SymbolTable &circuitSymTbl;
2206void FIRStmtParser::emitInvalidate(Value val,
Flow flow) {
2214 auto props = tpe.getRecursiveTypeProperties();
2215 if (props.isPassive && !props.containsAnalog) {
2216 if (flow == Flow::Source)
2218 emitConnect(builder, val, InvalidValueOp::create(builder, tpe),
2219 getConstants().options.warnOnTruncation);
2230 TypeSwitch<FIRRTLType>(tpe)
2231 .Case<BundleType>([&](
auto tpe) {
2232 for (
size_t i = 0, e = tpe.getNumElements(); i < e; ++i) {
2233 auto &subfield = moduleContext.getCachedSubaccess(val, i);
2235 OpBuilder::InsertionGuard guard(builder);
2236 builder.setInsertionPointAfterValue(val);
2237 subfield = SubfieldOp::create(builder, val, i);
2239 emitInvalidate(subfield,
2240 tpe.getElement(i).isFlip ?
swapFlow(flow) : flow);
2243 .Case<FVectorType>([&](
auto tpe) {
2244 auto tpex = tpe.getElementType();
2245 for (
size_t i = 0, e = tpe.getNumElements(); i != e; ++i) {
2246 auto &subindex = moduleContext.getCachedSubaccess(val, i);
2248 OpBuilder::InsertionGuard guard(builder);
2249 builder.setInsertionPointAfterValue(val);
2250 subindex = SubindexOp::create(builder, tpex, val, i);
2252 emitInvalidate(subindex, flow);
2280ParseResult FIRStmtParser::parseExpImpl(Value &result,
const Twine &message,
2281 bool isLeadingStmt) {
2282 auto token = getToken();
2283 auto kind = token.getKind();
2285 case FIRToken::lp_integer_add:
2286 case FIRToken::lp_integer_mul:
2287 case FIRToken::lp_integer_shr:
2288 case FIRToken::lp_integer_shl:
2289 if (requireFeature({4, 0, 0},
"Integer arithmetic expressions"))
2298#define TOK_LPKEYWORD_PRIM(SPELLING, CLASS, NUMOPERANDS, NUMATTRIBUTES, \
2300 case FIRToken::lp_##SPELLING: \
2301 if (requireFeature(VERSION, FEATURE)) \
2303 if (parsePrimExp<CLASS, NUMOPERANDS, NUMATTRIBUTES>(result)) \
2306#include "FIRTokenKinds.def"
2308 case FIRToken::l_brace_bar:
2310 return emitError(
"unexpected enumeration as start of statement");
2311 if (parseEnumExp(result))
2314 case FIRToken::lp_read:
2316 return emitError(
"unexpected read() as start of statement");
2317 if (parseRefRead(result))
2320 case FIRToken::lp_probe:
2322 return emitError(
"unexpected probe() as start of statement");
2323 if (parseProbe(result))
2326 case FIRToken::lp_rwprobe:
2328 return emitError(
"unexpected rwprobe() as start of statement");
2329 if (parseRWProbe(result))
2333 case FIRToken::langle_UInt:
2334 case FIRToken::langle_SInt: {
2337 bool isSigned = getToken().is(FIRToken::langle_SInt);
2340 if (parseWidth(width))
2344 if (parseIntegerLiteralExp(result, isSigned, width))
2349 case FIRToken::lp_UInt:
2350 if (parseIntegerLiteralExp(result,
false))
2353 case FIRToken::lp_SInt:
2354 if (parseIntegerLiteralExp(result,
true))
2357 case FIRToken::lp_String: {
2358 if (requireFeature({3, 1, 0},
"Strings"))
2360 locationProcessor.setLoc(getToken().
getLoc());
2361 consumeToken(FIRToken::lp_String);
2363 if (parseGetSpelling(spelling) ||
2364 parseToken(FIRToken::string,
2365 "expected string literal in String expression") ||
2366 parseToken(FIRToken::r_paren,
"expected ')' in String expression"))
2369 result = moduleContext.getCachedConstant<StringConstantOp>(
2370 builder, attr, builder.getType<StringType>(), attr);
2373 case FIRToken::lp_Integer: {
2374 if (requireFeature({3, 1, 0},
"Integers"))
2376 locationProcessor.setLoc(getToken().
getLoc());
2377 consumeToken(FIRToken::lp_Integer);
2379 if (parseIntLit(value,
"expected integer literal in Integer expression") ||
2380 parseToken(FIRToken::r_paren,
"expected ')' in Integer expression"))
2382 APSInt apint(value,
false);
2383 result = moduleContext.getCachedConstant<FIntegerConstantOp>(
2384 builder, IntegerAttr::get(getContext(), apint),
2385 builder.getType<FIntegerType>(), apint);
2388 case FIRToken::lp_Bool: {
2389 if (requireFeature({6, 0, 0},
"Bools"))
2391 locationProcessor.setLoc(getToken().
getLoc());
2392 consumeToken(FIRToken::lp_Bool);
2394 if (consumeIf(FIRToken::kw_true))
2396 else if (consumeIf(FIRToken::kw_false))
2399 return emitError(
"expected true or false in Bool expression");
2400 if (parseToken(FIRToken::r_paren,
"expected ')' in Bool expression"))
2402 auto attr = builder.getBoolAttr(value);
2403 result = moduleContext.getCachedConstant<BoolConstantOp>(
2404 builder, attr, builder.getType<BoolType>(), value);
2407 case FIRToken::lp_Double: {
2408 if (requireFeature({6, 0, 0},
"Doubles"))
2410 locationProcessor.setLoc(getToken().
getLoc());
2411 consumeToken(FIRToken::lp_Double);
2412 auto spelling = getTokenSpelling();
2413 if (parseToken(FIRToken::floatingpoint,
2414 "expected floating point in Double expression") ||
2415 parseToken(FIRToken::r_paren,
"expected ')' in Double expression"))
2420 if (!llvm::to_float(spelling, d))
2421 return emitError(
"invalid double");
2422 auto attr = builder.getF64FloatAttr(d);
2423 result = moduleContext.getCachedConstant<DoubleConstantOp>(
2424 builder, attr, builder.getType<DoubleType>(), attr);
2427 case FIRToken::lp_List:
2428 case FIRToken::langle_List: {
2429 if (requireFeature({4, 0, 0},
"Lists"))
2432 return emitError(
"unexpected List<>() as start of statement");
2433 if (parseListExp(result))
2438 case FIRToken::lp_list_concat: {
2440 return emitError(
"unexpected list_create() as start of statement");
2441 if (requireFeature({4, 0, 0},
"List concat") || parseListConcatExp(result))
2446 case FIRToken::lp_path:
2448 return emitError(
"unexpected path() as start of statement");
2449 if (requireFeature({6, 0, 0},
"Paths") || parsePathExp(result))
2453 case FIRToken::lp_intrinsic:
2454 if (requireFeature({4, 0, 0},
"generic intrinsics") ||
2455 parseIntrinsicExp(result))
2459 case FIRToken::lp_cat:
2460 if (parseCatExp(result))
2464 case FIRToken::lp_string_concat:
2465 if (parseStringConcatExp(result))
2469 case FIRToken::lp_prop_eq:
2470 if (requireFeature({6, 0, 0},
"property equality") ||
2471 parsePropEqExp(result))
2475 case FIRToken::lp_object_eq:
2477 parseObjectEqExp(result))
2481 case FIRToken::lp_list_contains:
2483 parseListContainsExp(result))
2487 case FIRToken::lp_unsafe_domain_cast:
2489 parseUnsafeDomainCast(result))
2492 case FIRToken::lp_Unknown:
2493 if (requireFeature(
nextFIRVersion,
"unknown property expressions") ||
2494 parseUnknownProperty(result))
2500 case FIRToken::identifier:
2501 case FIRToken::literal_identifier:
2502 case FIRToken::kw_UInt:
2503 case FIRToken::kw_SInt:
2504 case FIRToken::kw_String:
2505 case FIRToken::kw_Integer:
2506 case FIRToken::kw_Bool:
2507 case FIRToken::kw_Double:
2508 case FIRToken::kw_List:
2511 auto loc = getToken().getLoc();
2513 if (parseId(name, message) ||
2514 moduleContext.lookupSymbolEntry(symtabEntry, name, loc))
2518 if (!moduleContext.resolveSymbolEntry(result, symtabEntry, loc,
false))
2521 assert(isa<UnbundledID>(symtabEntry) &&
"should be an instance");
2526 if (isLeadingStmt && consumeIf(FIRToken::kw_is)) {
2527 if (parseToken(FIRToken::kw_invalid,
"expected 'invalid'") ||
2528 parseOptionalInfo())
2531 locationProcessor.setLoc(loc);
2533 unsigned unbundledId = cast<UnbundledID>(symtabEntry) - 1;
2535 moduleContext.getUnbundledEntry(unbundledId);
2536 for (
auto elt : ubEntry)
2537 emitInvalidate(elt.second);
2545 StringRef fieldName;
2546 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
2547 parseFieldId(fieldName,
"expected field name") ||
2548 moduleContext.resolveSymbolEntry(result, symtabEntry, fieldName, loc))
2556 case FIRToken::lp_shr:
2560 result = PadPrimOp::create(builder, result, 1);
2566 return parseOptionalExpPostscript(result);
2576ParseResult FIRStmtParser::parseOptionalExpPostscript(Value &result,
2577 bool allowDynamic) {
2582 if (consumeIf(FIRToken::period)) {
2583 if (parsePostFixFieldId(result))
2590 if (consumeIf(FIRToken::l_square)) {
2591 if (getToken().isAny(FIRToken::integer, FIRToken::string)) {
2592 if (parsePostFixIntSubscript(result))
2597 return emitError(
"subaccess not allowed here");
2598 if (parsePostFixDynamicSubscript(result))
2608template <
typename subop>
2610FIRStmtParser::emitCachedSubAccess(Value base,
unsigned indexNo, SMLoc loc) {
2612 auto &value = moduleContext.getCachedSubaccess(base, indexNo);
2618 auto baseType = cast<FIRRTLType>(base.getType());
2619 auto resultType = subop::inferReturnType(baseType, indexNo, {});
2622 (void)subop::inferReturnType(baseType, indexNo, translateLocation(loc));
2628 locationProcessor.setLoc(loc);
2629 OpBuilder::InsertionGuard guard(builder);
2630 builder.setInsertionPointAfterValue(base);
2631 auto op = subop::create(builder, resultType, base, indexNo);
2634 return value = op.getResult();
2641ParseResult FIRStmtParser::parsePostFixFieldId(Value &result) {
2642 auto loc = getToken().getLoc();
2643 SmallVector<StringRef, 3> fields;
2644 if (parseFieldIdSeq(fields,
"expected field name"))
2646 for (
auto fieldName : fields) {
2647 std::optional<unsigned> indexV;
2648 auto type = result.getType();
2650 type = refTy.getType();
2652 indexV = bundle.getElementIndex(fieldName);
2654 indexV = bundle.getElementIndex(fieldName);
2656 indexV = klass.getElementIndex(fieldName);
2658 indexV = domain.getFieldIndex(fieldName);
2660 return emitError(loc,
2661 "subfield requires bundle, object, or domain operand ");
2663 return emitError(loc,
"unknown field '" + fieldName +
"' in type ")
2664 << result.getType();
2665 auto indexNo = *indexV;
2667 FailureOr<Value> subResult;
2669 subResult = emitCachedSubAccess<RefSubOp>(result, indexNo, loc);
2671 subResult = emitCachedSubAccess<ObjectSubfieldOp>(result, indexNo, loc);
2673 subResult = emitCachedSubAccess<DomainSubfieldOp>(result, indexNo, loc);
2675 subResult = emitCachedSubAccess<SubfieldOp>(result, indexNo, loc);
2677 subResult = emitCachedSubAccess<OpenSubfieldOp>(result, indexNo, loc);
2679 if (failed(subResult))
2681 result = *subResult;
2690ParseResult FIRStmtParser::parsePostFixIntSubscript(Value &result) {
2691 auto loc = getToken().getLoc();
2693 if (parseIntLit(indexNo,
"expected index") ||
2694 parseToken(FIRToken::r_square,
"expected ']'"))
2698 return emitError(loc,
"invalid index specifier"),
failure();
2700 FailureOr<Value> subResult;
2702 subResult = emitCachedSubAccess<RefSubOp>(result, indexNo, loc);
2704 subResult = emitCachedSubAccess<SubindexOp>(result, indexNo, loc);
2706 subResult = emitCachedSubAccess<OpenSubindexOp>(result, indexNo, loc);
2708 if (failed(subResult))
2710 result = *subResult;
2718ParseResult FIRStmtParser::parsePostFixDynamicSubscript(Value &result) {
2719 auto loc = getToken().getLoc();
2721 if (parseExp(index,
"expected subscript index expression") ||
2722 parseToken(FIRToken::r_square,
"expected ']' in subscript"))
2728 return emitError(
"expected base type for index expression");
2729 indexType = indexType.getPassiveType();
2730 locationProcessor.setLoc(loc);
2735 SubaccessOp::inferReturnType(result.getType(), index.getType(), {});
2738 (void)SubaccessOp::inferReturnType(result.getType(), index.getType(),
2739 translateLocation(loc));
2744 auto op = SubaccessOp::create(builder, resultType, result, index);
2745 result = op.getResult();
2756FIRStmtParser::parseIntegerLiteralExp(Value &result,
bool isSigned,
2757 std::optional<int32_t> allocatedWidth) {
2758 auto loc = getToken().getLoc();
2761 bool hasLParen = getToken().isAny(FIRToken::lp_UInt, FIRToken::lp_SInt);
2766 int32_t width = allocatedWidth.value_or(-1);
2772 parseToken(FIRToken::l_paren,
"expected '(' in integer expression"))
2775 if (parseIntLit(value,
"expected integer value") ||
2776 parseToken(FIRToken::r_paren,
"expected ')' in integer expression"))
2781 auto type =
IntType::get(builder.getContext(), isSigned, width,
true);
2783 IntegerType::SignednessSemantics signedness =
2784 isSigned ? IntegerType::Signed : IntegerType::Unsigned;
2786 if (!value.isZero())
2787 return emitError(loc,
"zero bit constant must be zero");
2788 value = value.trunc(0);
2789 }
else if (width != -1) {
2791 bool valueFits = isSigned ? value.isSignedIntN(width) : value.isIntN(width);
2793 return emitError(loc,
"initializer too wide for declared width");
2794 value = isSigned ? value.sextOrTrunc(width) : value.zextOrTrunc(width);
2798 IntegerType::get(type.getContext(), value.getBitWidth(), signedness);
2799 auto attr = builder.getIntegerAttr(attrType, value);
2801 locationProcessor.setLoc(loc);
2802 result = moduleContext.getCachedConstant(builder, attr, type, attr);
2807ParseResult FIRStmtParser::parseListExp(Value &result) {
2808 auto loc = getToken().getLoc();
2809 bool hasLAngle = getToken().is(FIRToken::langle_List);
2810 bool hasLParen = getToken().is(FIRToken::lp_List);
2815 if (!hasLAngle && parseToken(FIRToken::less,
"expected '<' in List type"))
2818 if (parsePropertyType(
elementType,
"expected List element type") ||
2819 parseToken(FIRToken::greater,
"expected '>' in List type"))
2822 auto listType = ListType::get(getContext(),
elementType);
2826 parseToken(FIRToken::l_paren,
"expected '(' in List expression"))
2829 SmallVector<Value, 3> operands;
2830 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2832 locationProcessor.setLoc(loc);
2833 if (parseExp(operand,
"expected expression in List expression"))
2836 operand = emitImplicitAnyRefCast(operand,
elementType);
2838 return emitError(loc,
"unexpected expression of type ")
2839 << operand.getType() <<
" in List expression of type "
2842 operands.push_back(operand);
2847 locationProcessor.setLoc(loc);
2848 result = ListCreateOp::create(builder, listType, operands);
2853ParseResult FIRStmtParser::parseListConcatExp(Value &result) {
2854 consumeToken(FIRToken::lp_list_concat);
2856 auto loc = getToken().getLoc();
2858 SmallVector<Value, 3> operands;
2859 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2861 locationProcessor.setLoc(loc);
2862 if (parseExp(operand,
"expected expression in List concat expression"))
2866 return emitError(loc,
"unexpected expression of type ")
2867 << operand.getType() <<
" in List concat expression";
2872 if (operand.getType() != type)
2873 return emitError(loc,
"unexpected expression of type ")
2874 << operand.getType() <<
" in List concat expression of type "
2877 operands.push_back(operand);
2882 if (operands.empty())
2883 return emitError(loc,
"need at least one List to concatenate");
2885 locationProcessor.setLoc(loc);
2886 result = ListConcatOp::create(builder, type, operands);
2891ParseResult FIRStmtParser::parseCatExp(Value &result) {
2892 consumeToken(FIRToken::lp_cat);
2894 auto loc = getToken().getLoc();
2895 SmallVector<Value, 3> operands;
2896 std::optional<bool> isSigned;
2897 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2899 locationProcessor.setLoc(loc);
2900 auto operandLoc = getToken().getLoc();
2901 if (parseExp(operand,
"expected expression in cat expression"))
2904 auto diag = emitError(loc,
"all operands must be Int type");
2905 diag.attachNote(translateLocation(operandLoc))
2906 <<
"non-integer operand is here";
2912 auto diag = emitError(loc,
"all operands must have same signedness");
2913 diag.attachNote(translateLocation(operandLoc))
2914 <<
"operand with different signedness is here";
2918 operands.push_back(operand);
2923 if (operands.size() != 2) {
2924 if (requireFeature({6, 0, 0},
"variadic cat", loc))
2928 locationProcessor.setLoc(loc);
2929 result = CatPrimOp::create(builder, operands);
2934ParseResult FIRStmtParser::parseStringConcatExp(Value &result) {
2935 consumeToken(FIRToken::lp_string_concat);
2937 auto loc = getToken().getLoc();
2938 SmallVector<Value, 3> operands;
2939 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
2941 locationProcessor.setLoc(loc);
2942 if (parseExp(operand,
2943 "expected expression in string_concat expression"))
2946 return emitError(loc,
"all operands must be String type");
2947 operands.push_back(operand);
2952 if (operands.empty())
2953 return emitError(loc,
"need at least one String to concatenate");
2955 locationProcessor.setLoc(loc);
2956 auto type = StringType::get(builder.getContext());
2957 result = builder.create<StringConcatOp>(type, operands);
2962ParseResult FIRStmtParser::parsePropEqExp(Value &result) {
2963 consumeToken(FIRToken::lp_prop_eq);
2965 auto loc = getToken().getLoc();
2967 locationProcessor.setLoc(loc);
2968 if (parseExp(lhs,
"expected lhs expression in prop_eq expression") ||
2969 parseToken(FIRToken::comma,
"expected ','") ||
2970 parseExp(rhs,
"expected rhs expression in prop_eq expression") ||
2971 parseToken(FIRToken::r_paren,
"expected ')'"))
2974 auto isValidType = [](Type t) {
2978 if (!isValidType(lhs.getType()))
2979 return emitError(loc,
2980 "lhs of prop_eq must be String, Bool, or Integer type");
2981 if (!isValidType(rhs.getType()))
2982 return emitError(loc,
2983 "rhs of prop_eq must be String, Bool, or Integer type");
2984 if (lhs.getType() != rhs.getType())
2985 return emitError(loc,
"prop_eq operands must have the same type");
2987 locationProcessor.setLoc(loc);
2988 result = PropEqOp::create(builder, lhs, rhs);
2993ParseResult FIRStmtParser::parseObjectEqExp(Value &result) {
2994 consumeToken(FIRToken::lp_object_eq);
2996 auto loc = getToken().getLoc();
2998 locationProcessor.setLoc(loc);
2999 if (parseExp(lhs,
"expected lhs expression in object_eq expression") ||
3000 parseToken(FIRToken::comma,
"expected ','") ||
3001 parseExp(rhs,
"expected rhs expression in object_eq expression") ||
3002 parseToken(FIRToken::r_paren,
"expected ')'"))
3005 if (!isa<ClassType, AnyRefType>(lhs.getType()))
3006 return emitError(loc,
"lhs of object_eq must be Inst or AnyRef type");
3007 if (!isa<ClassType, AnyRefType>(rhs.getType()))
3008 return emitError(loc,
"rhs of object_eq must be Inst or AnyRef type");
3010 locationProcessor.setLoc(loc);
3011 result = ObjectEqOp::create(builder, lhs, rhs);
3016ParseResult FIRStmtParser::parseListContainsExp(Value &result) {
3017 consumeToken(FIRToken::lp_list_contains);
3019 auto loc = getToken().getLoc();
3020 Value list, element;
3021 locationProcessor.setLoc(loc);
3022 if (parseExp(list,
"expected list expression in list_contains expression") ||
3023 parseToken(FIRToken::comma,
"expected ','") ||
3025 "expected element expression in list_contains expression") ||
3026 parseToken(FIRToken::r_paren,
"expected ')'"))
3029 auto listType = dyn_cast<ListType>(list.getType());
3031 return emitError(loc,
"first operand of list_contains must be a List");
3035 return emitError(loc,
"list_contains element type ")
3036 << element.getType() <<
" does not match list element type "
3039 if (!isa<StringType, FIntegerType, BoolType>(
elementType))
3040 return emitError(loc,
"list_contains does not support elements of type ")
3043 locationProcessor.setLoc(loc);
3044 result = ListContainsOp::create(builder, list, element);
3048ParseResult FIRStmtParser::parseUnsafeDomainCast(Value &result) {
3049 consumeToken(FIRToken::lp_unsafe_domain_cast);
3051 auto loc = getToken().getLoc();
3053 if (parseExp(input,
"expected input"))
3056 SmallVector<Value> domains;
3057 if (consumeIf(FIRToken::comma)) {
3058 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
3060 if (parseExp(domain,
"expected domain"))
3062 domains.push_back(domain);
3066 }
else if (parseToken(FIRToken::r_paren,
"expected closing parenthesis")) {
3070 locationProcessor.setLoc(loc);
3071 result = UnsafeDomainCastOp::create(builder, input, domains);
3075ParseResult FIRStmtParser::parseUnknownProperty(Value &result) {
3076 auto loc = getToken().getLoc();
3077 consumeToken(FIRToken::lp_Unknown);
3081 if (parsePropertyType(type,
"expected property type") ||
3082 parseToken(FIRToken::r_paren,
"expected ')' in unknown property"))
3085 locationProcessor.setLoc(loc);
3086 result = UnknownValueOp::create(builder, type);
3107std::optional<ParseResult>
3108FIRStmtParser::parseExpWithLeadingKeyword(FIRToken keyword) {
3109 switch (getToken().getKind()) {
3112 return std::nullopt;
3114 case FIRToken::period:
3115 case FIRToken::l_square:
3116 case FIRToken::kw_is:
3117 case FIRToken::less_equal:
3123 auto loc = keyword.
getLoc();
3125 if (moduleContext.lookupSymbolEntry(symtabEntry, keyword.
getSpelling(), loc))
3126 return ParseResult(
failure());
3132 if (moduleContext.resolveSymbolEntry(lhs, symtabEntry, loc,
false)) {
3135 if (!consumeIf(FIRToken::period))
3136 return ParseResult(
failure());
3138 StringRef fieldName;
3139 if (parseFieldId(fieldName,
"expected field name") ||
3140 moduleContext.resolveSymbolEntry(lhs, symtabEntry, fieldName, loc))
3141 return ParseResult(
failure());
3145 if (parseOptionalExpPostscript(lhs))
3146 return ParseResult(
failure());
3148 return parseLeadingExpStmt(lhs);
3154ParseResult FIRStmtParser::parseSimpleStmtBlock(
unsigned indent) {
3157 if (getToken().isAny(FIRToken::eof, FIRToken::error))
3160 auto subIndent = getIndentation();
3161 if (!subIndent.has_value())
3162 return emitError(
"expected statement to be on its own line"),
failure();
3164 if (*subIndent <= indent)
3168 if (parseSimpleStmt(*subIndent))
3173ParseResult FIRStmtParser::parseSimpleStmt(
unsigned stmtIndent) {
3174 locationProcessor.startStatement();
3175 auto result = parseSimpleStmtImpl(stmtIndent);
3176 locationProcessor.endStatement(*
this);
3199ParseResult FIRStmtParser::parseSimpleStmtImpl(
unsigned stmtIndent) {
3200 auto kind = getToken().getKind();
3203 case FIRToken::kw_invalidate:
3204 case FIRToken::kw_connect:
3205 case FIRToken::kw_regreset:
3208 if (version < FIRVersion(3, 0, 0))
3209 kind = FIRToken::identifier;
3216 case FIRToken::kw_attach:
3217 return parseAttach();
3218 case FIRToken::kw_infer:
3219 return parseMemPort(MemDirAttr::Infer);
3220 case FIRToken::kw_read:
3221 return parseMemPort(MemDirAttr::Read);
3222 case FIRToken::kw_write:
3223 return parseMemPort(MemDirAttr::Write);
3224 case FIRToken::kw_rdwr:
3225 return parseMemPort(MemDirAttr::ReadWrite);
3226 case FIRToken::kw_connect:
3227 return parseConnect();
3228 case FIRToken::kw_propassert:
3229 if (requireFeature({6, 0, 0},
"property assertions"))
3231 return parsePropAssert();
3232 case FIRToken::kw_propassign:
3233 if (requireFeature({3, 1, 0},
"properties"))
3235 return parsePropAssign();
3236 case FIRToken::kw_invalidate:
3237 return parseInvalidate();
3238 case FIRToken::lp_printf:
3239 return parsePrintf();
3240 case FIRToken::lp_fprintf:
3241 return parseFPrintf();
3242 case FIRToken::lp_fflush:
3243 return parseFFlush();
3244 case FIRToken::kw_skip:
3246 case FIRToken::lp_stop:
3248 case FIRToken::lp_assert:
3249 return parseAssert();
3250 case FIRToken::lp_assume:
3251 return parseAssume();
3252 case FIRToken::lp_cover:
3253 return parseCover();
3254 case FIRToken::kw_when:
3255 return parseWhen(stmtIndent);
3256 case FIRToken::kw_match:
3257 return parseMatch(stmtIndent);
3258 case FIRToken::kw_domain:
3260 return parseDomainInstantiation();
3261 case FIRToken::kw_domain_define:
3262 return parseDomainDefine();
3263 case FIRToken::kw_define:
3264 return parseRefDefine();
3265 case FIRToken::lp_force:
3266 return parseRefForce();
3267 case FIRToken::lp_force_initial:
3268 return parseRefForceInitial();
3269 case FIRToken::lp_release:
3270 return parseRefRelease();
3271 case FIRToken::lp_release_initial:
3272 return parseRefReleaseInitial();
3273 case FIRToken::kw_group:
3274 if (requireFeature({3, 2, 0},
"optional groups") ||
3275 removedFeature({3, 3, 0},
"optional groups"))
3277 return parseLayerBlockOrGroup(stmtIndent);
3278 case FIRToken::kw_layerblock:
3279 if (requireFeature({3, 3, 0},
"layers"))
3281 return parseLayerBlockOrGroup(stmtIndent);
3282 case FIRToken::lp_intrinsic:
3283 if (requireFeature({4, 0, 0},
"generic intrinsics"))
3285 return parseIntrinsicStmt();
3289 if (parseExpLeadingStmt(lhs,
"unexpected token in module"))
3296 return parseLeadingExpStmt(lhs);
3300 case FIRToken::kw_inst:
3301 return parseInstance();
3302 case FIRToken::kw_instchoice:
3303 return parseInstanceChoice();
3304 case FIRToken::kw_object:
3305 return parseObject();
3306 case FIRToken::kw_cmem:
3307 return parseCombMem();
3308 case FIRToken::kw_smem:
3309 return parseSeqMem();
3310 case FIRToken::kw_mem:
3311 return parseMem(stmtIndent);
3312 case FIRToken::kw_node:
3314 case FIRToken::kw_wire:
3316 case FIRToken::kw_reg:
3317 return parseRegister(stmtIndent);
3318 case FIRToken::kw_regreset:
3319 return parseRegisterWithReset();
3320 case FIRToken::kw_contract:
3321 return parseContract(stmtIndent);
3325ParseResult FIRStmtParser::parseSubBlock(Block &blockToInsertInto,
3327 SymbolRefAttr layerSym) {
3329 auto suiteScope = std::make_unique<FIRModuleContext::ContextScope>(
3330 moduleContext, &blockToInsertInto);
3335 UnbundledValueRestorer x(moduleContext.unbundledValues);
3339 auto subParser = std::make_unique<FIRStmtParser>(
3340 blockToInsertInto, moduleContext, innerSymFixups, circuitSymTbl, version,
3344 auto stmtIndent = getIndentation();
3347 if (!stmtIndent.has_value())
3348 return subParser->parseSimpleStmt(indent);
3350 if (*stmtIndent <= indent)
3351 return emitError(
"statement must be indented more than previous statement"),
3355 return subParser->parseSimpleStmtBlock(indent);
3359ParseResult FIRStmtParser::parseAttach() {
3360 auto startTok = consumeToken(FIRToken::kw_attach);
3363 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3366 if (parseToken(FIRToken::l_paren,
"expected '(' after attach"))
3369 SmallVector<Value, 4> operands;
3370 operands.push_back({});
3371 if (parseExp(operands.back(),
"expected operand in attach"))
3374 while (consumeIf(FIRToken::comma)) {
3375 operands.push_back({});
3376 if (parseExp(operands.back(),
"expected operand in attach"))
3379 if (parseToken(FIRToken::r_paren,
"expected close paren"))
3382 if (parseOptionalInfo())
3385 locationProcessor.setLoc(startTok.getLoc());
3386 AttachOp::create(builder, operands);
3393ParseResult FIRStmtParser::parseMemPort(MemDirAttr direction) {
3394 auto startTok = consumeToken();
3395 auto startLoc = startTok.getLoc();
3399 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3405 Value memory, indexExp, clock;
3406 if (parseToken(FIRToken::kw_mport,
"expected 'mport' in memory port") ||
3407 parseId(
id,
"expected result name") ||
3408 parseToken(FIRToken::equal,
"expected '=' in memory port") ||
3409 parseId(memName,
"expected memory name") ||
3410 moduleContext.lookupSymbolEntry(memorySym, memName, startLoc) ||
3411 moduleContext.resolveSymbolEntry(memory, memorySym, startLoc) ||
3412 parseToken(FIRToken::l_square,
"expected '[' in memory port") ||
3413 parseExp(indexExp,
"expected index expression") ||
3414 parseToken(FIRToken::r_square,
"expected ']' in memory port") ||
3415 parseToken(FIRToken::comma,
"expected ','") ||
3416 parseExp(clock,
"expected clock expression") || parseOptionalInfo())
3421 return emitError(startLoc,
3422 "memory port should have behavioral memory type");
3423 auto resultType = memVType.getElementType();
3425 ArrayAttr annotations = getConstants().emptyArrayAttr;
3426 locationProcessor.setLoc(startLoc);
3429 Value memoryPort, memoryData;
3431 OpBuilder::InsertionGuard guard(builder);
3432 builder.setInsertionPointAfterValue(memory);
3433 auto memoryPortOp = MemoryPortOp::create(
3434 builder, resultType, CMemoryPortType::get(getContext()), memory,
3435 direction,
id, annotations);
3436 memoryData = memoryPortOp.getResult(0);
3437 memoryPort = memoryPortOp.getResult(1);
3441 MemoryPortAccessOp::create(builder, memoryPort, indexExp, clock);
3443 return moduleContext.addSymbolEntry(
id, memoryData, startLoc,
true);
3449ParseResult FIRStmtParser::parseFormatString(SMLoc formatStringLoc,
3450 StringRef formatString,
3451 ArrayRef<Value> specOperands,
3452 StringAttr &formatStringResult,
3453 SmallVectorImpl<Value> &operands) {
3455 if (version < FIRVersion(5, 0, 0)) {
3456 operands.append(specOperands.begin(), specOperands.end());
3457 formatStringResult =
3463 auto loc = translateLocation(formatStringLoc);
3466 formatStringResult, operands);
3471ParseResult FIRStmtParser::parsePrintf() {
3472 auto startTok = consumeToken(FIRToken::lp_printf);
3474 Value clock, condition;
3475 StringRef formatString;
3476 if (parseExp(clock,
"expected clock expression in printf") ||
3477 parseToken(FIRToken::comma,
"expected ','") ||
3478 parseExp(condition,
"expected condition in printf") ||
3479 parseToken(FIRToken::comma,
"expected ','"))
3482 auto formatStringLoc = getToken().getLoc();
3483 if (parseGetSpelling(formatString) ||
3484 parseToken(FIRToken::string,
"expected format string in printf"))
3487 SmallVector<Value, 4> specOperands;
3488 while (consumeIf(FIRToken::comma)) {
3489 specOperands.push_back({});
3490 if (parseExp(specOperands.back(),
"expected operand in printf"))
3495 if (parseToken(FIRToken::r_paren,
"expected ')'") ||
3496 parseOptionalName(name) || parseOptionalInfo())
3499 locationProcessor.setLoc(startTok.getLoc());
3501 StringAttr formatStrUnescaped;
3502 SmallVector<Value> operands;
3504 formatStrUnescaped, operands))
3507 PrintFOp::create(builder, clock, condition, formatStrUnescaped, operands,
3513ParseResult FIRStmtParser::parseFPrintf() {
3514 if (requireFeature({6, 0, 0},
"fprintf"))
3516 auto startTok = consumeToken(FIRToken::lp_fprintf);
3518 Value clock, condition;
3519 StringRef outputFile, formatString;
3520 if (parseExp(clock,
"expected clock expression in fprintf") ||
3521 parseToken(FIRToken::comma,
"expected ','") ||
3522 parseExp(condition,
"expected condition in fprintf") ||
3523 parseToken(FIRToken::comma,
"expected ','"))
3526 auto outputFileLoc = getToken().getLoc();
3527 if (parseGetSpelling(outputFile) ||
3528 parseToken(FIRToken::string,
"expected output file in fprintf"))
3531 SmallVector<Value, 4> outputFileSpecOperands;
3532 while (consumeIf(FIRToken::comma)) {
3534 if (getToken().getKind() == FIRToken::string)
3536 outputFileSpecOperands.push_back({});
3537 if (parseExp(outputFileSpecOperands.back(),
"expected operand in fprintf"))
3541 auto formatStringLoc = getToken().getLoc();
3542 if (parseGetSpelling(formatString) ||
3543 parseToken(FIRToken::string,
"expected format string in printf"))
3546 SmallVector<Value, 4> specOperands;
3547 while (consumeIf(FIRToken::comma)) {
3548 specOperands.push_back({});
3549 if (parseExp(specOperands.back(),
"expected operand in fprintf"))
3554 if (parseToken(FIRToken::r_paren,
"expected ')'") ||
3555 parseOptionalName(name) || parseOptionalInfo())
3558 locationProcessor.setLoc(startTok.getLoc());
3560 StringAttr outputFileNameStrUnescaped;
3561 SmallVector<Value> outputFileOperands;
3563 outputFileNameStrUnescaped, outputFileOperands))
3566 StringAttr formatStrUnescaped;
3567 SmallVector<Value> operands;
3569 formatStrUnescaped, operands))
3572 FPrintFOp::create(builder, clock, condition, outputFileNameStrUnescaped,
3573 outputFileOperands, formatStrUnescaped, operands, name);
3578ParseResult FIRStmtParser::parseFFlush() {
3579 if (requireFeature({6, 0, 0},
"fflush"))
3582 auto startTok = consumeToken(FIRToken::lp_fflush);
3584 Value clock, condition;
3585 if (parseExp(clock,
"expected clock expression in 'fflush'") ||
3586 parseToken(FIRToken::comma,
"expected ','") ||
3587 parseExp(condition,
"expected condition in 'fflush'"))
3590 locationProcessor.setLoc(startTok.getLoc());
3591 StringAttr outputFileNameStrUnescaped;
3592 SmallVector<Value> outputFileOperands;
3594 if (consumeIf(FIRToken::comma)) {
3595 SmallVector<Value, 4> outputFileSpecOperands;
3596 auto outputFileLoc = getToken().getLoc();
3597 StringRef outputFile;
3598 if (parseGetSpelling(outputFile) ||
3599 parseToken(FIRToken::string,
"expected output file in fflush"))
3602 while (consumeIf(FIRToken::comma)) {
3603 outputFileSpecOperands.push_back({});
3604 if (parseExp(outputFileSpecOperands.back(),
"expected operand in fflush"))
3609 outputFileNameStrUnescaped, outputFileOperands))
3613 if (parseToken(FIRToken::r_paren,
"expected ')' in 'fflush'") ||
3614 parseOptionalInfo())
3617 FFlushOp::create(builder, clock, condition, outputFileNameStrUnescaped,
3618 outputFileOperands);
3623ParseResult FIRStmtParser::parseSkip() {
3624 auto startTok = consumeToken(FIRToken::kw_skip);
3628 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3631 if (parseOptionalInfo())
3634 locationProcessor.setLoc(startTok.getLoc());
3635 SkipOp::create(builder);
3640ParseResult FIRStmtParser::parseStop() {
3641 auto startTok = consumeToken(FIRToken::lp_stop);
3643 Value clock, condition;
3646 if (parseExp(clock,
"expected clock expression in 'stop'") ||
3647 parseToken(FIRToken::comma,
"expected ','") ||
3648 parseExp(condition,
"expected condition in 'stop'") ||
3649 parseToken(FIRToken::comma,
"expected ','") ||
3650 parseIntLit(exitCode,
"expected exit code in 'stop'") ||
3651 parseToken(FIRToken::r_paren,
"expected ')' in 'stop'") ||
3652 parseOptionalName(name) || parseOptionalInfo())
3655 locationProcessor.setLoc(startTok.getLoc());
3656 StopOp::create(builder, clock, condition, builder.getI32IntegerAttr(exitCode),
3662ParseResult FIRStmtParser::parseAssert() {
3663 auto startTok = consumeToken(FIRToken::lp_assert);
3665 Value clock, predicate, enable;
3666 StringRef formatString;
3668 if (parseExp(clock,
"expected clock expression in 'assert'") ||
3669 parseToken(FIRToken::comma,
"expected ','") ||
3670 parseExp(predicate,
"expected predicate in 'assert'") ||
3671 parseToken(FIRToken::comma,
"expected ','") ||
3672 parseExp(enable,
"expected enable in 'assert'") ||
3673 parseToken(FIRToken::comma,
"expected ','") ||
3674 parseGetSpelling(formatString) ||
3675 parseToken(FIRToken::string,
"expected format string in 'assert'"))
3678 SmallVector<Value, 4> operands;
3679 while (!consumeIf(FIRToken::r_paren)) {
3680 operands.push_back({});
3681 if (parseToken(FIRToken::comma,
"expected ','") ||
3682 parseExp(operands.back(),
"expected operand in 'assert'"))
3686 if (parseOptionalName(name) || parseOptionalInfo())
3689 locationProcessor.setLoc(startTok.getLoc());
3691 AssertOp::create(builder, clock, predicate, enable, formatStrUnescaped,
3692 operands, name.getValue());
3697ParseResult FIRStmtParser::parseAssume() {
3698 auto startTok = consumeToken(FIRToken::lp_assume);
3700 Value clock, predicate, enable;
3701 StringRef formatString;
3703 if (parseExp(clock,
"expected clock expression in 'assume'") ||
3704 parseToken(FIRToken::comma,
"expected ','") ||
3705 parseExp(predicate,
"expected predicate in 'assume'") ||
3706 parseToken(FIRToken::comma,
"expected ','") ||
3707 parseExp(enable,
"expected enable in 'assume'") ||
3708 parseToken(FIRToken::comma,
"expected ','") ||
3709 parseGetSpelling(formatString) ||
3710 parseToken(FIRToken::string,
"expected format string in 'assume'"))
3713 SmallVector<Value, 4> operands;
3714 while (!consumeIf(FIRToken::r_paren)) {
3715 operands.push_back({});
3716 if (parseToken(FIRToken::comma,
"expected ','") ||
3717 parseExp(operands.back(),
"expected operand in 'assume'"))
3721 if (parseOptionalName(name) || parseOptionalInfo())
3724 locationProcessor.setLoc(startTok.getLoc());
3726 AssumeOp::create(builder, clock, predicate, enable, formatStrUnescaped,
3727 operands, name.getValue());
3732ParseResult FIRStmtParser::parseCover() {
3733 auto startTok = consumeToken(FIRToken::lp_cover);
3735 Value clock, predicate, enable;
3738 if (parseExp(clock,
"expected clock expression in 'cover'") ||
3739 parseToken(FIRToken::comma,
"expected ','") ||
3740 parseExp(predicate,
"expected predicate in 'cover'") ||
3741 parseToken(FIRToken::comma,
"expected ','") ||
3742 parseExp(enable,
"expected enable in 'cover'") ||
3743 parseToken(FIRToken::comma,
"expected ','") ||
3744 parseGetSpelling(message) ||
3745 parseToken(FIRToken::string,
"expected message in 'cover'") ||
3746 parseToken(FIRToken::r_paren,
"expected ')' in 'cover'") ||
3747 parseOptionalName(name) || parseOptionalInfo())
3750 locationProcessor.setLoc(startTok.getLoc());
3752 CoverOp::create(builder, clock, predicate, enable, messageUnescaped,
3753 ValueRange{}, name.getValue());
3759ParseResult FIRStmtParser::parseWhen(
unsigned whenIndent) {
3760 auto startTok = consumeToken(FIRToken::kw_when);
3764 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3768 if (parseExp(condition,
"expected condition in 'when'") ||
3769 parseToken(FIRToken::colon,
"expected ':' in when") ||
3770 parseOptionalInfo())
3773 locationProcessor.setLoc(startTok.getLoc());
3775 auto whenStmt = WhenOp::create(builder, condition,
false);
3778 if (parseSubBlock(whenStmt.getThenBlock(), whenIndent, layerSym))
3782 if (getToken().isNot(FIRToken::kw_else))
3787 auto elseIndent = getIndentation();
3788 if (elseIndent && *elseIndent < whenIndent)
3791 consumeToken(FIRToken::kw_else);
3794 whenStmt.createElseRegion();
3800 if (getToken().is(FIRToken::kw_when)) {
3802 auto subParser = std::make_unique<FIRStmtParser>(
3803 whenStmt.getElseBlock(), moduleContext, innerSymFixups, circuitSymTbl,
3806 return subParser->parseSimpleStmt(whenIndent);
3810 LocationAttr elseLoc;
3811 if (parseToken(FIRToken::colon,
"expected ':' after 'else'") ||
3812 parseOptionalInfoLocator(elseLoc) ||
3813 parseSubBlock(whenStmt.getElseBlock(), whenIndent, layerSym))
3822ParseResult FIRStmtParser::parseEnumExp(Value &value) {
3823 auto startLoc = getToken().getLoc();
3824 locationProcessor.setLoc(startLoc);
3826 if (parseEnumType(type))
3832 return emitError(startLoc,
3833 "expected enumeration type in enumeration expression");
3836 if (parseToken(FIRToken::l_paren,
"expected '(' in enumeration expression") ||
3837 parseId(tag,
"expected enumeration tag"))
3841 if (consumeIf(FIRToken::r_paren)) {
3844 auto type =
IntType::get(builder.getContext(),
false, 0,
true);
3845 Type attrType = IntegerType::get(getContext(), 0, IntegerType::Unsigned);
3846 auto attr = builder.getIntegerAttr(attrType, APInt(0, 0,
false));
3847 input = ConstantOp::create(builder, type, attr);
3850 if (parseToken(FIRToken::comma,
"expected ','") ||
3851 parseExp(input,
"expected expression in enumeration value") ||
3852 parseToken(FIRToken::r_paren,
"expected closing ')'"))
3856 value = FEnumCreateOp::create(builder, enumType, tag, input);
3864ParseResult FIRStmtParser::parseMatch(
unsigned matchIndent) {
3865 auto startTok = consumeToken(FIRToken::kw_match);
3867 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
3871 if (parseExp(input,
"expected expression in 'match'") ||
3872 parseToken(FIRToken::colon,
"expected ':' in 'match'") ||
3873 parseOptionalInfo())
3878 return mlir::emitError(
3880 "expected enumeration type for 'match' statement, but got ")
3883 locationProcessor.setLoc(startTok.getLoc());
3885 SmallVector<Attribute> tags;
3886 SmallVector<std::unique_ptr<Region>> regions;
3888 auto tagLoc = getToken().getLoc();
3891 auto caseIndent = getIndentation();
3892 if (!caseIndent || *caseIndent <= matchIndent)
3896 StringRef tagSpelling;
3897 if (parseId(tagSpelling,
"expected enumeration tag in match statement"))
3899 auto tagIndex = enumType.getElementIndex(tagSpelling);
3901 return emitError(tagLoc,
"tag ")
3902 << tagSpelling <<
" not a member of enumeration " << enumType;
3903 auto tag = IntegerAttr::get(IntegerType::get(getContext(), 32), *tagIndex);
3904 tags.push_back(tag);
3907 auto *caseBlock = ®ions.emplace_back(
new Region)->emplaceBlock();
3910 FIRModuleContext::ContextScope scope(moduleContext, caseBlock);
3915 UnbundledValueRestorer x(moduleContext.unbundledValues);
3918 if (consumeIf(FIRToken::l_paren)) {
3919 StringAttr identifier;
3920 if (parseId(identifier,
"expected identifier for 'case' binding"))
3924 auto dataType = enumType.getElementType(*tagIndex);
3925 caseBlock->addArgument(dataType, LocWithInfo(tagLoc,
this).
getLoc());
3927 if (moduleContext.addSymbolEntry(identifier, caseBlock->getArgument(0),
3931 if (parseToken(FIRToken::r_paren,
"expected ')' in match statement case"))
3935 auto dataType =
IntType::get(builder.getContext(),
false, 0);
3936 caseBlock->addArgument(dataType, LocWithInfo(tagLoc,
this).
getLoc());
3939 if (parseToken(FIRToken::colon,
"expected ':' in match statement case"))
3943 auto subParser = std::make_unique<FIRStmtParser>(
3944 *caseBlock, moduleContext, innerSymFixups, circuitSymTbl, version,
3946 if (subParser->parseSimpleStmtBlock(*caseIndent))
3950 MatchOp::create(builder, input, ArrayAttr::get(getContext(), tags), regions);
3957ParseResult FIRStmtParser::parseDomainExp(Value &result) {
3958 auto loc = getToken().getLoc();
3961 if (parseId(
id,
"expected domain expression") ||
3962 moduleContext.lookupSymbolEntry(entry,
id, loc))
3965 if (moduleContext.resolveSymbolEntry(result, entry, loc,
false)) {
3967 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
3968 parseFieldId(field,
"expected field name") ||
3969 moduleContext.resolveSymbolEntry(result, entry, field, loc))
3973 if (parseOptionalExpPostscript(result,
false))
3976 auto type = result.getType();
3978 return emitError(loc) <<
"expected domain-type expression, got " << type;
3989ParseResult FIRStmtParser::parseRefExp(Value &result,
const Twine &message) {
3990 auto token = getToken().getKind();
3991 if (token == FIRToken::lp_probe)
3992 return failure(parseProbe(result) ||
3993 parseOptionalExpPostscript(result,
false));
3994 if (token == FIRToken::lp_rwprobe)
3995 return failure(parseRWProbe(result) ||
3996 parseOptionalExpPostscript(result,
false));
4001 return parseStaticRefExp(result, message);
4008ParseResult FIRStmtParser::parseStaticRefExp(Value &result,
4009 const Twine &message) {
4010 auto parseIdOrInstance = [&]() -> ParseResult {
4012 auto loc = getToken().getLoc();
4014 if (parseId(
id, message) ||
4015 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
4019 if (!moduleContext.resolveSymbolEntry(result, symtabEntry, loc,
false))
4022 assert(isa<UnbundledID>(symtabEntry) &&
"should be an instance");
4025 StringRef fieldName;
4027 parseToken(FIRToken::period,
"expected '.' in field reference") ||
4028 parseFieldId(fieldName,
"expected field name") ||
4029 moduleContext.resolveSymbolEntry(result, symtabEntry, fieldName, loc));
4031 return failure(parseIdOrInstance() ||
4032 parseOptionalExpPostscript(result,
false));
4043ParseResult FIRStmtParser::parseRWProbeStaticRefExp(FieldRef &refResult,
4045 const Twine &message) {
4046 auto loc = getToken().getLoc();
4050 if (parseId(
id, message) ||
4051 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
4063 if (
auto unbundledId = dyn_cast<UnbundledID>(symtabEntry)) {
4065 auto &ubEntry = moduleContext.getUnbundledEntry(unbundledId - 1);
4067 StringRef fieldName;
4068 auto loc = getToken().getLoc();
4069 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
4070 parseFieldId(fieldName,
"expected field name"))
4075 auto fieldAttr = StringAttr::get(getContext(), fieldName);
4076 for (
auto &elt : ubEntry) {
4077 if (elt.first == fieldAttr) {
4080 auto &instResult = elt.second;
4083 auto *defining = instResult.getDefiningOp();
4085 if (isa<WireOp>(defining)) {
4086 result = instResult;
4091 auto type = instResult.getType();
4095 auto annotations = getConstants().emptyArrayAttr;
4096 StringAttr sym = {};
4097 SmallString<64> name;
4098 (
id +
"_" + fieldName +
"_bounce").
toVector(name);
4099 locationProcessor.setLoc(loc);
4100 OpBuilder::InsertionGuard guard(builder);
4101 builder.setInsertionPoint(defining);
4103 WireOp::create(builder, type, name, NameKindEnum::InterestingName,
4105 auto bounceVal = bounce.getDataRaw();
4108 instResult.replaceAllUsesWith(bounceVal);
4111 builder.setInsertionPointAfter(defining);
4112 if (
foldFlow(instResult) == Flow::Source)
4114 getConstants().options.warnOnTruncation);
4117 getConstants().options.warnOnTruncation);
4121 result = instResult = bounce.getDataRaw();
4127 emitError(loc,
"use of invalid field name '")
4128 << fieldName <<
"' on bundle value";
4133 result = cast<Value>(symtabEntry);
4137 assert(isa<BlockArgument>(result) ||
4138 result.getDefiningOp<hw::InnerSymbolOpInterface>());
4143 refResult = FieldRef(result, 0);
4144 type = result.getType();
4146 if (consumeIf(FIRToken::period)) {
4147 SmallVector<StringRef, 3> fields;
4148 if (parseFieldIdSeq(fields,
"expected field name"))
4150 for (
auto fieldName : fields) {
4152 if (
auto index = bundle.getElementIndex(fieldName)) {
4153 refResult = refResult.
getSubField(bundle.getFieldID(*index));
4154 type = bundle.getElementTypePreservingConst(*index);
4158 if (
auto index = bundle.getElementIndex(fieldName)) {
4159 refResult = refResult.
getSubField(bundle.getFieldID(*index));
4160 type = bundle.getElementTypePreservingConst(*index);
4164 return emitError(loc,
"subfield requires bundle operand")
4165 <<
"got " << type <<
"\n";
4167 return emitError(loc,
4168 "unknown field '" + fieldName +
"' in bundle type ")
4173 if (consumeIf(FIRToken::l_square)) {
4174 auto loc = getToken().getLoc();
4176 if (parseIntLit(index,
"expected index") ||
4177 parseToken(FIRToken::r_square,
"expected ']'"))
4181 return emitError(loc,
"invalid index specifier");
4184 if ((
unsigned)index < vector.getNumElements()) {
4185 refResult = refResult.
getSubField(vector.getFieldID(index));
4186 type = vector.getElementTypePreservingConst();
4190 if ((
unsigned)index < vector.getNumElements()) {
4191 refResult = refResult.
getSubField(vector.getFieldID(index));
4192 type = vector.getElementTypePreservingConst();
4196 return emitError(loc,
"subindex requires vector operand");
4198 return emitError(loc,
"out of range index '")
4199 << index <<
"' for vector type " << type;
4207ParseResult FIRStmtParser::parseIntrinsic(Value &result,
bool isStatement) {
4208 auto startTok = consumeToken(FIRToken::lp_intrinsic);
4209 StringRef intrinsic;
4210 ArrayAttr parameters;
4213 if (parseId(intrinsic,
"expected intrinsic identifier") ||
4214 parseOptionalParams(parameters))
4217 if (consumeIf(FIRToken::colon)) {
4218 if (
parseType(type,
"expected intrinsic return type"))
4220 }
else if (!isStatement)
4221 return emitError(
"expected ':' in intrinsic expression");
4223 SmallVector<Value> operands;
4224 auto loc = startTok.getLoc();
4225 if (consumeIf(FIRToken::comma)) {
4226 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
4228 if (parseExp(operand,
"expected operand in intrinsic"))
4230 operands.push_back(operand);
4231 locationProcessor.setLoc(loc);
4236 if (parseToken(FIRToken::r_paren,
"expected ')' in intrinsic"))
4241 if (parseOptionalInfo())
4244 locationProcessor.setLoc(loc);
4246 auto op = GenericIntrinsicOp::create(
4247 builder, type, builder.getStringAttr(intrinsic), operands, parameters);
4249 result = op.getResult();
4254ParseResult FIRStmtParser::parseOptionalParams(ArrayAttr &resultParameters) {
4255 if (!consumeIf(FIRToken::less))
4258 SmallVector<Attribute, 8> parameters;
4259 SmallPtrSet<StringAttr, 8> seen;
4260 if (parseListUntil(FIRToken::greater, [&]() -> ParseResult {
4264 if (parseParameter(name, value, loc))
4266 auto typedValue = dyn_cast<TypedAttr>(value);
4268 return emitError(loc)
4269 <<
"invalid value for parameter '" << name.getValue() <<
"'";
4270 if (!seen.insert(name).second)
4271 return emitError(loc,
"redefinition of parameter '" +
4272 name.getValue() +
"'");
4273 parameters.push_back(ParamDeclAttr::get(name, typedValue));
4278 resultParameters = ArrayAttr::get(getContext(), parameters);
4284ParseResult FIRStmtParser::parsePathExp(Value &result) {
4285 auto startTok = consumeToken(FIRToken::lp_path);
4286 locationProcessor.setLoc(startTok.getLoc());
4288 if (parseGetSpelling(target) ||
4289 parseToken(FIRToken::string,
4290 "expected target string in path expression") ||
4291 parseToken(FIRToken::r_paren,
"expected ')' in path expression"))
4293 result = UnresolvedPathOp::create(
4299ParseResult FIRStmtParser::parseDomainInstantiation() {
4300 auto startTok = consumeToken(FIRToken::kw_domain);
4301 auto startLoc = startTok.getLoc();
4304 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4307 locationProcessor.setLoc(startTok.getLoc());
4309 StringAttr instanceName;
4310 StringAttr domainKind;
4313 parseId(instanceName,
"expected domain instance name") ||
4314 parseToken(FIRToken::kw_of,
"expected 'of' after domain instance name") ||
4315 parseId(domainKind,
"expected domain type name"))
4320 const auto &domainMap = getConstants().domainMap;
4321 auto lookup = domainMap.find(domainKind.getValue());
4322 if (lookup == domainMap.end())
4323 return emitError(startTok.getLoc())
4324 <<
"unknown domain '" << domainKind.getValue() <<
"'";
4326 auto domainType = DomainType::getFromDomainOp(lookup->second);
4327 auto fields = domainType.getFields();
4330 SmallVector<Value> fieldValues;
4331 if (consumeIf(FIRToken::l_paren)) {
4333 if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult {
4334 if (fieldValues.size() >= fields.size())
4335 return emitError(getToken().
getLoc())
4336 <<
"too many field values for domain '"
4337 << domainKind.getValue() <<
"': expected " << fields.size();
4340 if (parseExp(value,
"expected field value expression"))
4343 value = emitImplicitAnyRefCast(
4345 cast<DomainFieldAttr>(fields[fieldValues.size()]).getType());
4347 fieldValues.push_back(value);
4353 if (parseOptionalInfo())
4356 if (fieldValues.size() < fields.size())
4357 return emitError(startLoc)
4358 <<
"not enough field values for domain '" << domainKind.getValue()
4359 <<
"': expected " << fields.size() <<
", got " << fieldValues.size();
4361 locationProcessor.setLoc(startLoc);
4363 DomainCreateOp::create(builder, domainType, instanceName, fieldValues);
4366 return moduleContext.addSymbolEntry(instanceName.getValue(), result,
4371ParseResult FIRStmtParser::parseDomainDefine() {
4372 auto startTok = consumeToken(FIRToken::kw_domain_define);
4373 auto startLoc = startTok.getLoc();
4374 locationProcessor.setLoc(startLoc);
4378 parseDomainExp(dest) || parseToken(FIRToken::equal,
"expected '='") ||
4379 parseDomainExp(src) || parseOptionalInfo())
4382 emitConnect(builder, dest, src, getConstants().options.warnOnTruncation);
4387ParseResult FIRStmtParser::parseRefDefine() {
4388 auto startTok = consumeToken(FIRToken::kw_define);
4391 if (parseStaticRefExp(target,
4392 "expected static reference expression in 'define'") ||
4393 parseToken(FIRToken::equal,
4394 "expected '=' after define reference expression") ||
4395 parseRefExp(src,
"expected reference expression in 'define'") ||
4396 parseOptionalInfo())
4401 return emitError(startTok.getLoc(),
"expected reference-type expression in "
4402 "'define' target (LHS), got ")
4403 << target.getType();
4405 return emitError(startTok.getLoc(),
"expected reference-type expression in "
4406 "'define' source (RHS), got ")
4411 if (isa_and_nonnull<RefSubOp>(target.getDefiningOp()))
4412 return emitError(startTok.getLoc(),
4413 "cannot define into a sub-element of a reference");
4415 locationProcessor.setLoc(startTok.getLoc());
4418 return emitError(startTok.getLoc(),
"cannot define reference of type ")
4419 << target.getType() <<
" with incompatible reference of type "
4422 emitConnect(builder, target, src, getConstants().options.warnOnTruncation);
4428ParseResult FIRStmtParser::parseRefRead(Value &result) {
4429 auto startTok = consumeToken(FIRToken::lp_read);
4432 if (parseRefExp(ref,
"expected reference expression in 'read'") ||
4433 parseToken(FIRToken::r_paren,
"expected ')' in 'read'"))
4436 locationProcessor.setLoc(startTok.getLoc());
4440 return emitError(startTok.getLoc(),
4441 "expected reference-type expression in 'read', got ")
4444 result = RefResolveOp::create(builder, ref);
4450ParseResult FIRStmtParser::parseProbe(Value &result) {
4451 auto startTok = consumeToken(FIRToken::lp_probe);
4454 if (parseStaticRefExp(staticRef,
4455 "expected static reference expression in 'probe'") ||
4456 parseToken(FIRToken::r_paren,
"expected ')' in 'probe'"))
4459 locationProcessor.setLoc(startTok.getLoc());
4463 return emitError(startTok.getLoc(),
4464 "expected base-type expression in 'probe', got ")
4465 << staticRef.getType();
4469 if (isa_and_nonnull<MemOp, CombMemOp, SeqMemOp, MemoryPortOp,
4470 MemoryDebugPortOp, MemoryPortAccessOp>(
4471 staticRef.getDefiningOp()))
4472 return emitError(startTok.getLoc(),
"cannot probe memories or their ports");
4474 result = RefSendOp::create(builder, staticRef);
4480ParseResult FIRStmtParser::parseRWProbe(Value &result) {
4481 auto startTok = consumeToken(FIRToken::lp_rwprobe);
4484 Type parsedTargetType;
4485 if (parseRWProbeStaticRefExp(
4486 staticRef, parsedTargetType,
4487 "expected static reference expression in 'rwprobe'") ||
4488 parseToken(FIRToken::r_paren,
"expected ')' in 'rwprobe'"))
4491 locationProcessor.setLoc(startTok.getLoc());
4499 return emitError(startTok.getLoc(),
4500 "expected base-type expression in 'rwprobe', got ")
4501 << parsedTargetType;
4504 auto *definingOp = root.getDefiningOp();
4506 if (isa_and_nonnull<MemOp, CombMemOp, SeqMemOp, MemoryPortOp,
4507 MemoryDebugPortOp, MemoryPortAccessOp>(definingOp))
4508 return emitError(startTok.getLoc(),
"cannot probe memories or their ports");
4512 return emitError(startTok.getLoc(),
"cannot force target of type ")
4516 auto op = RWProbeOp::create(builder, forceableType,
4517 getConstants().placeholderInnerRef);
4524ParseResult FIRStmtParser::parseRefForce() {
4525 auto startTok = consumeToken(FIRToken::lp_force);
4527 Value clock, pred, dest, src;
4528 if (parseExp(clock,
"expected clock expression in force") ||
4529 parseToken(FIRToken::comma,
"expected ','") ||
4530 parseExp(pred,
"expected predicate expression in force") ||
4531 parseToken(FIRToken::comma,
"expected ','") ||
4532 parseRefExp(dest,
"expected destination reference expression in force") ||
4533 parseToken(FIRToken::comma,
"expected ','") ||
4534 parseExp(src,
"expected source expression in force") ||
4535 parseToken(FIRToken::r_paren,
"expected ')' in force") ||
4536 parseOptionalInfo())
4541 if (!ref || !ref.getForceable())
4544 "expected rwprobe-type expression for force destination, got ")
4548 return emitError(startTok.getLoc(),
4549 "expected base-type for force source, got ")
4551 if (!srcBaseType.isPassive())
4552 return emitError(startTok.getLoc(),
4553 "expected passive value for force source, got ")
4556 locationProcessor.setLoc(startTok.getLoc());
4559 auto noConstSrcType = srcBaseType.getAllConstDroppedType();
4560 if (noConstSrcType != ref.getType()) {
4562 auto compatibleRWProbe = RefType::get(noConstSrcType,
true, ref.getLayer());
4564 dest = RefCastOp::create(builder, compatibleRWProbe, dest);
4566 return emitError(startTok.getLoc(),
"incompatible force source of type ")
4567 << src.getType() <<
" cannot target destination "
4571 RefForceOp::create(builder, clock, pred, dest, src);
4577ParseResult FIRStmtParser::parseRefForceInitial() {
4578 auto startTok = consumeToken(FIRToken::lp_force_initial);
4582 dest,
"expected destination reference expression in force_initial") ||
4583 parseToken(FIRToken::comma,
"expected ','") ||
4584 parseExp(src,
"expected source expression in force_initial") ||
4585 parseToken(FIRToken::r_paren,
"expected ')' in force_initial") ||
4586 parseOptionalInfo())
4591 if (!ref || !ref.getForceable())
4592 return emitError(startTok.getLoc(),
"expected rwprobe-type expression for "
4593 "force_initial destination, got ")
4597 return emitError(startTok.getLoc(),
4598 "expected base-type expression for force_initial "
4601 if (!srcBaseType.isPassive())
4602 return emitError(startTok.getLoc(),
4603 "expected passive value for force_initial source, got ")
4606 locationProcessor.setLoc(startTok.getLoc());
4609 auto noConstSrcType = srcBaseType.getAllConstDroppedType();
4610 if (noConstSrcType != ref.getType()) {
4612 auto compatibleRWProbe = RefType::get(noConstSrcType,
true, ref.getLayer());
4614 dest = RefCastOp::create(builder, compatibleRWProbe, dest);
4616 return emitError(startTok.getLoc(),
4617 "incompatible force_initial source of type ")
4618 << src.getType() <<
" cannot target destination "
4622 auto value = APInt::getAllOnes(1);
4623 auto type = UIntType::get(builder.getContext(), 1);
4624 auto attr = builder.getIntegerAttr(IntegerType::get(type.getContext(),
4625 value.getBitWidth(),
4626 IntegerType::Unsigned),
4628 auto pred = moduleContext.getCachedConstant(builder, attr, type, attr);
4629 RefForceInitialOp::create(builder, pred, dest, src);
4635ParseResult FIRStmtParser::parseRefRelease() {
4636 auto startTok = consumeToken(FIRToken::lp_release);
4638 Value clock, pred, dest;
4639 if (parseExp(clock,
"expected clock expression in release") ||
4640 parseToken(FIRToken::comma,
"expected ','") ||
4641 parseExp(pred,
"expected predicate expression in release") ||
4642 parseToken(FIRToken::comma,
"expected ','") ||
4644 "expected destination reference expression in release") ||
4645 parseToken(FIRToken::r_paren,
"expected ')' in release") ||
4646 parseOptionalInfo())
4651 !ref || !ref.getForceable())
4654 "expected rwprobe-type expression for release destination, got ")
4657 locationProcessor.setLoc(startTok.getLoc());
4659 RefReleaseOp::create(builder, clock, pred, dest);
4665ParseResult FIRStmtParser::parseRefReleaseInitial() {
4666 auto startTok = consumeToken(FIRToken::lp_release_initial);
4671 "expected destination reference expression in release_initial") ||
4672 parseToken(FIRToken::r_paren,
"expected ')' in release_initial") ||
4673 parseOptionalInfo())
4678 !ref || !ref.getForceable())
4679 return emitError(startTok.getLoc(),
"expected rwprobe-type expression for "
4680 "release_initial destination, got ")
4683 locationProcessor.setLoc(startTok.getLoc());
4685 auto value = APInt::getAllOnes(1);
4686 auto type = UIntType::get(builder.getContext(), 1);
4687 auto attr = builder.getIntegerAttr(IntegerType::get(type.getContext(),
4688 value.getBitWidth(),
4689 IntegerType::Unsigned),
4691 auto pred = moduleContext.getCachedConstant(builder, attr, type, attr);
4692 RefReleaseInitialOp::create(builder, pred, dest);
4698ParseResult FIRStmtParser::parseConnect() {
4699 auto startTok = consumeToken(FIRToken::kw_connect);
4700 auto loc = startTok.getLoc();
4703 if (parseExp(lhs,
"expected connect expression") ||
4704 parseToken(FIRToken::comma,
"expected ','") ||
4705 parseExp(rhs,
"expected connect expression") || parseOptionalInfo())
4710 if (!lhsType || !rhsType)
4711 return mlir::emitError(locationProcessor.getLoc(*
this, loc),
4712 "cannot connect reference or property types");
4714 if (lhsType.containsReference() || rhsType.containsReference())
4715 return mlir::emitError(locationProcessor.getLoc(*
this, loc),
4716 "cannot connect types containing references");
4719 return mlir::emitError(locationProcessor.getLoc(*
this, loc),
4720 "cannot connect non-equivalent type ")
4721 << rhsType <<
" to " << lhsType;
4723 locationProcessor.setLoc(loc);
4725 builder, lhs, rhs, [&] {
return locationProcessor.getLoc(*
this, loc); },
4726 getConstants().options.warnOnTruncation);
4737ParseResult FIRStmtParser::parsePropAssert() {
4738 auto startTok = consumeToken(FIRToken::kw_propassert);
4739 auto loc = startTok.getLoc();
4741 llvm::SMLoc conditionLoc = getToken().getLoc(), messageLoc;
4742 Value condition, message;
4743 if (parseExp(condition,
"expected condition in 'propassert'") ||
4744 parseToken(FIRToken::comma,
"expected ','"))
4747 if (getToken().is(FIRToken::string)) {
4748 if (removedFeature({8, 0, 0},
"string messages in property asserts"))
4750 StringRef messageStr;
4751 messageLoc = getToken().getLoc();
4752 if (parseGetSpelling(messageStr) ||
4753 parseToken(FIRToken::string,
"expected message string in 'propassert'"))
4755 locationProcessor.setLoc(messageLoc);
4757 message = moduleContext.getCachedConstant<StringConstantOp>(
4758 builder, attr, builder.getType<StringType>(), attr);
4762 "string property expression message in property asserts"))
4764 messageLoc = getToken().getLoc();
4765 if (parseExp(message,
"expected message in 'propassert'"))
4769 if (!isa<BoolType>(condition.getType()))
4770 return emitError(conditionLoc,
4771 "propassert condition must be of boolean type");
4775 return emitError(messageLoc,
"propassert message must be a string type");
4777 if (parseOptionalInfo())
4780 locationProcessor.setLoc(loc);
4781 PropertyAssertOp::create(builder, condition, message);
4786ParseResult FIRStmtParser::parsePropAssign() {
4787 auto startTok = consumeToken(FIRToken::kw_propassign);
4788 auto loc = startTok.getLoc();
4791 if (parseExp(lhs,
"expected propassign expression") ||
4792 parseToken(FIRToken::comma,
"expected ','") ||
4793 parseExp(rhs,
"expected propassign expression") || parseOptionalInfo())
4798 return emitError(loc,
"can only propassign property types");
4799 locationProcessor.setLoc(loc);
4800 rhs = emitImplicitAnyRefCast(rhs, lhsType);
4803 return emitError(loc,
"can only propassign property types");
4804 if (lhsType != rhsType)
4805 return emitError(loc,
"cannot propassign non-equivalent type ")
4806 << rhsType <<
" to " << lhsType;
4807 PropAssignOp::create(builder, lhs, rhs);
4812ParseResult FIRStmtParser::parseInvalidate() {
4813 auto startTok = consumeToken(FIRToken::kw_invalidate);
4818 auto loc = getToken().getLoc();
4820 if (parseId(
id,
"expected static reference expression") ||
4821 moduleContext.lookupSymbolEntry(symtabEntry,
id, loc))
4826 if (!moduleContext.resolveSymbolEntry(lhs, symtabEntry, loc,
false)) {
4827 if (parseOptionalExpPostscript(lhs,
false) ||
4828 parseOptionalInfo())
4831 locationProcessor.setLoc(startTok.getLoc());
4832 emitInvalidate(lhs);
4839 assert(isa<UnbundledID>(symtabEntry) &&
"should be an instance");
4841 if (getToken().isNot(FIRToken::period)) {
4842 locationProcessor.setLoc(loc);
4844 unsigned unbundledId = cast<UnbundledID>(symtabEntry) - 1;
4846 for (
auto elt : ubEntry)
4847 emitInvalidate(elt.second);
4853 StringRef fieldName;
4854 if (parseToken(FIRToken::period,
"expected '.' in field reference") ||
4855 parseFieldId(fieldName,
"expected field name") ||
4856 moduleContext.resolveSymbolEntry(lhs, symtabEntry, fieldName, loc))
4860 if (parseOptionalExpPostscript(lhs,
false) ||
4861 parseOptionalInfo())
4864 locationProcessor.setLoc(startTok.getLoc());
4865 emitInvalidate(lhs);
4869ParseResult FIRStmtParser::parseLayerBlockOrGroup(
unsigned indent) {
4871 auto startTok = consumeToken();
4872 assert(startTok.isAny(FIRToken::kw_layerblock, FIRToken::kw_group) &&
4873 "consumed an unexpected token");
4874 auto loc = startTok.getLoc();
4877 if (parseId(
id,
"expected layer identifer") ||
4878 parseToken(FIRToken::colon,
"expected ':' at end of layer block") ||
4879 parseOptionalInfo())
4882 locationProcessor.setLoc(loc);
4884 StringRef rootLayer;
4885 SmallVector<FlatSymbolRefAttr> nestedLayers;
4889 rootLayer = layerSym.getRootReference();
4890 auto nestedRefs = layerSym.getNestedReferences();
4891 nestedLayers.append(nestedRefs.begin(), nestedRefs.end());
4892 nestedLayers.push_back(FlatSymbolRefAttr::get(builder.getContext(),
id));
4895 auto layerBlockOp = LayerBlockOp::create(
4897 SymbolRefAttr::get(builder.getContext(), rootLayer, nestedLayers));
4898 layerBlockOp->getRegion(0).push_back(
new Block());
4900 if (getIndentation() > indent)
4901 if (parseSubBlock(layerBlockOp.getRegion().front(), indent,
4902 layerBlockOp.getLayerName()))
4910ParseResult FIRStmtParser::parseLeadingExpStmt(Value lhs) {
4911 auto loc = getToken().getLoc();
4914 if (consumeIf(FIRToken::kw_is)) {
4915 if (parseToken(FIRToken::kw_invalid,
"expected 'invalid'") ||
4916 parseOptionalInfo())
4919 if (removedFeature({3, 0, 0},
"'is invalid' statements", loc))
4922 locationProcessor.setLoc(loc);
4923 emitInvalidate(lhs);
4927 if (parseToken(FIRToken::less_equal,
"expected '<=' in statement"))
4930 if (removedFeature({3, 0, 0},
"'<=' connections", loc))
4934 if (parseExp(rhs,
"unexpected token in statement") || parseOptionalInfo())
4937 locationProcessor.setLoc(loc);
4941 if (!lhsType || !rhsType)
4942 return mlir::emitError(locationProcessor.getLoc(*
this, loc),
4943 "cannot connect reference or property types");
4945 if (lhsType.containsReference() || rhsType.containsReference())
4946 return mlir::emitError(locationProcessor.getLoc(*
this, loc),
4947 "cannot connect types containing references");
4950 return mlir::emitError(locationProcessor.getLoc(*
this, loc),
4951 "cannot connect non-equivalent type ")
4952 << rhsType <<
" to " << lhsType;
4954 builder, lhs, rhs, [&] {
return locationProcessor.getLoc(*
this, loc); },
4955 getConstants().options.warnOnTruncation);
4963ParseResult FIRStmtParser::parseInstance() {
4964 auto startTok = consumeToken(FIRToken::kw_inst);
4968 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
4972 StringRef moduleName;
4973 if (parseId(
id,
"expected instance name") ||
4974 parseToken(FIRToken::kw_of,
"expected 'of' in instance") ||
4975 parseId(moduleName,
"expected module name") || parseOptionalInfo())
4978 locationProcessor.setLoc(startTok.getLoc());
4981 auto referencedModule = getReferencedModule(startTok.getLoc(), moduleName);
4982 if (!referencedModule)
4985 SmallVector<PortInfo> modulePorts = referencedModule.getPorts();
4987 auto annotations = getConstants().emptyArrayAttr;
4988 SmallVector<Attribute, 4> portAnnotations(modulePorts.size(), annotations);
4990 hw::InnerSymAttr sym = {};
4991 auto result = InstanceOp::create(
4992 builder, referencedModule,
id, NameKindEnum::InterestingName,
4993 annotations.getValue(), portAnnotations,
false,
false, sym);
4999 unbundledValueEntry.reserve(modulePorts.size());
5000 for (
size_t i = 0, e = modulePorts.size(); i != e; ++i)
5001 unbundledValueEntry.push_back({modulePorts[i].name, result.getResult(i)});
5005 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
5006 auto entryId =
UnbundledID(moduleContext.unbundledValues.size());
5007 return moduleContext.addSymbolEntry(
id, entryId, startTok.getLoc());
5012ParseResult FIRStmtParser::parseInstanceChoice() {
5013 auto startTok = consumeToken(FIRToken::kw_instchoice);
5014 SMLoc loc = startTok.getLoc();
5017 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
5024 StringRef defaultModuleName;
5025 StringRef optionGroupName;
5026 if (parseId(
id,
"expected instance name") ||
5027 parseToken(FIRToken::kw_of,
"expected 'of' in instance") ||
5028 parseId(defaultModuleName,
"expected module name") ||
5029 parseToken(FIRToken::comma,
"expected ','") ||
5030 parseId(optionGroupName,
"expected option group name") ||
5031 parseToken(FIRToken::colon,
"expected ':' after instchoice") ||
5032 parseOptionalInfo())
5035 locationProcessor.setLoc(startTok.getLoc());
5039 auto defaultModule = getReferencedModule(loc, defaultModuleName);
5043 SmallVector<PortInfo> modulePorts = defaultModule.getPorts();
5046 auto optionGroup = circuitSymTbl.lookup<OptionOp>(optionGroupName);
5048 return emitError(loc,
5049 "use of undefined option group '" + optionGroupName +
"'");
5051 auto baseIndent = getIndentation();
5052 SmallVector<std::pair<OptionCaseOp, FModuleLike>> caseModules;
5053 while (getIndentation() == baseIndent) {
5055 StringRef caseModuleName;
5056 if (parseId(caseId,
"expected a case identifier") ||
5057 parseToken(FIRToken::equal_greater,
5058 "expected '=> in instance choice definition") ||
5059 parseId(caseModuleName,
"expected module name"))
5062 auto caseModule = getReferencedModule(loc, caseModuleName);
5066 for (
const auto &[defaultPort, casePort] :
5067 llvm::zip(modulePorts, caseModule.getPorts())) {
5068 if (defaultPort.name != casePort.name)
5069 return emitError(loc,
"instance case module port '")
5070 << casePort.name.getValue()
5071 <<
"' does not match the default module port '"
5072 << defaultPort.name.getValue() <<
"'";
5073 if (defaultPort.type != casePort.type)
5074 return emitError(loc,
"instance case port '")
5075 << casePort.name.getValue()
5076 <<
"' type does not match the default module port";
5080 dyn_cast_or_null<OptionCaseOp>(optionGroup.lookupSymbol(caseId));
5082 return emitError(loc,
"use of undefined option case '" + caseId +
"'");
5083 caseModules.emplace_back(optionCase, caseModule);
5086 auto annotations = getConstants().emptyArrayAttr;
5087 SmallVector<Attribute, 4> portAnnotations(modulePorts.size(), annotations);
5091 auto result = InstanceChoiceOp::create(
5092 builder, defaultModule, caseModules,
id, NameKindEnum::InterestingName,
5093 annotations.getValue(), portAnnotations, sym);
5097 unbundledValueEntry.reserve(modulePorts.size());
5098 for (
size_t i = 0, e = modulePorts.size(); i != e; ++i)
5099 unbundledValueEntry.push_back({modulePorts[i].name, result.getResult(i)});
5101 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
5102 auto entryId =
UnbundledID(moduleContext.unbundledValues.size());
5103 return moduleContext.addSymbolEntry(
id, entryId, startTok.getLoc());
5106FModuleLike FIRStmtParser::getReferencedModule(SMLoc loc,
5107 StringRef moduleName) {
5108 auto referencedModule = circuitSymTbl.lookup<FModuleLike>(moduleName);
5109 if (!referencedModule) {
5111 "use of undefined module name '" + moduleName +
"' in instance");
5114 if (isa<ClassOp /* ClassLike */>(referencedModule)) {
5115 emitError(loc,
"cannot create instance of class '" + moduleName +
5116 "', did you mean object?");
5119 return referencedModule;
5123ParseResult FIRStmtParser::parseObject() {
5124 auto startTok = consumeToken(FIRToken::kw_object);
5128 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
5131 if (requireFeature({6, 0, 0},
"object statements"))
5135 StringRef className;
5136 if (parseId(
id,
"expected object name") ||
5137 parseToken(FIRToken::kw_of,
"expected 'of' in object") ||
5138 parseId(className,
"expected class name") || parseOptionalInfo())
5141 locationProcessor.setLoc(startTok.getLoc());
5144 const auto &classMap = getConstants().classMap;
5145 auto lookup = classMap.find(className);
5146 if (lookup == classMap.end())
5147 return emitError(startTok.getLoc(),
"use of undefined class name '" +
5148 className +
"' in object");
5149 auto referencedClass = lookup->getSecond();
5150 auto result = ObjectOp::create(builder, referencedClass,
id);
5151 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
5155ParseResult FIRStmtParser::parseCombMem() {
5157 auto startTok = consumeToken(FIRToken::kw_cmem);
5161 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
5166 if (parseId(
id,
"expected cmem name") ||
5167 parseToken(FIRToken::colon,
"expected ':' in cmem") ||
5168 parseType(type,
"expected cmem type") || parseOptionalInfo())
5171 locationProcessor.setLoc(startTok.getLoc());
5176 return emitError(
"cmem requires vector type");
5178 auto annotations = getConstants().emptyArrayAttr;
5179 StringAttr sym = {};
5180 auto result = CombMemOp::create(
5181 builder, vectorType.getElementType(), vectorType.getNumElements(),
id,
5182 NameKindEnum::InterestingName, annotations, sym);
5183 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
5187ParseResult FIRStmtParser::parseSeqMem() {
5189 auto startTok = consumeToken(FIRToken::kw_smem);
5193 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
5198 RUWBehavior ruw = RUWBehavior::Undefined;
5200 if (parseId(
id,
"expected smem name") ||
5201 parseToken(FIRToken::colon,
"expected ':' in smem") ||
5205 if (consumeIf(FIRToken::comma)) {
5210 if (parseOptionalInfo()) {
5214 locationProcessor.setLoc(startTok.getLoc());
5219 return emitError(
"smem requires vector type");
5221 auto annotations = getConstants().emptyArrayAttr;
5222 StringAttr sym = {};
5223 auto result = SeqMemOp::create(
5224 builder, vectorType.getElementType(), vectorType.getNumElements(), ruw,
5225 id, NameKindEnum::InterestingName, annotations, sym);
5226 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
5238ParseResult FIRStmtParser::parseMem(
unsigned memIndent) {
5239 auto startTok = consumeToken(FIRToken::kw_mem);
5243 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
5247 if (parseId(
id,
"expected mem name") ||
5248 parseToken(FIRToken::colon,
"expected ':' in mem") || parseOptionalInfo())
5252 int64_t depth = -1, readLatency = -1, writeLatency = -1;
5253 RUWBehavior ruw = RUWBehavior::Undefined;
5255 SmallVector<std::pair<StringAttr, Type>, 4> ports;
5259 auto nextIndent = getIndentation();
5260 if (!nextIndent || *nextIndent <= memIndent)
5263 auto spelling = getTokenSpelling();
5264 if (parseToken(FIRToken::identifier,
"unexpected token in 'mem'") ||
5265 parseToken(FIRToken::equal_greater,
"expected '=>' in 'mem'"))
5268 if (spelling ==
"data-type") {
5270 return emitError(
"'mem' type specified multiple times"),
failure();
5272 if (
parseType(type,
"expected type in data-type declaration"))
5276 if (spelling ==
"depth") {
5277 if (parseIntLit(depth,
"expected integer in depth specification"))
5281 if (spelling ==
"read-latency") {
5282 if (parseIntLit(readLatency,
"expected integer latency"))
5286 if (spelling ==
"write-latency") {
5287 if (parseIntLit(writeLatency,
"expected integer latency"))
5291 if (spelling ==
"read-under-write") {
5292 if (getToken().isNot(FIRToken::kw_old, FIRToken::kw_new,
5293 FIRToken::kw_undefined))
5294 return emitError(
"expected specifier"),
failure();
5296 if (parseOptionalRUW(ruw))
5301 MemOp::PortKind portKind;
5302 if (spelling ==
"reader")
5303 portKind = MemOp::PortKind::Read;
5304 else if (spelling ==
"writer")
5305 portKind = MemOp::PortKind::Write;
5306 else if (spelling ==
"readwriter")
5307 portKind = MemOp::PortKind::ReadWrite;
5309 return emitError(
"unexpected field in 'mem' declaration"),
failure();
5312 if (parseId(portName,
"expected port name"))
5316 return emitError(
"unexpected type, must be base type");
5317 ports.push_back({builder.getStringAttr(portName),
5318 MemOp::getTypeForPort(depth, baseType, portKind)});
5320 while (!getIndentation().has_value()) {
5321 if (parseId(portName,
"expected port name"))
5323 ports.push_back({builder.getStringAttr(portName),
5324 MemOp::getTypeForPort(depth, baseType, portKind)});
5335 llvm::array_pod_sort(ports.begin(), ports.end(),
5336 [](
const std::pair<StringAttr, Type> *lhs,
5337 const std::pair<StringAttr, Type> *rhs) ->
int {
5338 return lhs->first.getValue().compare(
5339 rhs->first.getValue());
5342 auto annotations = getConstants().emptyArrayAttr;
5343 SmallVector<Attribute, 4> resultNames;
5344 SmallVector<Type, 4> resultTypes;
5345 SmallVector<Attribute, 4> resultAnnotations;
5346 for (
auto p : ports) {
5347 resultNames.push_back(p.first);
5348 resultTypes.push_back(p.second);
5349 resultAnnotations.push_back(annotations);
5352 locationProcessor.setLoc(startTok.getLoc());
5354 auto result = MemOp::create(
5355 builder, resultTypes, readLatency, writeLatency, depth, ruw,
5356 builder.getArrayAttr(resultNames),
id, NameKindEnum::InterestingName,
5357 annotations, builder.getArrayAttr(resultAnnotations), hw::InnerSymAttr(),
5358 MemoryInitAttr(), StringAttr());
5361 unbundledValueEntry.reserve(result.getNumResults());
5362 for (
size_t i = 0, e = result.getNumResults(); i != e; ++i)
5363 unbundledValueEntry.push_back({resultNames[i], result.getResult(i)});
5365 moduleContext.unbundledValues.push_back(std::move(unbundledValueEntry));
5366 auto entryID =
UnbundledID(moduleContext.unbundledValues.size());
5367 return moduleContext.addSymbolEntry(
id, entryID, startTok.getLoc());
5371ParseResult FIRStmtParser::parseNode() {
5372 auto startTok = consumeToken(FIRToken::kw_node);
5376 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
5381 if (parseId(
id,
"expected node name") ||
5382 parseToken(FIRToken::equal,
"expected '=' in node") ||
5383 parseExp(initializer,
"expected expression for node") ||
5384 parseOptionalInfo())
5387 locationProcessor.setLoc(startTok.getLoc());
5400 auto initializerBaseType =
5403 !(initializerBaseType && initializerBaseType.isPassive())) {
5404 emitError(startTok.getLoc())
5405 <<
"Node cannot be analog and must be passive or passive under a flip "
5406 << initializer.getType();
5410 auto annotations = getConstants().emptyArrayAttr;
5411 StringAttr sym = {};
5413 auto result = NodeOp::create(builder, initializer,
id,
5414 NameKindEnum::InterestingName, annotations, sym);
5415 return moduleContext.addSymbolEntry(
id, result.getResult(),
5420ParseResult FIRStmtParser::parseWire() {
5421 auto startTok = consumeToken(FIRToken::kw_wire);
5425 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
5430 if (parseId(
id,
"expected wire name") ||
5431 parseToken(FIRToken::colon,
"expected ':' in wire") ||
5436 SmallVector<Value> domains;
5437 if (consumeIf(FIRToken::kw_domains)) {
5441 if (parseToken(FIRToken::l_square,
"expected '[' after 'domains'"))
5444 if (parseListUntil(FIRToken::r_square, [&]() -> ParseResult {
5445 StringRef domainName;
5446 auto domainLoc = getToken().getLoc();
5447 if (parseId(domainName,
"expected domain name"))
5452 if (moduleContext.lookupSymbolEntry(lookup, domainName, domainLoc))
5457 if (moduleContext.resolveSymbolEntry(domainValue, lookup, domainLoc))
5460 if (!isa<DomainType>(domainValue.getType()))
5461 return emitError(domainLoc)
5462 <<
"'" << domainName <<
"' is not a domain";
5464 domains.push_back(domainValue);
5470 if (parseOptionalInfo())
5473 locationProcessor.setLoc(startTok.getLoc());
5475 auto annotations = getConstants().emptyArrayAttr;
5476 StringAttr sym = {};
5479 auto namekind = isa<PropertyType, RefType>(type)
5480 ? NameKindEnum::DroppableName
5481 : NameKindEnum::InterestingName;
5483 auto result = WireOp::create(builder, type,
id, namekind, annotations, sym,
5485 return moduleContext.addSymbolEntry(
id, result.getResult(),
5499ParseResult FIRStmtParser::parseRegister(
unsigned regIndent) {
5500 auto startTok = consumeToken(FIRToken::kw_reg);
5504 if (
auto isExpr = parseExpWithLeadingKeyword(startTok))
5513 if (parseId(
id,
"expected reg name") ||
5514 parseToken(FIRToken::colon,
"expected ':' in reg") ||
5516 parseToken(FIRToken::comma,
"expected ','") ||
5517 parseExp(clock,
"expected expression for register clock"))
5521 return emitError(startTok.getLoc(),
"register must have base type");
5524 Value resetSignal, resetValue;
5525 if (consumeIf(FIRToken::kw_with)) {
5526 if (removedFeature({3, 0, 0},
"'reg with' registers"))
5529 if (parseToken(FIRToken::colon,
"expected ':' in reg"))
5537 bool hasExtraLParen = consumeIf(FIRToken::l_paren);
5539 auto indent = getIndentation();
5540 if (!indent || *indent <= regIndent)
5541 if (!hasExtraLParen)
5542 return emitError(
"expected indented reset specifier in reg"),
failure();
5544 if (parseToken(FIRToken::kw_reset,
"expected 'reset' in reg") ||
5545 parseToken(FIRToken::equal_greater,
"expected => in reset specifier") ||
5546 parseToken(FIRToken::l_paren,
"expected '(' in reset specifier") ||
5547 parseExp(resetSignal,
"expected expression for reset signal") ||
5548 parseToken(FIRToken::comma,
"expected ','"))
5556 if (getTokenSpelling() ==
id) {
5558 if (parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
5560 resetSignal = Value();
5562 if (parseExp(resetValue,
"expected expression for reset value") ||
5563 parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
5567 if (hasExtraLParen &&
5568 parseToken(FIRToken::r_paren,
"expected ')' in reset specifier"))
5574 if (parseOptionalInfo())
5577 locationProcessor.setLoc(startTok.getLoc());
5579 ArrayAttr annotations = getConstants().emptyArrayAttr;
5581 StringAttr sym = {};
5584 RegResetOp::create(builder, type, clock, resetSignal, resetValue,
id,
5585 NameKindEnum::InterestingName, annotations, sym)
5588 result = RegOp::create(builder, type, clock,
id,
5589 NameKindEnum::InterestingName, annotations, sym)
5591 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
5599ParseResult FIRStmtParser::parseRegisterWithReset() {
5600 auto startTok = consumeToken(FIRToken::kw_regreset);
5604 Value clock, resetSignal, resetValue;
5606 if (parseId(
id,
"expected reg name") ||
5607 parseToken(FIRToken::colon,
"expected ':' in reg") ||
5609 parseToken(FIRToken::comma,
"expected ','") ||
5610 parseExp(clock,
"expected expression for register clock") ||
5611 parseToken(FIRToken::comma,
"expected ','") ||
5612 parseExp(resetSignal,
"expected expression for register reset") ||
5613 parseToken(FIRToken::comma,
"expected ','") ||
5614 parseExp(resetValue,
"expected expression for register reset value") ||
5615 parseOptionalInfo())
5619 return emitError(startTok.getLoc(),
"register must have base type");
5621 locationProcessor.setLoc(startTok.getLoc());
5624 RegResetOp::create(builder, type, clock, resetSignal, resetValue,
id,
5625 NameKindEnum::InterestingName,
5626 getConstants().emptyArrayAttr, StringAttr{})
5629 return moduleContext.addSymbolEntry(
id, result, startTok.getLoc());
5634ParseResult FIRStmtParser::parseContract(
unsigned blockIndent) {
5638 auto startTok = consumeToken(FIRToken::kw_contract);
5641 SmallVector<StringRef> ids;
5642 SmallVector<SMLoc> locs;
5643 SmallVector<Value> values;
5644 SmallVector<Type> types;
5645 if (!consumeIf(FIRToken::colon)) {
5646 auto parseContractId = [&] {
5648 locs.push_back(getToken().
getLoc());
5649 if (parseId(
id,
"expected contract result name"))
5654 auto parseContractValue = [&] {
5656 if (parseExp(value,
"expected expression for contract result"))
5658 values.push_back(value);
5659 types.push_back(value.getType());
5662 if (parseListUntil(FIRToken::equal, parseContractId) ||
5663 parseListUntil(FIRToken::colon, parseContractValue))
5666 if (parseOptionalInfo())
5670 if (ids.size() != values.size())
5671 return emitError(startTok.getLoc())
5672 <<
"contract requires same number of results and expressions; got "
5673 << ids.size() <<
" results and " << values.size()
5674 <<
" expressions instead";
5676 locationProcessor.setLoc(startTok.getLoc());
5680 auto contract = ContractOp::create(builder, types, values);
5681 auto &block = contract.getBody().emplaceBlock();
5685 FIRModuleContext::ContextScope scope(moduleContext, &block);
5686 for (
auto [
id, loc, type] : llvm::zip(ids, locs, types)) {
5687 auto arg = block.addArgument(type, LocWithInfo(loc,
this).
getLoc());
5688 if (failed(moduleContext.addSymbolEntry(
id, arg, loc)))
5691 if (getIndentation() > blockIndent)
5692 if (parseSubBlock(block, blockIndent, SymbolRefAttr{}))
5697 for (
auto [
id, loc, value, result] :
5698 llvm::zip(ids, locs, values, contract.getResults())) {
5700 moduleContext.removeSymbolEntry(
id);
5701 if (failed(moduleContext.addSymbolEntry(
id, result, loc)))
5714struct FIRCircuitParser :
public FIRParser {
5715 explicit FIRCircuitParser(SharedParserConstants &state, FIRLexer &lexer,
5716 ModuleOp mlirModule, FIRVersion version)
5717 : FIRParser(state, lexer, version), mlirModule(mlirModule) {}
5720 parseCircuit(SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBuf,
5721 mlir::TimingScope &ts);
5726 ParseResult importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
5727 SmallVectorImpl<Attribute> &
attrs);
5729 ParseResult parseToplevelDefinition(CircuitOp circuit,
unsigned indent);
5731 ParseResult parseClass(CircuitOp circuit,
unsigned indent);
5732 ParseResult parseDomain(CircuitOp circuit,
unsigned indent);
5733 ParseResult parseExtClass(CircuitOp circuit,
unsigned indent);
5734 ParseResult parseExtModule(CircuitOp circuit,
unsigned indent);
5735 ParseResult parseIntModule(CircuitOp circuit,
unsigned indent);
5736 ParseResult parseModule(CircuitOp circuit,
bool isPublic,
unsigned indent);
5737 ParseResult parseFormal(CircuitOp circuit,
unsigned indent);
5738 ParseResult parseSimulation(CircuitOp circuit,
unsigned indent);
5740 ParseResult parseFormalLike(CircuitOp circuit,
unsigned indent);
5742 ParseResult parseLayerName(SymbolRefAttr &result);
5743 ParseResult parseLayerList(SmallVectorImpl<Attribute> &result);
5744 ParseResult parseEnableLayerSpec(SmallVectorImpl<Attribute> &result);
5745 ParseResult parseKnownLayerSpec(SmallVectorImpl<Attribute> &result);
5746 ParseResult parseRequiresSpec(SmallVectorImpl<Attribute> &result);
5747 ParseResult parseModuleLayerSpec(ArrayAttr &enabledLayers);
5748 ParseResult parseExtModuleAttributesSpec(ArrayAttr &enabledLayers,
5749 ArrayAttr &knownLayers,
5750 ArrayAttr &externalRequirements);
5752 ParseResult
parsePortList(SmallVectorImpl<PortInfo> &resultPorts,
5753 SmallVectorImpl<SMLoc> &resultPortLocs,
5757 ParseResult skipToModuleEnd(
unsigned indent);
5759 ParseResult parseTypeDecl();
5761 ParseResult parseOptionDecl(CircuitOp circuit);
5763 ParseResult parseLayer(CircuitOp circuit);
5765 ParseResult resolveDomains(
5766 const SmallVectorImpl<std::pair<Attribute, llvm::SMLoc>> &domainsByName,
5767 const DenseMap<Attribute, size_t> &nameToIndex,
5768 SmallVectorImpl<Attribute> &domainsByIndex);
5771 parseDomains(SmallVectorImpl<std::pair<Attribute, llvm::SMLoc>> &domains,
5772 const DenseMap<Attribute, size_t> &nameToIndex);
5774 struct DeferredModuleToParse {
5775 FModuleLike moduleOp;
5776 SmallVector<SMLoc> portLocs;
5777 FIRLexerCursor lexerCursor;
5781 ParseResult parseModuleBody(
const SymbolTable &circuitSymTbl,
5782 DeferredModuleToParse &deferredModule,
5783 InnerSymFixups &fixups);
5785 SmallVector<DeferredModuleToParse, 0> deferredModules;
5787 SmallVector<InnerSymFixups, 0> moduleFixups;
5789 hw::InnerSymbolNamespaceCollection innerSymbolNamespaces;
5791 ModuleOp mlirModule;
5796FIRCircuitParser::importAnnotationsRaw(SMLoc loc, StringRef annotationsStr,
5797 SmallVectorImpl<Attribute> &
attrs) {
5799 auto annotations = json::parse(annotationsStr);
5800 if (
auto err = annotations.takeError()) {
5801 handleAllErrors(std::move(err), [&](
const json::ParseError &a) {
5802 auto diag = emitError(loc,
"Failed to parse JSON Annotations");
5803 diag.attachNote() << a.message();
5808 json::Path::Root root;
5809 llvm::StringMap<ArrayAttr> thisAnnotationMap;
5812 auto diag = emitError(loc,
"Invalid/unsupported annotation format");
5813 std::string jsonErrorMessage =
5814 "See inline comments for problem area in JSON:\n";
5815 llvm::raw_string_ostream
s(jsonErrorMessage);
5816 root.printErrorContext(annotations.get(), s);
5817 diag.attachNote() << jsonErrorMessage;
5824ParseResult FIRCircuitParser::parseLayerName(SymbolRefAttr &result) {
5826 SmallVector<StringRef> strings;
5829 if (parseId(name,
"expected layer name"))
5831 strings.push_back(name);
5832 }
while (consumeIf(FIRToken::period));
5834 SmallVector<FlatSymbolRefAttr> nested;
5835 nested.reserve(strings.size() - 1);
5836 for (
unsigned i = 1, e = strings.size(); i < e; ++i)
5837 nested.push_back(FlatSymbolRefAttr::get(
context, strings[i]));
5839 result = SymbolRefAttr::get(
context, strings[0], nested);
5843ParseResult FIRCircuitParser::parseModuleLayerSpec(ArrayAttr &enabledLayers) {
5844 SmallVector<Attribute> enabledLayersBuffer;
5846 auto tokenKind = getToken().getKind();
5848 if (tokenKind == FIRToken::kw_enablelayer) {
5849 if (parseEnableLayerSpec(enabledLayersBuffer))
5857 if (enabledLayersBuffer.size() != 0)
5858 if (requireFeature({4, 0, 0},
"modules with layers enabled"))
5861 enabledLayers = ArrayAttr::get(getContext(), enabledLayersBuffer);
5865ParseResult FIRCircuitParser::parseExtModuleAttributesSpec(
5866 ArrayAttr &enabledLayers, ArrayAttr &knownLayers,
5867 ArrayAttr &externalRequirements) {
5868 SmallVector<Attribute> enabledLayersBuffer;
5869 SmallVector<Attribute> knownLayersBuffer;
5870 SmallVector<Attribute> requirementsBuffer;
5872 auto tokenKind = getToken().getKind();
5874 if (tokenKind == FIRToken::kw_enablelayer) {
5875 if (parseEnableLayerSpec(enabledLayersBuffer))
5880 if (tokenKind == FIRToken::kw_knownlayer) {
5881 if (parseKnownLayerSpec(knownLayersBuffer))
5886 if (tokenKind == FIRToken::kw_requires) {
5887 if (parseRequiresSpec(requirementsBuffer))
5895 if (enabledLayersBuffer.size() != 0)
5896 if (requireFeature({4, 0, 0},
"extmodules with layers enabled"))
5899 if (knownLayersBuffer.size() != 0)
5900 if (requireFeature({6, 0, 0},
"extmodules with known layers"))
5903 enabledLayers = ArrayAttr::get(getContext(), enabledLayersBuffer);
5904 knownLayers = ArrayAttr::get(getContext(), knownLayersBuffer);
5905 externalRequirements = ArrayAttr::get(getContext(), requirementsBuffer);
5910FIRCircuitParser::parseLayerList(SmallVectorImpl<Attribute> &result) {
5912 SymbolRefAttr layer;
5913 if (parseLayerName(layer))
5915 result.push_back(layer);
5916 }
while (consumeIf(FIRToken::comma));
5921FIRCircuitParser::parseEnableLayerSpec(SmallVectorImpl<Attribute> &result) {
5922 consumeToken(FIRToken::kw_enablelayer);
5923 return parseLayerList(result);
5927FIRCircuitParser::parseKnownLayerSpec(SmallVectorImpl<Attribute> &result) {
5928 consumeToken(FIRToken::kw_knownlayer);
5929 return parseLayerList(result);
5933FIRCircuitParser::parseRequiresSpec(SmallVectorImpl<Attribute> &result) {
5934 consumeToken(FIRToken::kw_requires);
5936 StringRef requireStr;
5937 if (parseGetSpelling(requireStr) ||
5938 parseToken(FIRToken::string,
"expected string after 'requires'"))
5942 StringAttr::get(getContext(), requireStr.drop_front().drop_back()));
5943 }
while (consumeIf(FIRToken::comma));
5951FIRCircuitParser::parsePortList(SmallVectorImpl<PortInfo> &resultPorts,
5952 SmallVectorImpl<SMLoc> &resultPortLocs,
5958 DenseMap<Attribute, size_t> nameToIndex;
5959 DenseMap<size_t, SmallVector<std::pair<Attribute, SMLoc>>> domainNames;
5962 while (getToken().isAny(FIRToken::kw_input, FIRToken::kw_output) &&
5964 getIndentation() > indent) {
5970 auto backtrackState = getLexer().getCursor();
5972 bool isOutput = getToken().is(FIRToken::kw_output);
5977 if (!getToken().isAny(FIRToken::identifier, FIRToken::literal_identifier) &&
5978 !getToken().isKeyword()) {
5979 backtrackState.restore(getLexer());
5986 if (parseId(name,
"expected port name") ||
5987 parseToken(FIRToken::colon,
"expected ':' in port definition") ||
5988 parseType(type,
"expected a type in port declaration"))
5990 Attribute domainInfoElement = {};
5991 size_t portIdx = resultPorts.size();
5992 if (
auto domainType = dyn_cast<DomainType>(type)) {
5995 domainInfoElement = ArrayAttr::get(getContext(), {});
5997 if (getToken().is(FIRToken::kw_domains))
5998 if (parseDomains(domainNames[portIdx], nameToIndex))
6002 if (
info.parseOptionalInfo())
6005 StringAttr innerSym = {};
6006 resultPorts.push_back(PortInfo{name,
6012 domainInfoElement});
6013 resultPortLocs.push_back(
info.getFIRLoc());
6014 nameToIndex.insert({name, portIdx});
6018 for (
size_t portIdx = 0, e = resultPorts.size(); portIdx != e; ++portIdx) {
6019 auto &port = resultPorts[portIdx];
6020 Attribute &attr = port.domains;
6024 SmallVector<Attribute> domainInfo;
6025 if (failed(resolveDomains(domainNames[portIdx], nameToIndex, domainInfo)))
6027 attr = ArrayAttr::get(getContext(), domainInfo);
6031 SmallDenseMap<Attribute, SMLoc> portIds;
6032 for (
auto portAndLoc : llvm::zip(resultPorts, resultPortLocs)) {
6033 PortInfo &port = std::get<0>(portAndLoc);
6034 auto &entry = portIds[port.
name];
6035 if (!entry.isValid()) {
6036 entry = std::get<1>(portAndLoc);
6040 emitError(std::get<1>(portAndLoc),
6041 "redefinition of name '" + port.
getName() +
"'")
6042 .attachNote(translateLocation(entry))
6043 <<
"previous definition here";
6052ParseResult FIRCircuitParser::skipToModuleEnd(
unsigned indent) {
6054 switch (getToken().getKind()) {
6058 case FIRToken::error:
6062 case FIRToken::kw_class:
6063 case FIRToken::kw_domain:
6064 case FIRToken::kw_declgroup:
6065 case FIRToken::kw_extclass:
6066 case FIRToken::kw_extmodule:
6067 case FIRToken::kw_intmodule:
6068 case FIRToken::kw_formal:
6069 case FIRToken::kw_module:
6070 case FIRToken::kw_public:
6071 case FIRToken::kw_layer:
6072 case FIRToken::kw_option:
6073 case FIRToken::kw_simulation:
6074 case FIRToken::kw_type:
6078 if (getIndentation() == indent)
6090ParseResult FIRCircuitParser::parseParameterList(ArrayAttr &resultParameters) {
6091 SmallVector<Attribute, 8> parameters;
6092 SmallPtrSet<StringAttr, 8> seen;
6093 while (consumeIf(FIRToken::kw_parameter)) {
6097 if (parseParameter(name, value, loc))
6099 auto typedValue = dyn_cast<TypedAttr>(value);
6101 return emitError(loc)
6102 <<
"invalid value for parameter '" << name.getValue() <<
"'";
6103 if (!seen.insert(name).second)
6104 return emitError(loc,
6105 "redefinition of parameter '" + name.getValue() +
"'");
6106 parameters.push_back(ParamDeclAttr::get(name, typedValue));
6108 resultParameters = ArrayAttr::get(getContext(), parameters);
6113ParseResult FIRCircuitParser::parseClass(CircuitOp circuit,
unsigned indent) {
6115 SmallVector<PortInfo, 8> portList;
6116 SmallVector<SMLoc> portLocs;
6119 if (requireFeature({6, 0, 0},
"classes"))
6122 consumeToken(FIRToken::kw_class);
6123 if (parseId(name,
"expected class name") ||
6124 parseToken(FIRToken::colon,
"expected ':' in class definition") ||
6128 if (name == circuit.getName())
6129 return mlir::emitError(
info.getLoc(),
6130 "class cannot be the top of a circuit");
6132 for (
auto &portInfo : portList)
6133 if (!isa<PropertyType>(portInfo.type))
6134 return mlir::emitError(portInfo.loc,
6135 "ports on classes must be properties");
6138 auto builder = circuit.getBodyBuilder();
6139 auto classOp = ClassOp::create(builder,
info.getLoc(), name, portList);
6140 classOp.setPrivate();
6141 deferredModules.emplace_back(
6142 DeferredModuleToParse{classOp, portLocs, getLexer().getCursor(), indent});
6145 getConstants().classMap[name.getValue()] = classOp;
6146 return skipToModuleEnd(indent);
6150ParseResult FIRCircuitParser::parseDomain(CircuitOp circuit,
unsigned indent) {
6151 consumeToken(FIRToken::kw_domain);
6155 if (parseId(name,
"domain name") ||
6156 parseToken(FIRToken::colon,
"expected ':' after domain definition") ||
6157 info.parseOptionalInfo())
6160 SmallVector<Attribute> fields;
6162 auto nextIndent = getIndentation();
6163 if (!nextIndent || *nextIndent <= indent)
6166 StringAttr fieldName;
6168 if (parseId(fieldName,
"field name") ||
6169 parseToken(FIRToken::colon,
"expected ':' after field name") ||
6170 parsePropertyType(type,
"field type") ||
info.parseOptionalInfo())
6174 DomainFieldAttr::get(circuit.getContext(), fieldName, type));
6177 auto builder = circuit.getBodyBuilder();
6179 DomainOp::create(builder,
info.getLoc(), name, {},
6180 builder.getArrayAttr(fields));
6184 getConstants().domainMap[name.getValue()] = domainOp;
6190ParseResult FIRCircuitParser::parseExtClass(CircuitOp circuit,
6193 SmallVector<PortInfo, 8> portList;
6194 SmallVector<SMLoc> portLocs;
6197 if (requireFeature({6, 0, 0},
"classes"))
6200 consumeToken(FIRToken::kw_extclass);
6201 if (parseId(name,
"expected extclass name") ||
6202 parseToken(FIRToken::colon,
"expected ':' in extclass definition") ||
6206 if (name == circuit.getName())
6207 return mlir::emitError(
info.getLoc(),
6208 "extclass cannot be the top of a circuit");
6210 for (
auto &portInfo : portList)
6211 if (!isa<PropertyType>(portInfo.type))
6212 return mlir::emitError(portInfo.loc,
6213 "ports on extclasses must be properties");
6216 auto builder = circuit.getBodyBuilder();
6217 auto extClassOp = ExtClassOp::create(builder,
info.getLoc(), name, portList);
6220 getConstants().classMap[name.getValue()] = extClassOp;
6221 return skipToModuleEnd(indent);
6229ParseResult FIRCircuitParser::parseExtModule(CircuitOp circuit,
6232 ArrayAttr enabledLayers;
6233 ArrayAttr knownLayers;
6234 ArrayAttr externalRequirements;
6235 SmallVector<PortInfo, 8> portList;
6236 SmallVector<SMLoc> portLocs;
6238 consumeToken(FIRToken::kw_extmodule);
6239 if (parseId(name,
"expected extmodule name") ||
6240 parseExtModuleAttributesSpec(enabledLayers, knownLayers,
6241 externalRequirements) ||
6242 parseToken(FIRToken::colon,
"expected ':' in extmodule definition") ||
6247 if (consumeIf(FIRToken::kw_defname)) {
6248 if (parseToken(FIRToken::equal,
"expected '=' in defname") ||
6249 parseId(defName,
"expected defname name"))
6253 ArrayAttr parameters;
6257 if (version >= FIRVersion({4, 0, 0})) {
6258 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
6260 if (ftype.hasUninferredWidth())
6261 return emitError(loc,
"extmodule port must have known width");
6266 auto builder = circuit.getBodyBuilder();
6267 auto isMainModule = (name == circuit.getName());
6269 (isMainModule && getConstants().options.scalarizePublicModules) ||
6270 getConstants().options.scalarizeExtModules
6271 ? Convention::Scalarized
6272 : Convention::Internal;
6273 auto conventionAttr = ConventionAttr::get(getContext(), convention);
6274 auto annotations = ArrayAttr::get(getContext(), {});
6275 auto extModuleOp = FExtModuleOp::create(
6276 builder,
info.getLoc(), name, conventionAttr, portList, knownLayers,
6277 defName, annotations, parameters, enabledLayers, externalRequirements);
6278 auto visibility = isMainModule ? SymbolTable::Visibility::Public
6279 : SymbolTable::Visibility::Private;
6280 SymbolTable::setSymbolVisibility(extModuleOp, visibility);
6288ParseResult FIRCircuitParser::parseIntModule(CircuitOp circuit,
6292 ArrayAttr enabledLayers;
6293 SmallVector<PortInfo, 8> portList;
6294 SmallVector<SMLoc> portLocs;
6296 consumeToken(FIRToken::kw_intmodule);
6297 if (parseId(name,
"expected intmodule name") ||
6298 parseModuleLayerSpec(enabledLayers) ||
6299 parseToken(FIRToken::colon,
"expected ':' in intmodule definition") ||
6301 parseToken(FIRToken::kw_intrinsic,
"expected 'intrinsic'") ||
6302 parseToken(FIRToken::equal,
"expected '=' in intrinsic") ||
6303 parseId(intName,
"expected intrinsic name"))
6306 ArrayAttr parameters;
6310 ArrayAttr annotations = getConstants().emptyArrayAttr;
6311 auto builder = circuit.getBodyBuilder();
6312 FIntModuleOp::create(builder,
info.getLoc(), name, portList, intName,
6313 annotations, parameters, enabledLayers)
6319ParseResult FIRCircuitParser::parseModule(CircuitOp circuit,
bool isPublic,
6322 SmallVector<PortInfo, 8> portList;
6323 SmallVector<SMLoc> portLocs;
6324 ArrayAttr enabledLayers;
6325 auto modLoc = getToken().getLoc();
6326 LocWithInfo
info(modLoc,
this);
6327 consumeToken(FIRToken::kw_module);
6328 if (parseId(name,
"expected module name") ||
6329 parseModuleLayerSpec(enabledLayers) ||
6330 parseToken(FIRToken::colon,
"expected ':' in module definition") ||
6335 if (name == circuit.getName()) {
6336 if (!isPublic && removedFeature({4, 0, 0},
"private main modules", modLoc))
6341 if (isPublic && version >= FIRVersion({4, 0, 0})) {
6342 for (
auto [pi, loc] : llvm::zip_equal(portList, portLocs)) {
6344 if (ftype.hasUninferredWidth())
6345 return emitError(loc,
"public module port must have known width");
6346 if (ftype.hasUninferredReset())
6347 return emitError(loc,
6348 "public module port must have concrete reset type");
6353 ArrayAttr annotations = getConstants().emptyArrayAttr;
6354 auto convention = Convention::Internal;
6355 if (isPublic && getConstants().options.scalarizePublicModules)
6356 convention = Convention::Scalarized;
6357 if (!isPublic && getConstants().options.scalarizeInternalModules)
6358 convention = Convention::Scalarized;
6359 auto conventionAttr = ConventionAttr::get(getContext(), convention);
6360 auto builder = circuit.getBodyBuilder();
6362 FModuleOp::create(builder,
info.getLoc(), name, conventionAttr, portList,
6363 annotations, enabledLayers);
6365 auto visibility = isPublic ? SymbolTable::Visibility::Public
6366 : SymbolTable::Visibility::Private;
6367 SymbolTable::setSymbolVisibility(moduleOp, visibility);
6371 deferredModules.emplace_back(DeferredModuleToParse{
6372 moduleOp, portLocs, getLexer().getCursor(), indent});
6374 if (skipToModuleEnd(indent))
6380ParseResult FIRCircuitParser::parseFormal(CircuitOp circuit,
unsigned indent) {
6381 consumeToken(FIRToken::kw_formal);
6382 return parseFormalLike<FormalOp>(circuit, indent);
6386ParseResult FIRCircuitParser::parseSimulation(CircuitOp circuit,
6388 consumeToken(FIRToken::kw_simulation);
6389 return parseFormalLike<SimulationOp>(circuit, indent);
6396ParseResult FIRCircuitParser::parseFormalLike(CircuitOp circuit,
6398 StringRef id, moduleName;
6401 auto builder = circuit.getBodyBuilder();
6404 if (parseId(
id,
"expected test name") ||
6405 parseToken(FIRToken::kw_of,
"expected 'of' in test") ||
6406 parseId(moduleName,
"expected module name"))
6410 NamedAttrList params;
6411 if (consumeIf(FIRToken::comma)) {
6413 if (getToken().isNot(FIRToken::identifier) || getTokenSpelling() !=
"bound")
6414 return emitError(
"expected 'bound' after ','");
6416 if (parseToken(FIRToken::equal,
"expected '=' after 'bound'") ||
6417 parseIntLit(bound,
"expected integer bound after '='"))
6420 return emitError(
"bound must be a positive integer");
6421 if (
info.parseOptionalInfo())
6423 params.set(
"bound", builder.getIntegerAttr(builder.getI32Type(), bound));
6426 if (parseToken(FIRToken::colon,
"expected ':' in test") ||
6427 info.parseOptionalInfo())
6429 while (getIndentation() > indent) {
6430 StringAttr paramName;
6431 Attribute paramValue;
6433 if (parseParameter(paramName, paramValue, paramLoc,
6436 if (params.set(paramName, paramValue))
6437 return emitError(paramLoc,
"redefinition of parameter '" +
6438 paramName.getValue() +
"'");
6442 Op::create(builder,
info.getLoc(),
id, {}, moduleName,
6443 params.getDictionary(getContext()));
6447ParseResult FIRCircuitParser::parseToplevelDefinition(CircuitOp circuit,
6449 switch (getToken().getKind()) {
6450 case FIRToken::kw_class:
6451 return parseClass(circuit, indent);
6452 case FIRToken::kw_declgroup:
6453 if (requireFeature({3, 2, 0},
"optional groups") ||
6454 removedFeature({3, 3, 0},
"optional groups"))
6456 return parseLayer(circuit);
6457 case FIRToken::kw_domain:
6460 return parseDomain(circuit, indent);
6461 case FIRToken::kw_extclass:
6462 return parseExtClass(circuit, indent);
6463 case FIRToken::kw_extmodule:
6464 return parseExtModule(circuit, indent);
6465 case FIRToken::kw_formal:
6466 if (requireFeature({4, 0, 0},
"formal tests"))
6468 return parseFormal(circuit, indent);
6469 case FIRToken::kw_intmodule:
6470 if (requireFeature({1, 2, 0},
"intrinsic modules") ||
6471 removedFeature({4, 0, 0},
"intrinsic modules"))
6473 return parseIntModule(circuit, indent);
6474 case FIRToken::kw_layer:
6475 if (requireFeature({3, 3, 0},
"layers"))
6477 return parseLayer(circuit);
6478 case FIRToken::kw_module:
6479 return parseModule(circuit,
false, indent);
6480 case FIRToken::kw_public:
6481 if (requireFeature({3, 3, 0},
"public modules"))
6484 if (getToken().getKind() == FIRToken::kw_module)
6485 return parseModule(circuit,
true, indent);
6486 return emitError(getToken().
getLoc(),
"only modules may be public");
6487 case FIRToken::kw_simulation:
6490 return parseSimulation(circuit, indent);
6491 case FIRToken::kw_type:
6492 return parseTypeDecl();
6493 case FIRToken::kw_option:
6496 return parseOptionDecl(circuit);
6498 return emitError(getToken().
getLoc(),
"unknown toplevel definition");
6503ParseResult FIRCircuitParser::parseTypeDecl() {
6507 auto loc = getToken().getLoc();
6509 if (getToken().isKeyword())
6510 return emitError(loc) <<
"cannot use keyword '" << getToken().getSpelling()
6511 <<
"' for type alias name";
6513 if (parseId(
id,
"expected type name") ||
6514 parseToken(FIRToken::equal,
"expected '=' in type decl") ||
6517 auto name = StringAttr::get(type.getContext(),
id);
6521 type = BaseTypeAliasType::get(name, base);
6524 <<
"type alias for non-base type " << type
6525 <<
" is currently not supported. Type alias is stripped immediately";
6527 if (!getConstants().aliasMap.insert({id, type}).second)
6528 return emitError(loc) <<
"type alias `" << name.getValue()
6529 <<
"` is already defined";
6534ParseResult FIRCircuitParser::parseOptionDecl(CircuitOp circuit) {
6537 auto loc = getToken().getLoc();
6540 if (parseId(
id,
"expected an option group name") ||
6541 parseToken(FIRToken::colon,
6542 "expected ':' after option group definition") ||
6543 info.parseOptionalInfo())
6546 auto builder = OpBuilder::atBlockEnd(circuit.getBodyBlock());
6548 OptionOp::create(builder,
info.getLoc(),
id, {});
6549 auto *block =
new Block;
6550 optionOp.getBody().push_back(block);
6551 builder.setInsertionPointToEnd(block);
6553 auto baseIndent = getIndentation();
6555 while (getIndentation() == baseIndent) {
6557 LocWithInfo caseInfo(getToken().
getLoc(),
this);
6558 if (parseId(
id,
"expected an option case ID") ||
6559 caseInfo.parseOptionalInfo())
6562 if (!cases.insert(
id).second)
6563 return emitError(loc)
6564 <<
"duplicate option case definition '" <<
id <<
"'";
6566 OptionCaseOp::create(builder, caseInfo.getLoc(),
id);
6573ParseResult FIRCircuitParser::parseLayer(CircuitOp circuit) {
6574 auto baseIndent = getIndentation();
6577 SmallVector<std::pair<std::optional<unsigned>, LayerOp>> layerStack;
6580 auto parseOne = [&](
Block *block) -> ParseResult {
6581 auto indent = getIndentation();
6582 StringRef id, convention;
6585 if (parseId(
id,
"expected layer name") ||
6586 parseToken(FIRToken::comma,
"expected ','") ||
6587 parseGetSpelling(convention))
6590 auto layerConvention = symbolizeLayerConvention(convention);
6591 if (!layerConvention) {
6592 emitError() <<
"unknown convention '" << convention
6593 <<
"' (did you misspell it?)";
6596 if (layerConvention == LayerConvention::Inline &&
6597 requireFeature({4, 1, 0},
"inline layers"))
6601 hw::OutputFileAttr outputDir;
6602 if (consumeIf(FIRToken::comma)) {
6603 if (getToken().getKind() == FIRToken::string) {
6604 auto text = getToken().getStringValue();
6606 return emitError() <<
"output directory must not be blank";
6607 outputDir = hw::OutputFileAttr::getAsDirectory(getContext(), text);
6608 consumeToken(FIRToken::string);
6612 if (parseToken(FIRToken::colon,
"expected ':' after layer definition") ||
6613 info.parseOptionalInfo())
6615 auto builder = OpBuilder::atBlockEnd(block);
6617 auto layerOp = LayerOp::create(builder,
info.getLoc(),
id,
6618 {}, *layerConvention);
6619 layerOp->getRegion(0).push_back(
new Block());
6621 layerOp->setAttr(
"output_file", outputDir);
6622 layerStack.push_back({indent, layerOp});
6626 if (parseOne(circuit.getBodyBlock()))
6630 while (getIndentation() > baseIndent) {
6631 switch (getToken().getKind()) {
6632 case FIRToken::kw_declgroup:
6633 case FIRToken::kw_layer: {
6636 while (layerStack.back().first >= getIndentation())
6637 layerStack.pop_back();
6638 auto parentLayer = layerStack.back().second;
6639 if (parseOne(&parentLayer.getBody().front()))
6644 return emitError(
"expected 'layer'"),
failure();
6651ParseResult FIRCircuitParser::resolveDomains(
6652 const SmallVectorImpl<std::pair<Attribute, llvm::SMLoc>> &domainsByName,
6653 const DenseMap<Attribute, size_t> &nameToIndex,
6654 SmallVectorImpl<Attribute> &domainsByIndex) {
6656 for (
auto [attr, loc] : domainsByName) {
6657 auto domain = cast<StringAttr>(attr);
6658 auto indexItr = nameToIndex.find(domain);
6659 if (indexItr == nameToIndex.end()) {
6660 emitError(loc) <<
"unknown domain name '" << domain.getValue() <<
"'";
6663 domainsByIndex.push_back(IntegerAttr::get(
6664 IntegerType::get(getContext(), 32, IntegerType::Unsigned),
6671ParseResult FIRCircuitParser::parseDomains(
6672 SmallVectorImpl<std::pair<Attribute, llvm::SMLoc>> &domains,
6673 const DenseMap<Attribute, size_t> &nameToIndex) {
6676 if (parseToken(FIRToken::kw_domains,
"expected 'domains'") ||
6677 parseToken(FIRToken::l_square,
"expected '['"))
6680 if (parseListUntil(FIRToken::r_square, [&]() -> ParseResult {
6682 auto domainLoc = getToken().getLoc();
6683 if (parseId(domain,
"expected domain name"))
6685 domains.push_back({domain, domainLoc});
6695FIRCircuitParser::parseModuleBody(
const SymbolTable &circuitSymTbl,
6696 DeferredModuleToParse &deferredModule,
6697 InnerSymFixups &fixups) {
6698 FModuleLike moduleOp = deferredModule.moduleOp;
6699 auto &body = moduleOp->getRegion(0).front();
6700 auto &portLocs = deferredModule.portLocs;
6704 FIRLexer moduleBodyLexer(getLexer().getSourceMgr(), getContext());
6707 deferredModule.lexerCursor.restore(moduleBodyLexer);
6709 FIRModuleContext moduleContext(&body, getConstants(), moduleBodyLexer,
6714 auto portList = moduleOp.getPorts();
6715 auto portArgs = body.getArguments();
6716 for (
auto tuple : llvm::zip(portList, portLocs, portArgs)) {
6717 PortInfo &port = std::get<0>(tuple);
6718 llvm::SMLoc loc = std::get<1>(tuple);
6719 BlockArgument portArg = std::get<2>(tuple);
6721 if (moduleContext.addSymbolEntry(port.
getName(), portArg, loc))
6725 FIRStmtParser stmtParser(body, moduleContext, fixups, circuitSymTbl, version);
6728 auto result = stmtParser.parseSimpleStmtBlock(deferredModule.indent);
6741ParseResult FIRCircuitParser::parseCircuit(
6742 SmallVectorImpl<const llvm::MemoryBuffer *> &annotationsBufs,
6743 mlir::TimingScope &ts) {
6745 auto indent = getIndentation();
6746 if (parseToken(FIRToken::kw_FIRRTL,
"expected 'FIRRTL'"))
6748 if (!indent.has_value())
6749 return emitError(
"'FIRRTL' must be first token on its line");
6750 if (parseToken(FIRToken::kw_version,
"expected version after 'FIRRTL'") ||
6751 parseVersionLit(
"expected version literal"))
6753 indent = getIndentation();
6755 if (!indent.has_value())
6756 return emitError(
"'circuit' must be first token on its line");
6757 unsigned circuitIndent = *indent;
6761 SMLoc inlineAnnotationsLoc;
6762 StringRef inlineAnnotations;
6765 if (parseToken(FIRToken::kw_circuit,
6766 "expected a top-level 'circuit' definition") ||
6767 parseId(name,
"expected circuit name") ||
6768 parseToken(FIRToken::colon,
"expected ':' in circuit definition") ||
6769 parseOptionalAnnotations(inlineAnnotationsLoc, inlineAnnotations) ||
6770 info.parseOptionalInfo())
6774 OpBuilder b(mlirModule.getBodyRegion());
6775 auto circuit = CircuitOp::create(b,
info.getLoc(), name);
6778 auto parseAnnotationTimer = ts.nest(
"Parse annotations");
6784 SmallVector<Attribute> annos;
6785 if (!inlineAnnotations.empty())
6786 if (importAnnotationsRaw(inlineAnnotationsLoc, inlineAnnotations, annos))
6790 for (
auto *annotationsBuf : annotationsBufs)
6791 if (importAnnotationsRaw(
info.getFIRLoc(), annotationsBuf->getBuffer(),
6795 parseAnnotationTimer.stop();
6803 auto parseTimer = ts.nest(
"Parse modules");
6804 deferredModules.reserve(16);
6808 switch (getToken().getKind()) {
6816 case FIRToken::error:
6820 emitError(
"unexpected token in circuit");
6823 case FIRToken::kw_class:
6824 case FIRToken::kw_declgroup:
6825 case FIRToken::kw_domain:
6826 case FIRToken::kw_extclass:
6827 case FIRToken::kw_extmodule:
6828 case FIRToken::kw_intmodule:
6829 case FIRToken::kw_layer:
6830 case FIRToken::kw_formal:
6831 case FIRToken::kw_module:
6832 case FIRToken::kw_option:
6833 case FIRToken::kw_public:
6834 case FIRToken::kw_simulation:
6835 case FIRToken::kw_type: {
6836 auto indent = getIndentation();
6837 if (!indent.has_value())
6838 return emitError(
"'module' must be first token on its line"),
failure();
6839 unsigned definitionIndent = *indent;
6841 if (definitionIndent <= circuitIndent)
6842 return emitError(
"module should be indented more"),
failure();
6844 if (parseToplevelDefinition(circuit, definitionIndent))
6858 (void)getLexer().translateLocation(
info.getFIRLoc());
6864 DenseMap<Attribute, Location> nameToOrigLoc;
6865 for (
auto &op : *circuit.getBodyBlock()) {
6867 auto symbol = dyn_cast<mlir::SymbolOpInterface>(&op);
6871 auto nameAttr = symbol.getNameAttr();
6874 auto it = nameToOrigLoc.try_emplace(nameAttr, op.getLoc());
6877 .append(
"redefinition of symbol named '", nameAttr.getValue(),
"'")
6878 .attachNote(it.first->second)
6879 .append(
"see existing symbol definition here");
6885 SymbolTable circuitSymTbl(circuit);
6887 moduleFixups.resize(deferredModules.size());
6892 for (
auto &d : deferredModules)
6893 innerSymbolNamespaces.get(
d.moduleOp.getOperation());
6896 auto anyFailed = mlir::failableParallelForEachN(
6897 getContext(), 0, deferredModules.size(), [&](
size_t index) {
6898 if (parseModuleBody(circuitSymTbl, deferredModules[index],
6899 moduleFixups[index]))
6903 if (failed(anyFailed))
6908 for (
auto &fixups : moduleFixups) {
6909 if (failed(fixups.resolve(innerSymbolNamespaces)))
6915 auto parseLayerName = [&](StringRef name) -> Attribute {
6917 auto [head, rest] = name.split(
".");
6918 SmallVector<FlatSymbolRefAttr> nestedRefs;
6919 while (!rest.empty()) {
6921 std::tie(next, rest) = rest.split(
".");
6922 nestedRefs.push_back(FlatSymbolRefAttr::get(getContext(), next));
6924 return SymbolRefAttr::get(getContext(), head, nestedRefs);
6927 auto getArrayAttr = [&](ArrayRef<std::string> strArray,
auto getAttr) {
6928 SmallVector<Attribute> attrArray;
6930 for (
const auto &str : strArray)
6931 attrArray.push_back(getAttr(str));
6932 if (attrArray.empty())
6934 return ArrayAttr::get(
context, attrArray);
6937 if (
auto enableLayers =
6938 getArrayAttr(getConstants().options.enableLayers, parseLayerName))
6939 circuit.setEnableLayersAttr(enableLayers);
6940 if (
auto disableLayers =
6941 getArrayAttr(getConstants().options.disableLayers, parseLayerName))
6942 circuit.setDisableLayersAttr(disableLayers);
6944 auto getStrAttr = [&](StringRef str) -> Attribute {
6945 return StringAttr::get(getContext(), str);
6948 if (
auto selectInstChoice =
6949 getArrayAttr(getConstants().options.selectInstanceChoice, getStrAttr))
6950 circuit.setSelectInstChoiceAttr(selectInstChoice);
6952 circuit.setDefaultLayerSpecialization(
6953 getConstants().options.defaultLayerSpecialization);
6963mlir::OwningOpRef<mlir::ModuleOp>
6965 mlir::TimingScope &ts, FIRParserOptions options) {
6966 const auto *sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
6967 SmallVector<const llvm::MemoryBuffer *> annotationsBufs;
6968 unsigned fileID = 1;
6970 annotationsBufs.push_back(
6971 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID() + fileID));
6973 context->loadDialect<CHIRRTLDialect>();
6974 context->loadDialect<FIRRTLDialect, hw::HWDialect>();
6977 mlir::OwningOpRef<mlir::ModuleOp> module(ModuleOp::create(
6978 FileLineColLoc::get(
context, sourceBuf->getBufferIdentifier(),
6981 SharedParserConstants state(
context, options);
6982 FIRLexer lexer(sourceMgr,
context);
6984 .parseCircuit(annotationsBufs, ts))
6989 auto circuitVerificationTimer = ts.nest(
"Verify circuit");
6990 if (failed(verify(*module)))
6997 static mlir::TranslateToMLIRRegistration fromFIR(
6998 "import-firrtl",
"import .fir",
6999 [](llvm::SourceMgr &sourceMgr, MLIRContext *
context) {
7000 mlir::TimingScope ts;
assert(baseType &&"element must be base type")
static ParseResult parseParameterList(OpAsmParser &parser, SmallVector< Attribute > ¶meters)
Parse an parameter list if present.
static std::unique_ptr< Context > context
static mlir::Operation * resolve(Context &context, mlir::SymbolRefAttr sym)
std::vector< UnbundledValueEntry > UnbundledValuesList
SmallVector< std::pair< Attribute, Value > > UnbundledValueEntry
llvm::PointerUnion< Value, UnbundledID > SymbolValueEntry
llvm::DenseMap< std::pair< Value, unsigned >, Value > SubaccessCache
ModuleSymbolTable::MapEntryTy ModuleSymbolTableEntry
llvm::StringMap< std::pair< SMLoc, SymbolValueEntry >, llvm::BumpPtrAllocator > ModuleSymbolTable
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 Location getLoc(DefSlot slot)
false return failure()
Parse an optional keyword or string and set instance into 'result'.
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.
FieldRef getSubField(unsigned subFieldID) const
Get a reference to a subfield.
Value getValue() const
Get the Value which created this location.
This implements a lexer 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.
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.
static Direction get(bool isOutput)
Return an output direction if isOutput is true, otherwise return an input direction.
BaseTy type_cast(Type type)
Flow swapFlow(Flow flow)
Get a flow's reverse.
void registerFromFIRFileTranslation()
constexpr FIRVersion nextFIRVersion(7, 0, 0)
The next version of FIRRTL that is not yet released.
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
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.
void emitConnect(OpBuilder &builder, Location loc, Value lhs, Value rhs, bool warnOnTruncation=false)
Emit a connect between two values.
mlir::ParseResult parseFormatString(mlir::OpBuilder &builder, mlir::Location loc, llvm::StringRef formatString, llvm::ArrayRef< mlir::Value > specOperands, mlir::StringAttr &formatStringResult, llvm::SmallVectorImpl< mlir::Value > &operands)
mlir::OwningOpRef< mlir::ModuleOp > importFIRFile(llvm::SourceMgr &sourceMgr, mlir::MLIRContext *context, mlir::TimingScope &ts, FIRParserOptions options={})
BaseTy type_dyn_cast(Type type)
constexpr FIRVersion missingSpecFIRVersion
A marker for parser features that are currently missing from the spec.
hw::InnerSymTarget getTargetFor(FieldRef ref)
Return the inner sym target for the specified value and fieldID.
constexpr FIRVersion minimumFIRVersion(2, 0, 0)
The current minimum version of FIRRTL that the parser supports.
bool importAnnotationsFromJSONRaw(llvm::json::Value &value, SmallVectorImpl< Attribute > &annotations, llvm::json::Path path, MLIRContext *context)
Deserialize a JSON value into FIRRTL Annotations.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
unsigned numAnnotationFiles
The number of annotation files that were specified on the command line.
InfoLocHandling infoLocatorHandling
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.
static std::optional< FIRVersion > fromString(StringRef str)
Parse a version string of the form "major.minor.patch".
StringRef getName() const