Skip to content

Commit fbb7fa2

Browse files
[stinkytofu] Add DPP modifier support in RawAsmParser
VOP instructions with DPP modifiers (row_xmask, row_shl, row_ror, etc.) were falling to TEXTBLOCK because VOP microcode formats have no modKey mapping. DPP is an add-on encoding variant layered on top of the base VOP format — the assembler picks a wider encoding when DPP modifiers are present. Add field-based DPP detection after modifier token collection via hasDPPFields() helper. When modKey is empty and DPP fields are present, assign modKey = "mod.dpp" post-hoc. This avoids mapping all VOP formats to DPP which would interfere with non-DPP VOP modifiers. Add dppCtrl string field to DPPModifiers for unmodelled DPP modes (row_xmask, row_shl, etc.). Existing typed fields (row_shr, row_bcast, bound_ctrl) preserved for rocisa pipeline compatibility. Add mod.dpp deserialize support in ModifierSerializer.
1 parent e81d594 commit fbb7fa2

4 files changed

Lines changed: 58 additions & 4 deletions

File tree

shared/stinkytofu/include/stinkytofu/ir/asm/StinkyModifiers.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,17 @@ struct DPPModifiers : public TypedModifier<DPPModifiers> {
272272
int row_bcast;
273273
int bound_ctrl;
274274

275-
DPPModifiers(int row_shr = -1, int row_bcast = -1, int bound_ctrl = -1)
275+
// Raw dpp_ctrl string for modes not modelled as typed fields
276+
// (e.g. "row_xmask:8", "row_shl:4"). Emitted verbatim.
277+
std::string dppCtrl;
278+
279+
DPPModifiers(int row_shr = -1, int row_bcast = -1, int bound_ctrl = -1,
280+
const std::string& dppCtrl = "")
276281
: TypedModifier<DPPModifiers>(),
277282
row_shr(row_shr),
278283
row_bcast(row_bcast),
279-
bound_ctrl(bound_ctrl) {}
284+
bound_ctrl(bound_ctrl),
285+
dppCtrl(dppCtrl) {}
280286
};
281287

282288
struct VOP3Modifiers : public TypedModifier<VOP3Modifiers> {

shared/stinkytofu/src/serialization/asm/ModifierSerializer.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,12 @@ void deserializeVisit(StinkyInstruction* inst, const std::string& attrKey,
468468
if (fields.count("tokens")) {
469469
inst->addModifier(MemTokenData(getIntVector(fields, "tokens")));
470470
}
471+
} else if (attrKey == "mod.dpp") {
472+
inst->addModifier(
473+
DPPModifiers(getInt(fields, "row_shr", -1), getInt(fields, "row_bcast", -1),
474+
getInt(fields, "bound_ctrl", -1), getStr(fields, "dppCtrl")));
471475
}
472-
// mod.sdwa, mod.dpp, mod.vop3p, mod.true16: no deserialize support yet
476+
// mod.sdwa, mod.vop3p, mod.true16: no deserialize support yet
473477
}
474478

475479
} // namespace

shared/stinkytofu/src/serialization/asm/RawAsmParser.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,24 @@ bool parseWaitAluSyntax(IRLexer& lexer, ParsedInstruction& inst) {
491491
return true;
492492
}
493493

