-
Notifications
You must be signed in to change notification settings - Fork 298
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
[MSFT] Add multicycle path op #6262
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,27 +94,33 @@ struct TclOutputState { | |
SmallVector<Attribute> symbolRefs; | ||
|
||
void emit(PhysLocationAttr); | ||
LogicalResult emitLocationAssignment(DynInstDataOpInterface refOp, | ||
LogicalResult emitLocationAssignment(UnaryDynInstDataOpInterface refOp, | ||
PhysLocationAttr, | ||
std::optional<StringRef> subpath); | ||
|
||
LogicalResult emit(PDPhysRegionOp region); | ||
LogicalResult emit(PDPhysLocationOp loc); | ||
LogicalResult emit(PDRegPhysLocationOp); | ||
LogicalResult emit(DynamicInstanceVerbatimAttrOp attr); | ||
LogicalResult emit(PDMulticycleOp op); | ||
|
||
void emitPath(hw::HierPathOp ref, std::optional<StringRef> subpath); | ||
void emitInnerRefPart(hw::InnerRefAttr innerRef); | ||
|
||
/// Get the HierPathOp to which the given operation is pointing. Add it to | ||
/// the set of used global refs. | ||
HierPathOp getRefOp(DynInstDataOpInterface op) { | ||
auto ref = dyn_cast_or_null<hw::HierPathOp>( | ||
emitter.getDefinition(op.getPathSym())); | ||
HierPathOp getRefOp(UnaryDynInstDataOpInterface op) { | ||
return getRefOp(op.getLoc(), op.getPathSym()); | ||
} | ||
|
||
/// Get the HierPathOp to which a given value is pointing. Add it to the | ||
/// set of used global refs. | ||
HierPathOp getRefOp(Location loc, FlatSymbolRefAttr pathSym) { | ||
auto ref = dyn_cast_or_null<hw::HierPathOp>(emitter.getDefinition(pathSym)); | ||
if (ref) | ||
emitter.usedRef(ref); | ||
else | ||
op.emitOpError("could not find hw.hierpath named ") << op.getPathSym(); | ||
emitError(loc, "could not find hw.hierpath named ") << pathSym; | ||
return ref; | ||
} | ||
}; | ||
|
@@ -166,7 +172,7 @@ void TclOutputState::emit(PhysLocationAttr pla) { | |
/// "set_location_assignment MPDSP_X34_Y285_N0 -to | ||
/// $parent|fooInst|entityName(subpath)" | ||
LogicalResult | ||
TclOutputState::emitLocationAssignment(DynInstDataOpInterface refOp, | ||
TclOutputState::emitLocationAssignment(UnaryDynInstDataOpInterface refOp, | ||
PhysLocationAttr loc, | ||
std::optional<StringRef> subpath) { | ||
indent() << "set_location_assignment "; | ||
|
@@ -199,6 +205,19 @@ LogicalResult TclOutputState::emit(PDRegPhysLocationOp locs) { | |
return success(); | ||
} | ||
|
||
LogicalResult TclOutputState::emit(PDMulticycleOp op) { | ||
indent() << "set_multicycle_path "; | ||
os << "-hold 1 "; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Previous we emitted the hold and setup on different lines of SDC. Have you checked that this works with quartus? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have not, but based on the documentation i see no reason how this should not work. |
||
os << "-setup " << op.getCycles() << " "; | ||
os << "-from [get_registers {$parent|"; | ||
emitPath(getRefOp(op.getLoc(), op.getSourceAttr()), std::nullopt); | ||
os << "}] "; | ||
os << "-to [get_registers {$parent|"; | ||
emitPath(getRefOp(op.getLoc(), op.getDestAttr()), std::nullopt); | ||
os << "}]\n"; | ||
return success(); | ||
} | ||
|
||
/// Emit tcl in the form of: | ||
/// "set_global_assignment -name NAME VALUE -to $parent|fooInst|entityName" | ||
LogicalResult TclOutputState::emit(DynamicInstanceVerbatimAttrOp attr) { | ||
|
@@ -299,6 +318,7 @@ LogicalResult TclEmitter::emit(Operation *hwMod, StringRef outputFile) { | |
.Case([&](PDPhysLocationOp op) { return state.emit(op); }) | ||
.Case([&](PDRegPhysLocationOp op) { return state.emit(op); }) | ||
.Case([&](PDPhysRegionOp op) { return state.emit(op); }) | ||
.Case([&](PDMulticycleOp op) { return state.emit(op); }) | ||
.Case([&](DynamicInstanceVerbatimAttrOp op) { | ||
return state.emit(op); | ||
}) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: dunno if I'd consider a multi-cycle path a PD optimization. If it just generates tcl (as this appears to do), it's needed for correctness (I think), in which case it's definitely not a PD optimization. Just a necessary tcl command which is being abstracted here.
I would suggest (longer term) creating a MCP op in the pipeline dialect which both results in tcl and omits the registers.