@@ -222,47 +222,6 @@ struct StmtVisitor {
222222 if (handled == true )
223223 return success ();
224224 }
225-
226- // According to IEEE 1800-2023 Section 21.3.3 "Formatting data to a
227- // string" the first argument of $sformat/$swrite is its output; the
228- // other arguments work like a FormatString.
229- // In Moore we only support writing to a location if it is a reference;
230- // However, Section 21.3.3 explains that the output of $sformat/$swrite
231- // is assigned as if it were cast from a string literal (Section 5.9),
232- // so this implementation casts the string to the target value.
233- if (!call->getSubroutineName ().compare (" $sformat" ) ||
234- !call->getSubroutineName ().compare (" $swrite" )) {
235-
236- // Use the first argument as the output location
237- auto *lhsExpr = call->arguments ().front ();
238- // Format the second and all later arguments as a string
239- auto fmtValue =
240- context.convertFormatString (call->arguments ().subspan (1 ), loc,
241- moore::IntFormat::Decimal, false );
242- if (failed (fmtValue))
243- return failure ();
244- // Convert the FormatString to a StringType
245- auto strValue = moore::FormatStringToStringOp::create (builder, loc,
246- fmtValue.value ());
247- // The Slang AST produces a `AssignmentExpression` for the first
248- // argument; the RHS of this expression is invalid though
249- // (`EmptyArgument`), so we only use the LHS of the
250- // `AssignmentExpression` and plug in the formatted string for the RHS.
251- if (auto assignExpr =
252- lhsExpr->as_if <slang::ast::AssignmentExpression>()) {
253- auto lhs = context.convertLvalueExpression (assignExpr->left ());
254- if (!lhs)
255- return failure ();
256-
257- auto convertedValue = context.materializeConversion (
258- cast<moore::RefType>(lhs.getType ()).getNestedType (), strValue,
259- false , loc);
260- moore::BlockingAssignOp::create (builder, loc, lhs, convertedValue);
261- return success ();
262- } else {
263- return failure ();
264- }
265- }
266225 }
267226
268227 auto value = context.convertRvalueExpression (stmt.expr );
@@ -1006,11 +965,13 @@ struct StmtVisitor {
1006965 }
1007966
1008967 // Display and Write Tasks (`$display[boh]?` or `$write[boh]?` or
1009- // `$fdisplay[boh]?` or `$fwrite[boh]?`)
968+ // `$fdisplay[boh]?` or `$fwrite[boh]?` or `$swrite[boh]` or `$sformat` )
1010969
1011970 using moore::IntFormat;
1012971 bool isDisplay = false ;
1013972 bool isFDisplay = false ;
973+ bool isSWrite = false ;
974+ bool isSFormat = false ;
1014975 bool appendNewline = false ;
1015976 IntFormat defaultFormat = IntFormat::Decimal;
1016977 switch (nameId) {
@@ -1082,6 +1043,24 @@ struct StmtVisitor {
10821043 isFDisplay = true ;
10831044 defaultFormat = IntFormat::HexLower;
10841045 break ;
1046+ case ksn::SFormat:
1047+ isSFormat = true ;
1048+ break ;
1049+ case ksn::SWrite:
1050+ isSWrite = true ;
1051+ break ;
1052+ case ksn::SWriteB:
1053+ isSWrite = true ;
1054+ defaultFormat = IntFormat::Binary;
1055+ break ;
1056+ case ksn::SWriteO:
1057+ isSWrite = true ;
1058+ defaultFormat = IntFormat::Octal;
1059+ break ;
1060+ case ksn::SWriteH:
1061+ isSWrite = true ;
1062+ defaultFormat = IntFormat::HexLower;
1063+ break ;
10851064 default :
10861065 break ;
10871066 }
@@ -1116,6 +1095,43 @@ struct StmtVisitor {
11161095 return true ;
11171096 }
11181097
1098+ // According to IEEE 1800-2023 Section 21.3.3 "Formatting data to a
1099+ // string" the first argument of $sformat/$swrite is its output; the
1100+ // other arguments work like a FormatString.
1101+ // In Moore we only support writing to a location if it is a reference;
1102+ // However, Section 21.3.3 explains that the output of $sformat/$swrite
1103+ // is assigned as if it were cast from a string literal (Section 5.9),
1104+ // so this implementation casts the string to the target value.
1105+ if (isSWrite || isSFormat) {
1106+ if (isSFormat && args.size () < 2 )
1107+ return emitError (loc) << " $sformat requires at least 2 arguments" ;
1108+ if (isSWrite && args.size () < 1 )
1109+ return emitError (loc) << " $swrite requires at least 1 argument" ;
1110+
1111+ auto fmtValue =
1112+ context.convertFormatString (args.subspan (1 ), loc, defaultFormat,
1113+ /* appendNewline=*/ false );
1114+ if (failed (fmtValue))
1115+ return failure ();
1116+ if (*fmtValue == Value{})
1117+ return true ;
1118+ auto strValue =
1119+ moore::FormatStringToStringOp::create (builder, loc, *fmtValue);
1120+ auto *lhsExpr = args[0 ];
1121+ if (auto *assignExpr =
1122+ lhsExpr->as_if <slang::ast::AssignmentExpression>()) {
1123+ auto lhs = context.convertLvalueExpression (assignExpr->left ());
1124+ if (!lhs)
1125+ return failure ();
1126+ auto convertedValue = context.materializeConversion (
1127+ cast<moore::RefType>(lhs.getType ()).getNestedType (), strValue,
1128+ false , loc);
1129+ moore::BlockingAssignOp::create (builder, loc, lhs, convertedValue);
1130+ return true ;
1131+ }
1132+ return failure ();
1133+ }
1134+
11191135 // Severity Tasks
11201136 using moore::Severity;
11211137 std::optional<Severity> severity;
0 commit comments