23
23
// * Inference passes, especially width inference. Probes infer slightly
24
24
// differently than non-probes do (must have same width along the chain).
25
25
//
26
- // Forceable and colored probes are not supported.
26
+ // Colored probes are not supported.
27
27
// Specialize layers on or off to remove colored probes first.
28
28
//
29
29
// Debug ports on FIRRTL memories are not currently supported,
@@ -66,7 +66,7 @@ namespace {
66
66
67
67
class ProbeVisitor : public FIRRTLVisitor <ProbeVisitor, LogicalResult> {
68
68
public:
69
- ProbeVisitor () = default ;
69
+ ProbeVisitor (hw::InnerRefNamespace &irn) : irn(irn) {}
70
70
71
71
// / Entrypoint.
72
72
LogicalResult visit (FModuleLike mod);
@@ -91,9 +91,6 @@ class ProbeVisitor : public FIRRTLVisitor<ProbeVisitor, LogicalResult> {
91
91
if (!refType)
92
92
return Type ();
93
93
94
- if (refType.getForceable ())
95
- return err (" rwprobe not supported" );
96
-
97
94
if (refType.getLayer ())
98
95
return err (" layer-colored probes not supported" );
99
96
@@ -141,39 +138,58 @@ class ProbeVisitor : public FIRRTLVisitor<ProbeVisitor, LogicalResult> {
141
138
142
139
// / Check declarations specifically before forwarding to unhandled.
143
140
LogicalResult visitUnhandledDecl (Operation *op) {
144
- // Check for and reject forceable declarations explicitly .
141
+ // Check for and handle active forceable declarations.
145
142
if (auto fop = dyn_cast<Forceable>(op); fop && fop.isForceable ())
146
- return fop. emitError ( " forceable declaration not supported " );
143
+ return visitActiveForceableDecl (fop );
147
144
return visitUnhandledOp (op);
148
145
}
149
146
150
147
// Declarations
151
148
152
149
LogicalResult visitDecl (MemOp op);
153
150
LogicalResult visitDecl (WireOp op);
151
+ LogicalResult visitActiveForceableDecl (Forceable fop);
154
152
155
153
LogicalResult visitInstanceLike (Operation *op);
156
154
LogicalResult visitDecl (InstanceOp op) { return visitInstanceLike (op); }
157
155
LogicalResult visitDecl (InstanceChoiceOp op) { return visitInstanceLike (op); }
158
156
159
157
// Probe operations.
160
158
161
- LogicalResult visitExpr (RWProbeOp op) {
162
- return op.emitError (" rwprobe not supported" );
163
- }
159
+ LogicalResult visitExpr (RWProbeOp op);
164
160
LogicalResult visitExpr (RefCastOp op);
165
161
LogicalResult visitExpr (RefResolveOp op);
166
162
LogicalResult visitExpr (RefSendOp op);
167
163
LogicalResult visitExpr (RefSubOp op);
168
164
169
165
LogicalResult visitStmt (RefDefineOp op);
170
166
167
+ // Force and release operations: reject as unsupported.
168
+ LogicalResult visitStmt (RefForceOp op) {
169
+ return op.emitError (" force not supported" );
170
+ }
171
+ LogicalResult visitStmt (RefForceInitialOp op) {
172
+ return op.emitError (" force_initial not supported" );
173
+ }
174
+ LogicalResult visitStmt (RefReleaseOp op) {
175
+ return op.emitError (" release not supported" );
176
+ }
177
+ LogicalResult visitStmt (RefReleaseInitialOp op) {
178
+ return op.emitError (" release_initial not supported" );
179
+ }
180
+
171
181
private:
172
182
// / Map from probe-typed Value's to their non-probe equivalent.
173
183
DenseMap<Value, Value> probeToHWMap;
174
184
185
+ // / Forceable operations to demote.
186
+ SmallVector<Forceable> forceables;
187
+
175
188
// / Operations to delete.
176
189
SmallVector<Operation *> toDelete;
190
+
191
+ // / Read-only copy of inner-ref namespace for resolving inner refs.
192
+ hw::InnerRefNamespace &irn;
177
193
};
178
194
179
195
} // end namespace
@@ -260,6 +276,10 @@ LogicalResult ProbeVisitor::visit(FModuleLike mod) {
260
276
for (auto *op : llvm::reverse (toDelete))
261
277
op->erase ();
262
278
279
+ // Demote forceable's.
280
+ for (auto fop : forceables)
281
+ firrtl::detail::replaceWithNewForceability (fop, false );
282
+
263
283
return success ();
264
284
}
265
285
@@ -384,7 +404,7 @@ LogicalResult ProbeVisitor::visitDecl(MemOp op) {
384
404
385
405
LogicalResult ProbeVisitor::visitDecl (WireOp op) {
386
406
if (op.isForceable ())
387
- return op. emitError ( " forceable declaration not supported " );
407
+ return visitActiveForceableDecl (op );
388
408
389
409
auto conv = convertType (op.getDataRaw ().getType (), op.getLoc ());
390
410
if (failed (conv))
@@ -402,6 +422,28 @@ LogicalResult ProbeVisitor::visitDecl(WireOp op) {
402
422
return success ();
403
423
}
404
424
425
+ LogicalResult ProbeVisitor::visitActiveForceableDecl (Forceable fop) {
426
+ assert (fop.isForceable () && " must be called on active forceables" );
427
+ // Map rw ref result to normal result.
428
+ auto data = fop.getData ();
429
+ auto conv = mapType (fop.getDataRef ().getType (), fop.getLoc ());
430
+ if (failed (conv))
431
+ return failure ();
432
+ auto newType = *conv;
433
+ forceables.push_back (fop);
434
+
435
+ assert (newType == data.getType ().getPassiveType ());
436
+ if (newType != data.getType ()) {
437
+ ImplicitLocOpBuilder builder (fop.getLoc (), fop);
438
+ builder.setInsertionPointAfterValue (data);
439
+ auto wire = builder.create <WireOp>(newType);
440
+ emitConnect (builder, wire.getData (), data);
441
+ data = wire.getData ();
442
+ }
443
+ probeToHWMap[fop.getDataRef ()] = data;
444
+ return success ();
445
+ }
446
+
405
447
LogicalResult ProbeVisitor::visitInstanceLike (Operation *op) {
406
448
SmallVector<Type> newTypes;
407
449
auto needsConv = mapRange (op->getResultTypes (), op->getLoc (), newTypes);
@@ -461,6 +503,33 @@ LogicalResult ProbeVisitor::visitStmt(RefDefineOp op) {
461
503
return success ();
462
504
}
463
505
506
+ LogicalResult ProbeVisitor::visitExpr (RWProbeOp op) {
507
+ // Handle similar to ref.send but lookup the target
508
+ // and materialize a value for it (indexing).
509
+ auto conv = mapType (op.getType (), op.getLoc ());
510
+ if (failed (conv))
511
+ return failure ();
512
+ auto newType = *conv;
513
+ toDelete.push_back (op);
514
+
515
+ auto ist = irn.lookup (op.getTarget ());
516
+ assert (ist);
517
+ auto ref = getFieldRefForTarget (ist);
518
+
519
+ ImplicitLocOpBuilder builder (op.getLoc (), op);
520
+ builder.setInsertionPointAfterValue (ref.getValue ());
521
+ auto data = getValueByFieldID (builder, ref.getValue (), ref.getFieldID ());
522
+ assert (cast<FIRRTLBaseType>(data.getType ()).getPassiveType () ==
523
+ op.getType ().getType ());
524
+ if (newType != data.getType ()) {
525
+ auto wire = builder.create <WireOp>(newType);
526
+ emitConnect (builder, wire.getData (), data);
527
+ data = wire.getData ();
528
+ }
529
+ probeToHWMap[op.getResult ()] = data;
530
+ return success ();
531
+ }
532
+
464
533
LogicalResult ProbeVisitor::visitExpr (RefCastOp op) {
465
534
auto input = probeToHWMap.at (op.getInput ());
466
535
// Insert wire of the new type, and connect to it.
@@ -546,8 +615,11 @@ void ProbesToSignalsPass::runOnOperation() {
546
615
547
616
SmallVector<Operation *, 0 > ops (getOperation ().getOps <FModuleLike>());
548
617
618
+ hw::InnerRefNamespace irn{getAnalysis<SymbolTable>(),
619
+ getAnalysis<hw::InnerSymbolTableCollection>()};
620
+
549
621
auto result = failableParallelForEach (&getContext (), ops, [&](Operation *op) {
550
- ProbeVisitor visitor;
622
+ ProbeVisitor visitor (irn) ;
551
623
return visitor.visit (cast<FModuleLike>(op));
552
624
});
553
625
0 commit comments