494+
/// Map of string key → string value used for parsed modifier fields.
495+
using FieldMap = std::unordered_map<std::string, std::string>;
496+
497+
/// Returns true if the field map contains any DPP control modifier key.
498+
/// DPP is an add-on encoding variant layered on top of VOP formats —
499+
/// the assembler picks a wider encoding when DPP modifiers are present.
500+
bool hasDPPFields(const FieldMap& fields) {
501+
// dpp_ctrl modes (13 symbolic names)
502+
return fields.count("quad_perm") || fields.count("row_shl") || fields.count("row_shr") ||
503+
fields.count("row_ror") || fields.count("wave_shl") || fields.count("wave_shr") ||
504+
fields.count("wave_rol") || fields.count("wave_ror") || fields.count("row_mirror") ||
505+
fields.count("row_half_mirror") || fields.count("row_bcast") ||
506+
fields.count("row_share") || fields.count("row_xmask") ||
507+
// other DPP encoding fields
508+
fields.count("bound_ctrl") || fields.count("row_mask") || fields.count("bank_mask") ||
509+
fields.count("fi");
510+
}
511+
494512
/// Parse hwreg(id, offset, width) syntax and store as a LiteralString
495513
/// register on the instruction for verbatim round-trip emission.
496514
void parseHwregOperand(IRLexer& lexer, ParsedInstruction& inst,
@@ -698,7 +716,16 @@ bool parseModifiers(IRLexer& lexer, ParsedInstruction& inst, const HwInstDesc* h
698716
// would be silently discarded below at the `modKey.empty()` early-return,
699717
// so flag the line as unrepresentable instead and let the caller fall
700718
// back to TEXTBLOCK pass-through.
701-
if (modKey.empty() && sawAnyModifier) sawUnrepresentable = true;
719+
// When no modKey was assigned from the microcode format, check if the
720+
// collected fields match a known add-on modifier pattern. DPP is an
721+
// add-on encoding variant whose base microcode format doesn't have a
722+
// dedicated modKey — detect by checking for DPP-specific field names.
723+
if (modKey.empty() && sawAnyModifier) {
724+
if (hasDPPFields(fields))
725+
modKey = "mod.dpp";
726+
else
727+
sawUnrepresentable = true;
728+
}
702729

703730
if (modKey.empty() || fields.empty()) return !sawUnrepresentable;
704731

@@ -739,6 +766,22 @@ bool parseModifiers(IRLexer& lexer, ParsedInstruction& inst, const HwInstDesc* h
739766
if (fields.count("glc")) modFields["glc"] = "true";
740767
if (fields.count("nv")) modFields["nv"] = "true";
741768

769+
} else if (modKey == "mod.dpp") {
770+
if (fields.count("row_shr")) modFields["row_shr"] = fields["row_shr"];
771+
if (fields.count("row_bcast")) modFields["row_bcast"] = fields["row_bcast"];
772+
if (fields.count("bound_ctrl")) modFields["bound_ctrl"] = fields["bound_ctrl"];
773+
// Collect remaining (unmodelled) DPP fields into dppCtrl string for
774+
// verbatim round-trip. Skip the typed fields handled above.
775+
std::string dppCtrl;
776+
for (const auto& [key, val] : fields) {
777+
if (key == "row_shr" || key == "row_bcast" || key == "bound_ctrl") continue;
778+
// Boolean flags (e.g. row_mirror) are stored as "true" —
779+
// emit just the key, not "key:true".
780+
dppCtrl = (val == "true") ? key : key + ":" + val;
781+
break;
782+
}
783+
if (!dppCtrl.empty()) modFields["dppCtrl"] = dppCtrl;
784+
742785
} else if (modKey == "mod.mfma") {
743786
if (fields.count("matrix_a_fmt")) modFields["matrix_a_fmt"] = fields["matrix_a_fmt"];
744787
if (fields.count("matrix_b_fmt")) modFields["matrix_b_fmt"] = fields["matrix_b_fmt"];

shared/stinkytofu/src/serialization/asm/StinkyAsmEmitter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ inline std::ostream& operator<<(std::ostream& os, const SDWAModifiers& sdwaMod)
272272
}
273273

274274
inline std::ostream& operator<<(std::ostream& os, const DPPModifiers& dppMod) {
275+
if (!dppMod.dppCtrl.empty()) os << " " << dppMod.dppCtrl;
275276
if (dppMod.row_shr != -1) os << " row_shr:" << dppMod.row_shr;
276277
if (dppMod.row_bcast != -1) os << " row_bcast:" << dppMod.row_bcast;
277278
if (dppMod.bound_ctrl != -1) os << " bound_ctrl:" << dppMod.bound_ctrl;

0 commit comments

Comments
 (0)