Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIRRTL][Emitter] RWProbeOp, RefCast, better forceable support. #5779

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/circt/Dialect/FIRRTL/FIRRTLVisitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class ExprVisitor {
// Miscellaneous.
BitsPrimOp, HeadPrimOp, MuxPrimOp, PadPrimOp, ShlPrimOp, ShrPrimOp,
TailPrimOp, VerbatimExprOp, HWStructCastOp, BitCastOp, RefSendOp,
RefResolveOp, RefSubOp,
RefResolveOp, RefSubOp, RWProbeOp,
// Casts to deal with weird stuff
UninferredResetCastOp, ConstCastOp, RefCastOp,
mlir::UnrealizedConversionCastOp,
Expand Down Expand Up @@ -190,6 +190,7 @@ class ExprVisitor {
HANDLE(RefSendOp, Unhandled);
HANDLE(RefResolveOp, Unhandled);
HANDLE(RefSubOp, Unhandled);
HANDLE(RWProbeOp, Unhandled);

// Conversions.
HANDLE(HWStructCastOp, Unhandled);
Expand Down
99 changes: 76 additions & 23 deletions lib/Dialect/FIRRTL/Export/FIREmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ struct Emitter {
void emitExpression(RefResolveOp op);
void emitExpression(RefSendOp op);
void emitExpression(RefSubOp op);
void emitExpression(RWProbeOp op);
void emitExpression(RefCastOp op);
void emitExpression(UninferredResetCastOp op);
void emitExpression(ConstCastOp op);
void emitExpression(StringConstantOp op);
Expand Down Expand Up @@ -310,10 +312,27 @@ struct Emitter {
auto it = valueNamesStorage.insert(str);
valueNames.insert({value, it.first->getKey()});
}
void addForceable(Forceable op, StringAttr attr) {
addValueName(op.getData(), attr);
if (op.isForceable()) {
SmallString<32> rwName;
(Twine("rwprobe(") + attr.strref() + ")").toVector(rwName);
addValueName(op.getDataRef(), rwName);
}
}

/// The current circuit namespace valid within the call to `emitCircuit`.
CircuitNamespace circuitNamespace;

/// Symbol and Inner Symbol analyses, valid within the call to `emitCircuit`.
struct SymInfos {
SymbolTable symbolTable;
hw::InnerSymbolTableCollection istc;
hw::InnerRefNamespace irn{symbolTable, istc};
SymInfos(Operation *op) : symbolTable(op), istc(op){};
};
std::optional<std::reference_wrapper<SymInfos>> symInfos;

/// The version of the FIRRTL spec that should be emitted.
FIRVersion version;
};
Expand All @@ -324,6 +343,8 @@ LogicalResult Emitter::finalize() { return failure(encounteredError); }
/// Emit an entire circuit.
void Emitter::emitCircuit(CircuitOp op) {
circuitNamespace.add(op);
SymInfos circuitSymInfos(op);
symInfos = circuitSymInfos;
startStatement();
ps << "FIRRTL version ";
ps.addAsString(version.major);
Expand All @@ -350,6 +371,7 @@ void Emitter::emitCircuit(CircuitOp op) {
}
});
circuitNamespace.clear();
symInfos = std::nullopt;
}

