// Each bit of the mask represents an unavailable resource.
uint64_t BusyResourceUnits;
- // Counts the number of instructions dispatched during this cycle that are
- // added to the pending set. This information is used by the bottleneck
- // analysis when analyzing instructions in the pending set.
+ // Counts the number of instructions in the pending set that were dispatched
+ // during this cycle.
unsigned NumDispatchedToThePendingSet;
+ // True if the previous pipeline Stage was unable to dispatch a full group of
+ // opcodes because scheduler buffers (or LS queues) were unavailable.
+ bool HadTokenStall;
+
/// Verify the given selection strategy and set the Strategy member
/// accordingly. If no strategy is provided, the DefaultSchedulerStrategy is
/// used.
Scheduler(std::unique_ptr<ResourceManager> RM, LSUnit &Lsu,
std::unique_ptr<SchedulerStrategy> SelectStrategy)
: LSU(Lsu), Resources(std::move(RM)), BusyResourceUnits(0),
- NumDispatchedToThePendingSet(0) {
+ NumDispatchedToThePendingSet(0), HadTokenStall(false) {
initializeStrategy(std::move(SelectStrategy));
}
SC_DISPATCH_GROUP_STALL,
};
- /// Check if the instruction in 'IR' can be dispatched and returns an answer
- /// in the form of a Status value.
+ /// Check if the instruction in 'IR' can be dispatched during this cycle.
+ /// Return SC_AVAILABLE if both scheduler and LS resources are available.
///
- /// The DispatchStage is responsible for querying the Scheduler before
- /// dispatching new instructions. This routine is used for performing such
- /// a query. If the instruction 'IR' can be dispatched, then true is
- /// returned, otherwise false is returned with Event set to the stall type.
- /// Internally, it also checks if the load/store unit is available.
- Status isAvailable(const InstRef &IR) const;
+ /// This method internally sets field HadTokenStall based on the Scheduler
+ /// Status value.
+ Status isAvailable(const InstRef &IR);
/// Reserves buffer and LSUnit queue resources that are necessary to issue
/// this instruction.
bool isReadySetEmpty() const { return ReadySet.empty(); }
bool isWaitSetEmpty() const { return WaitSet.empty(); }
+ // Returns true if the dispatch logic couldn't dispatch a full group due to
+ // unavailable scheduler and/or LS resources.
+ bool hadTokenStall() const { return HadTokenStall; }
+
#ifndef NDEBUG
// Update the ready queues.
void dump() const;
}
#endif
-Scheduler::Status Scheduler::isAvailable(const InstRef &IR) const {
+Scheduler::Status Scheduler::isAvailable(const InstRef &IR) {
const InstrDesc &Desc = IR.getInstruction()->getDesc();
- switch (Resources->canBeDispatched(Desc.Buffers)) {
+ ResourceStateEvent RSE = Resources->canBeDispatched(Desc.Buffers);
+ HadTokenStall = RSE != RS_BUFFER_AVAILABLE;
+
+ switch (RSE) {
case ResourceStateEvent::RS_BUFFER_UNAVAILABLE:
return Scheduler::SC_BUFFERS_FULL;
case ResourceStateEvent::RS_RESERVED:
}
// Give lower priority to LSUnit stall events.
- switch (LSU.isAvailable(IR)) {
+ LSUnit::Status LSS = LSU.isAvailable(IR);
+ HadTokenStall = LSS != LSUnit::LSU_AVAILABLE;
+
+ switch (LSS) {
case LSUnit::LSU_LQUEUE_FULL:
return Scheduler::SC_LOAD_QUEUE_FULL;
case LSUnit::LSU_SQUEUE_FULL: