10 #include "slang/text/SFormat.h"
13 using namespace circt;
14 using namespace ImportVerilog;
15 using moore::IntAlign;
16 using moore::IntFormat;
17 using moore::IntPadding;
18 using slang::SFormat::FormatOptions;
21 struct FormatStringParser {
25 ArrayRef<const slang::ast::Expression *> arguments;
30 IntFormat defaultFormat;
33 SmallVector<Value> fragments;
35 FormatStringParser(
Context &context,
36 ArrayRef<const slang::ast::Expression *> arguments,
37 Location loc, IntFormat defaultFormat)
38 : context(context), builder(context.builder), arguments(arguments),
39 loc(loc), defaultFormat(defaultFormat) {}
42 FailureOr<Value> parse(
bool appendNewline) {
43 while (!arguments.empty()) {
44 const auto &arg = *arguments[0];
45 arguments = arguments.drop_front();
46 if (arg.kind == slang::ast::ExpressionKind::EmptyArgument)
49 if (
auto *lit = arg.as_if<slang::ast::StringLiteral>()) {
50 if (failed(parseFormat(lit->getValue())))
53 if (failed(emitDefault(arg)))
64 if (fragments.empty())
66 if (fragments.size() == 1)
68 return builder.create<moore::FormatConcatOp>(loc, fragments).getResult();
73 LogicalResult parseFormat(StringRef format) {
74 bool anyFailure =
false;
75 auto onText = [&](
auto text) {
80 auto onArg = [&](
auto specifier,
auto offset,
auto len,
81 const auto &options) {
84 if (failed(emitArgument(specifier, format.substr(offset, len), options)))
87 auto onError = [&](
auto,
auto,
auto,
auto) {
88 assert(
false &&
"Slang should have already reported all errors");
90 slang::SFormat::parse(format, onText, onArg, onError);
91 return failure(anyFailure);
95 void emitLiteral(StringRef literal) {
96 fragments.push_back(builder.create<moore::FormatLiteralOp>(loc, literal));
101 LogicalResult emitArgument(
char specifier, StringRef fullSpecifier,
102 const FormatOptions &options) {
103 auto specifierLower = std::tolower(specifier);
106 if (specifierLower ==
'm' || specifierLower ==
'l')
107 return mlir::emitError(loc)
108 <<
"unsupported format specifier `" << fullSpecifier <<
"`";
112 assert(!arguments.empty() &&
"Slang guarantees correct arg count");
113 const auto &arg = *arguments[0];
114 arguments = arguments.drop_front();
119 switch (specifierLower) {
121 return emitInteger(arg, options, IntFormat::Binary);
123 return emitInteger(arg, options, IntFormat::Octal);
125 return emitInteger(arg, options, IntFormat::Decimal);
128 return emitInteger(arg, options,
129 std::isupper(specifier) ? IntFormat::HexUpper
130 : IntFormat::HexLower);
134 if (
auto *lit = arg.as_if<slang::ast::StringLiteral>()) {
136 return mlir::emitError(loc)
137 <<
"string format specifier with width not supported";
138 emitLiteral(lit->getValue());
141 return mlir::emitError(argLoc)
142 <<
"expression cannot be formatted as string";
145 return mlir::emitError(loc)
146 <<
"unsupported format specifier `" << fullSpecifier <<
"`";
151 LogicalResult emitInteger(
const slang::ast::Expression &arg,
152 const FormatOptions &options, IntFormat format) {
161 width = *options.width;
163 width = cast<moore::IntType>(value.getType()).getWidth();
164 if (format == IntFormat::Octal)
166 width = (width + 2) / 3;
167 else if (format == IntFormat::HexLower || format == IntFormat::HexUpper)
169 width = (width + 3) / 4;
170 else if (format == IntFormat::Decimal)
176 auto alignment = options.leftJustify ? IntAlign::Left : IntAlign::Right;
178 format == IntFormat::Decimal ? IntPadding::Space : IntPadding::Zero;
180 fragments.push_back(builder.create<moore::FormatIntOp>(
181 loc, value, format, width, alignment, padding));
186 LogicalResult emitDefault(
const slang::ast::Expression &expr) {
187 FormatOptions options;
188 return emitInteger(expr, options, defaultFormat);
193 FailureOr<Value> Context::convertFormatString(
194 slang::span<const slang::ast::Expression *const> arguments, Location loc,
195 IntFormat defaultFormat,
bool appendNewline) {
196 FormatStringParser parser(*
this, ArrayRef(arguments.data(), arguments.size()),
198 return parser.parse(appendNewline);
assert(baseType &&"element must be base type")
static void log(char *epId, bool toClient, const MessageData &msg)
Emit the contents of 'msg' to the log file in hex.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
Value convertRvalueExpression(const slang::ast::Expression &expr, Type requiredType={})
Value convertToSimpleBitVector(Value value)
Helper function to convert a value to its simple bit vector representation, if it has one.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.