/// Emit an entire module.
Expand Down Expand Up @@ -549,7 +571,7 @@ void Emitter::emitStatement(WhenOp op) {

void Emitter::emitStatement(WireOp op) {
auto legalName = legalize(op.getNameAttr());
addValueName(op.getResult(), legalName);
addForceable(op, legalName);
startStatement();
ps.scopedBox(PP::ibox2, [&]() {
ps << "wire " << PPExtString(legalName);
Expand All @@ -560,7 +582,7 @@ void Emitter::emitStatement(WireOp op) {

void Emitter::emitStatement(RegOp op) {
auto legalName = legalize(op.getNameAttr());
addValueName(op.getResult(), legalName);
addForceable(op, legalName);
startStatement();
ps.scopedBox(PP::ibox2, [&]() {
ps << "reg " << PPExtString(legalName);
Expand All @@ -573,7 +595,7 @@ void Emitter::emitStatement(RegOp op) {

void Emitter::emitStatement(RegResetOp op) {
auto legalName = legalize(op.getNameAttr());
addValueName(op.getResult(), legalName);
addForceable(op, legalName);
startStatement();
if (FIRVersion::compare(version, {3, 0, 0}) >= 0) {
ps.scopedBox(PP::ibox2, [&]() {
Expand Down Expand Up @@ -609,7 +631,7 @@ void Emitter::emitStatement(RegResetOp op) {

void Emitter::emitStatement(NodeOp op) {
auto legalName = legalize(op.getNameAttr());
addValueName(op.getResult(), legalName);
addForceable(op, legalName);
startStatement();
emitAssignLike([&]() { ps << "node " << PPExtString(legalName); },
[&]() { emitExpression(op.getInput()); });
Expand Down Expand Up @@ -889,22 +911,9 @@ void Emitter::emitStatement(MemoryPortAccessOp op) {

void Emitter::emitStatement(RefDefineOp op) {
startStatement();
emitAssignLike(
[&]() {
ps << "define ";
emitExpression(op.getDest());
},
[&]() {
auto src = op.getSrc();
if (auto forceable = src.getDefiningOp<Forceable>();
forceable && forceable.isForceable() &&
forceable.getDataRef() == src) {
ps << "rwprobe(";
emitExpression(forceable.getData());
ps << ")";
} else
emitExpression(src);
});
emitAssignLike([&]() { emitExpression(op.getDest()); },
[&]() { emitExpression(op.getSrc()); }, PPExtString("="),
PPExtString("define"));
emitLocationAndNewLine(op);
}

Expand Down Expand Up @@ -1014,9 +1023,10 @@ void Emitter::emitExpression(Value value) {
ShrPrimOp, UninferredResetCastOp, ConstCastOp, StringConstantOp,
FIntegerConstantOp,
// Reference expressions
RefSendOp, RefResolveOp, RefSubOp>([&](auto op) {
ps.scopedBox(PP::ibox0, [&]() { emitExpression(op); });
})
RefSendOp, RefResolveOp, RefSubOp, RWProbeOp, RefCastOp>(
[&](auto op) {
ps.scopedBox(PP::ibox0, [&]() { emitExpression(op); });
})
.Default([&](auto op) {
emitOpError(op, "not supported as expression");
ps << "<unsupported-expr-" << PPExtString(op->getName().stripDialect())
Expand Down Expand Up @@ -1114,6 +1124,49 @@ void Emitter::emitExpression(RefSubOp op) {
[&](auto type) { ps << "." << type.getElementName(op.getIndex()); });
}

void Emitter::emitExpression(RWProbeOp op) {
ps << "rwprobe(";

// Find the probe target.
auto target = symInfos->get().irn.lookup(op.getTarget());
Value base;
if (target.isPort()) {
auto mod = cast<FModuleOp>(target.getOp());
auto port = target.getPort();
base = mod.getArgument(port);
} else
base = cast<hw::InnerSymbolOpInterface>(target.getOp()).getTargetResult();

// Print target. Needs this to have a name already.
emitExpression(base);

// Print indexing for the target field.
auto fieldID = target.getField();
auto type = base.getType();
while (fieldID) {
FIRRTLTypeSwitch<Type, void>(type)
.Case<FVectorType, OpenVectorType>([&](auto vecTy) {
auto index = vecTy.getIndexForFieldID(fieldID);
ps << "[";
ps.addAsString(index);
ps << "]";
auto [subtype, subfieldID] = vecTy.getSubTypeByFieldID(fieldID);
type = subtype;
fieldID = subfieldID;
})
.Case<BundleType, OpenBundleType>([&](auto bundleTy) {
auto index = bundleTy.getIndexForFieldID(fieldID);
ps << "." << bundleTy.getElementName(index);
auto [subtype, subfieldID] = bundleTy.getSubTypeByFieldID(fieldID);
type = subtype;
fieldID = subfieldID;
});
}
ps << ")";
}

void Emitter::emitExpression(RefCastOp op) { emitExpression(op.getInput()); }

void Emitter::emitExpression(UninferredResetCastOp op) {
emitExpression(op.getInput());
}
Expand Down
19 changes: 19 additions & 0 deletions test/Dialect/FIRRTL/emit-basic.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -693,4 +693,23 @@ firrtl.circuit "Foo" {
}
}

// CHECK: module RWProbe :
// CHECK-NEXT: input in : { a : UInt<1> }[2]
// CHECK-NEXT: output p : RWProbe<UInt<1>>
// CHECK-NEXT: output p2 : RWProbe<UInt>
// CHECK-EMPTY:
// CHECK-NEXT: define p = rwprobe(in[1].a)
// CHECK-NEXT: node q = read(p)
// CHECK-NEXT: define p2 = rwprobe(q)
firrtl.module private @RWProbe(in %in: !firrtl.vector<bundle<a: uint<1>>, 2> sym [<@sym,4,public>],
out %p: !firrtl.rwprobe<uint<1>>,
out %p2 : !firrtl.rwprobe<uint>) {
%0 = firrtl.ref.rwprobe <@RWProbe::@sym> : !firrtl.rwprobe<uint<1>>
firrtl.ref.define %p, %0 : !firrtl.rwprobe<uint<1>>

%read = firrtl.ref.resolve %p : !firrtl.rwprobe<uint<1>>
%q, %q_ref = firrtl.node interesting_name %read forceable : !firrtl.uint<1>
%refcast = firrtl.ref.cast %q_ref : (!firrtl.rwprobe<uint<1>>) -> !firrtl.rwprobe<uint>
firrtl.ref.define %p2, %refcast : !firrtl.rwprobe<uint>
}
}