blob: 69bd2bf9fc28db59375159746673f27ca369482f [file] [log] [blame]
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +00001//===--------------------- Scheduler.h ------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10///
11/// A scheduler for Processor Resource Units and Processor Resource Groups.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_TOOLS_LLVM_MCA_SCHEDULER_H
16#define LLVM_TOOLS_LLVM_MCA_SCHEDULER_H
17
18#include "Instruction.h"
19#include "LSUnit.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/MC/MCSubtargetInfo.h"
22#include <map>
23
24namespace mca {
25
26class Backend;
Clement Courbet844f22d2018-03-13 13:11:01 +000027class DispatchUnit;
28
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000029/// Used to notify the internal state of a processor resource.
30///
31/// A processor resource is available if it is not reserved, and there are
32/// available slots in the buffer. A processor resource is unavailable if it
33/// is either reserved, or the associated buffer is full. A processor resource
34/// with a buffer size of -1 is always available if it is not reserved.
35///
36/// Values of type ResourceStateEvent are returned by method
37/// ResourceState::isBufferAvailable(), which is used to query the internal
38/// state of a resource.
39///
40/// The naming convention for resource state events is:
41/// * Event names start with prefix RS_
42/// * Prefix RS_ is followed by a string describing the actual resource state.
43enum ResourceStateEvent {
44 RS_BUFFER_AVAILABLE,
45 RS_BUFFER_UNAVAILABLE,
46 RS_RESERVED
47};
48
49/// \brief A descriptor for processor resources.
50///
51/// Each object of class ResourceState is associated to a specific processor
52/// resource. There is an instance of this class for every processor resource
53/// defined by the scheduling model.
54/// A ResourceState dynamically tracks the availability of units of a processor
55/// resource. For example, the ResourceState of a ProcResGroup tracks the
56/// availability of resource units which are part of the group.
57///
58/// Internally, ResourceState uses a round-robin selector to identify
59/// which unit of the group shall be used next.
60class ResourceState {
Andrea Di Biagio0c541292018-03-10 16:55:07 +000061 // Index to the MCProcResourceDesc in the processor Model.
62 unsigned ProcResourceDescIndex;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000063 // A resource unique identifier generated by the tool.
64 // For processor resource groups, the number of number of bits set in this
65 // mask is equivalent to the cardinality of the group plus one.
66 // Excluding the most significant bit, the remaining bits in the resource mask
67 // identify resources that are part of the group.
68 //
69 // Example, lets assume that this ResourceState describes a
70 // group containing ResourceA and ResourceB:
71 //
72 // ResourceA -- Mask: 0b001
73 // ResourceB -- Mask: 0b010
74 // ResourceAB -- Mask: 0b100 U (ResourceA::Mask | ResourceB::Mask) == 0b111
75 //
76 // There is only one bit set for non-group resources.
77 // A ResourceMask can be used to solve set membership problems with simple bit
78 // manipulation operations.
79 uint64_t ResourceMask;
80
81 // A ProcResource can specify a number of units. For the purpose of dynamic
82 // scheduling, a processor resource with more than one unit behaves like a
83 // group. This field has one bit set for every unit/resource that is part of
84 // the group.
85 // For groups, this field defaults to 'ResourceMask'. For non-group
86 // resources, the number of bits set in this mask is equivalent to the
87 // number of units (i.e. field 'NumUnits' in 'ProcResourceUnits').
88 uint64_t ResourceSizeMask;
89
90 // A simple round-robin selector for processor resources.
91 // Each bit of the mask identifies a sub resource within this group.
92 //
93 // As an example, lets assume that this ResourceState describes a
94 // processor resource group composed of the following three units:
95 // ResourceA -- 0b001
96 // ResourceB -- 0b010
97 // ResourceC -- 0b100
98 //
99 // Each unit is identified by a ResourceMask which always contains a
100 // single bit set. Field NextInSequenceMask is initially set to value
101 // 0xb111. That value is obtained by OR'ing the resource masks of
102 // processor resource that are part of the group.
103 //
104 // NextInSequenceMask -- 0b111
105 //
106 // Field NextInSequenceMask is used by the resource manager (i.e.
107 // an object of class ResourceManager) to select the "next available resource"
108 // from the set. The algorithm would prioritize resources with a bigger
109 // ResourceMask value.
110 //
111 // In this example, there are three resources in the set, and 'ResourceC'
112 // has the highest mask value. The round-robin selector would firstly select
113 // 'ResourceC', then 'ResourceB', and eventually 'ResourceA'.
114 //
115 // When a resource R is used, its corresponding bit is cleared from the set.
116 //
117 // Back to the example:
118 // If 'ResourceC' is selected, then the new value of NextInSequenceMask
119 // becomes 0xb011.
120 //
121 // When NextInSequenceMask becomes zero, it is reset to its original value
122 // (in this example, that value would be 0b111).
123 uint64_t NextInSequenceMask;
124
125 // Some instructions can only be issued on very specific pipeline resources.
126 // For those instructions, we know exactly which resource would be consumed
127 // without having to dynamically select it using field 'NextInSequenceMask'.
128 //
129 // The resource mask bit associated to the (statically) selected
130 // processor resource is still cleared from the 'NextInSequenceMask'.
131 // If that bit was already zero in NextInSequenceMask, then we update
132 // mask 'RemovedFromNextInSequence'.
133 //
134 // When NextInSequenceMask is reset back to its initial value, the algorithm
135 // removes any bits which are set in RemoveFromNextInSequence.
136 uint64_t RemovedFromNextInSequence;
137
138 // A mask of ready units.
139 uint64_t ReadyMask;
140
141 // Buffered resources will have this field set to a positive number bigger
142 // than 0. A buffered resource behaves like a separate reservation station
143 // implementing its own buffer for out-of-order execution.
144 // A buffer of 1 is for units that force in-order execution.
145 // A value of 0 is treated specially. In particular, a resource with
146 // A BufferSize = 0 is for an in-order issue/dispatch resource.
147 // That means, this resource is reserved starting from the dispatch event,
148 // until all the "resource cycles" are consumed after the issue event.
149 // While this resource is reserved, no other instruction may be dispatched.
150 int BufferSize;
151
152 // Available slots in the buffer (zero, if this is not a buffered resource).
153 unsigned AvailableSlots;
154
155 // Maximum number of buffer slots seen used during one cycle.
156 // This helps tracking dynamic dispatch stalls caused by the lack of
157 // entries in the scheduler's queue.
158 unsigned MaxUsedSlots;
159
160 // True if this is resource is currently unavailable.
161 // An instruction may "reserve" a resource for a number of cycles.
162 // During those cycles, the reserved resource cannot be used for other
163 // instructions, even if the ReadyMask is set.
164 bool Unavailable;
165
166 bool isSubResourceReady(uint64_t ID) const { return ReadyMask & ID; }
167
168 /// Returns the mask identifier of the next available resource in the set.
169 uint64_t getNextInSequence() const {
170 assert(NextInSequenceMask);
171 return llvm::PowerOf2Floor(NextInSequenceMask);
172 }
173
174 /// Returns the mask of the next available resource within the set,
175 /// and updates the resource selector.
176 void updateNextInSequence() {
177 NextInSequenceMask ^= getNextInSequence();
178 if (!NextInSequenceMask)
179 NextInSequenceMask = ResourceSizeMask;
180 }
181
182 uint64_t computeResourceSizeMaskForGroup(uint64_t ResourceMask) {
183 assert(llvm::countPopulation(ResourceMask) > 1);
184 return ResourceMask ^ llvm::PowerOf2Floor(ResourceMask);
185 }
186
187public:
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000188 ResourceState(const llvm::MCProcResourceDesc &Desc, unsigned Index,
189 uint64_t Mask)
190 : ProcResourceDescIndex(Index), ResourceMask(Mask) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000191 bool IsAGroup = llvm::countPopulation(ResourceMask) > 1;
192 ResourceSizeMask = IsAGroup ? computeResourceSizeMaskForGroup(ResourceMask)
193 : ((1ULL << Desc.NumUnits) - 1);
194 NextInSequenceMask = ResourceSizeMask;
195 RemovedFromNextInSequence = 0;
196 ReadyMask = ResourceSizeMask;
197 BufferSize = Desc.BufferSize;
198 AvailableSlots = BufferSize == -1 ? 0U : static_cast<unsigned>(BufferSize);
199 MaxUsedSlots = 0;
200 Unavailable = false;
201 }
202
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000203 unsigned getProcResourceID() const { return ProcResourceDescIndex; }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000204 uint64_t getResourceMask() const { return ResourceMask; }
205 int getBufferSize() const { return BufferSize; }
206 unsigned getMaxUsedSlots() const { return MaxUsedSlots; }
207
208 bool isBuffered() const { return BufferSize > 0; }
209 bool isInOrder() const { return BufferSize == 1; }
210 bool isADispatchHazard() const { return BufferSize == 0; }
211 bool isReserved() const { return Unavailable; }
212
213 void setReserved() { Unavailable = true; }
214 void clearReserved() { Unavailable = false; }
215
216 // A resource is ready if it is not reserved, and if there are enough
217 // available units.
218 // If a resource is also a dispatch hazard, then we don't check if
219 // it is reserved because that check would always return true.
220 // A resource marked as "dispatch hazard" is always reserved at
221 // dispatch time. When this method is called, the assumption is that
222 // the user of this resource has been already dispatched.
223 bool isReady(unsigned NumUnits = 1) const {
224 return (!isReserved() || isADispatchHazard()) &&
225 llvm::countPopulation(ReadyMask) >= NumUnits;
226 }
227 bool isAResourceGroup() const {
228 return llvm::countPopulation(ResourceMask) > 1;
229 }
230
231 bool containsResource(uint64_t ID) const { return ResourceMask & ID; }
232
233 void markSubResourceAsUsed(uint64_t ID) {
234 assert(isSubResourceReady(ID));
235 ReadyMask ^= ID;
236 }
237
238 void releaseSubResource(uint64_t ID) {
239 assert(!isSubResourceReady(ID));
240 ReadyMask ^= ID;
241 }
242
243 unsigned getNumUnits() const {
244 return isAResourceGroup() ? 1U : llvm::countPopulation(ResourceSizeMask);
245 }
246
247 uint64_t selectNextInSequence();
248 void removeFromNextInSequence(uint64_t ID);
249
250 ResourceStateEvent isBufferAvailable() const {
251 if (isADispatchHazard() && isReserved())
252 return RS_RESERVED;
253 if (!isBuffered() || AvailableSlots)
254 return RS_BUFFER_AVAILABLE;
255 return RS_BUFFER_UNAVAILABLE;
256 }
257
258 void reserveBuffer() {
259 if (AvailableSlots)
260 AvailableSlots--;
261 unsigned UsedSlots = static_cast<unsigned>(BufferSize) - AvailableSlots;
262 MaxUsedSlots = std::max(MaxUsedSlots, UsedSlots);
263 }
264
265 void releaseBuffer() {
266 if (BufferSize > 0)
267 AvailableSlots++;
268 assert(AvailableSlots <= static_cast<unsigned>(BufferSize));
269 }
270
271#ifndef NDEBUG
272 void dump() const;
273#endif
274};
275
276/// \brief A resource unit identifier.
277///
278/// This is used to identify a specific processor resource unit using a pair
279/// of indices where the 'first' index is a processor resource mask, and the
280/// 'second' index is an index for a "sub-resource" (i.e. unit).
281typedef std::pair<uint64_t, uint64_t> ResourceRef;
282
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000283// First: a MCProcResourceDesc index identifying a buffered resource.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000284// Second: max number of buffer entries used in this resource.
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000285typedef std::pair<unsigned, unsigned> BufferUsageEntry;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000286
287/// A resource manager for processor resource units and groups.
288///
289/// This class owns all the ResourceState objects, and it is responsible for
290/// acting on requests from a Scheduler by updating the internal state of
291/// ResourceState objects.
292/// This class doesn't know about instruction itineraries and functional units.
293/// In future, it can be extended to support itineraries too through the same
294/// public interface.
295class ResourceManager {
296 // The resource manager owns all the ResourceState.
297 using UniqueResourceState = std::unique_ptr<ResourceState>;
298 llvm::SmallDenseMap<uint64_t, UniqueResourceState> Resources;
299
300 // Keeps track of which resources are busy, and how many cycles are left
301 // before those become usable again.
302 llvm::SmallDenseMap<ResourceRef, unsigned> BusyResources;
303
304 // A table to map processor resource IDs to processor resource masks.
305 llvm::SmallVector<uint64_t, 8> ProcResID2Mask;
306
307 // Adds a new resource state in Resources, as well as a new descriptor in
308 // ResourceDescriptor.
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000309 void addResource(const llvm::MCProcResourceDesc &Desc, unsigned Index,
310 uint64_t Mask);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000311
312 // Compute processor resource masks for each processor resource declared by
313 // the scheduling model.
314 void computeProcResourceMasks(const llvm::MCSchedModel &SM);
315
316 // Populate resource descriptors.
317 void initialize(const llvm::MCSchedModel &SM) {
318 computeProcResourceMasks(SM);
319 for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I)
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000320 addResource(*SM.getProcResource(I), I, ProcResID2Mask[I]);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000321 }
322
323 // Returns the actual resource unit that will be used.
324 ResourceRef selectPipe(uint64_t ResourceID);
325
326 void use(ResourceRef RR);
327 void release(ResourceRef RR);
328
329 unsigned getNumUnits(uint64_t ResourceID) const {
330 assert(Resources.find(ResourceID) != Resources.end());
331 return Resources.find(ResourceID)->getSecond()->getNumUnits();
332 }
333
334 // Reserve a specific Resource kind.
335 void reserveBuffer(uint64_t ResourceID) {
336 assert(isBufferAvailable(ResourceID) ==
337 ResourceStateEvent::RS_BUFFER_AVAILABLE);
338 ResourceState &Resource = *Resources[ResourceID];
339 Resource.reserveBuffer();
340 }
341
342 void releaseBuffer(uint64_t ResourceID) {
343 Resources[ResourceID]->releaseBuffer();
344 }
345
346 ResourceStateEvent isBufferAvailable(uint64_t ResourceID) const {
347 const ResourceState &Resource = *Resources.find(ResourceID)->second;
348 return Resource.isBufferAvailable();
349 }
350
351 bool isReady(uint64_t ResourceID, unsigned NumUnits) const {
352 const ResourceState &Resource = *Resources.find(ResourceID)->second;
353 return Resource.isReady(NumUnits);
354 }
355
356public:
357 ResourceManager(const llvm::MCSchedModel &SM) { initialize(SM); }
358
Andrea Di Biagioe1a1da12018-03-13 13:58:02 +0000359 ResourceStateEvent
360 canBeDispatched(const llvm::ArrayRef<uint64_t> Buffers) const {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000361 ResourceStateEvent Result = ResourceStateEvent::RS_BUFFER_AVAILABLE;
Andrea Di Biagioe1a1da12018-03-13 13:58:02 +0000362 for (uint64_t Buffer : Buffers) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000363 Result = isBufferAvailable(Buffer);
364 if (Result != ResourceStateEvent::RS_BUFFER_AVAILABLE)
365 break;
366 }
367
368 return Result;
369 }
370
Andrea Di Biagioe1a1da12018-03-13 13:58:02 +0000371 void reserveBuffers(const llvm::ArrayRef<uint64_t> Buffers) {
372 for (const uint64_t R : Buffers)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000373 reserveBuffer(R);
374 }
375
Andrea Di Biagioe1a1da12018-03-13 13:58:02 +0000376 void releaseBuffers(const llvm::ArrayRef<uint64_t> Buffers) {
377 for (const uint64_t R : Buffers)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000378 releaseBuffer(R);
379 }
380
381 void reserveResource(uint64_t ResourceID) {
382 ResourceState &Resource = *Resources[ResourceID];
383 assert(!Resource.isReserved());
384 Resource.setReserved();
385 }
386
387 void releaseResource(uint64_t ResourceID) {
388 ResourceState &Resource = *Resources[ResourceID];
389 Resource.clearReserved();
390 }
391
Andrea Di Biagioe1a1da12018-03-13 13:58:02 +0000392 void reserveDispatchHazardResources(const llvm::ArrayRef<uint64_t> Buffers);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000393
394 // Returns true if all resources are in-order, and there is at least one
395 // resource which is a dispatch hazard (BufferSize = 0).
396 bool mustIssueImmediately(const InstrDesc &Desc);
397
398 bool canBeIssued(const InstrDesc &Desc) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000399
400 void issueInstruction(
401 unsigned Index, const InstrDesc &Desc,
402 llvm::SmallVectorImpl<std::pair<ResourceRef, unsigned>> &Pipes);
403
404 void cycleEvent(llvm::SmallVectorImpl<ResourceRef> &ResourcesFreed);
405
406 void getBuffersUsage(std::vector<BufferUsageEntry> &Usage) const {
407 for (const std::pair<uint64_t, UniqueResourceState> &Resource : Resources) {
408 const ResourceState &RS = *Resource.second;
409 if (RS.isBuffered())
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000410 Usage.emplace_back(std::pair<unsigned, unsigned>(RS.getProcResourceID(),
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000411 RS.getMaxUsedSlots()));
412 }
413 }
414
415 const llvm::ArrayRef<uint64_t> getProcResMasks() const {
416 return ProcResID2Mask;
417 }
418
419#ifndef NDEBUG
420 void dump() const {
421 for (const std::pair<uint64_t, UniqueResourceState> &Resource : Resources)
422 Resource.second->dump();
423 }
424#endif
425}; // namespace mca
426
427/// Class Scheduler is responsible for issuing instructions to pipeline
428/// resources. Internally, it delegates to a ResourceManager the management of
429/// processor resources.
430/// This class is also responsible for tracking the progress of instructions
431/// from the dispatch stage, until the write-back stage.
432///
433/// An nstruction dispatched to the Scheduler is initially placed into either
434/// the 'WaitQueue' or the 'ReadyQueue' depending on the availability of the
435/// input operands. Instructions in the WaitQueue are ordered by instruction
436/// index. An instruction is moved from the WaitQueue to the ReadyQueue when
437/// register operands become available, and all memory dependencies are met.
438/// Instructions that are moved from the WaitQueue to the ReadyQueue transition
439/// from state 'IS_AVAILABLE' to state 'IS_READY'.
440///
441/// At the beginning of each cycle, the Scheduler checks if there are
442/// instructions in the WaitQueue that can be moved to the ReadyQueue. If the
443/// ReadyQueue is not empty, then older instructions from the queue are issued
444/// to the processor pipelines, and the underlying ResourceManager is updated
445/// accordingly. The ReadyQueue is ordered by instruction index to guarantee
446/// that the first instructions in the set are also the oldest.
447///
448/// An Instruction is moved from the ReadyQueue the `IssuedQueue` when it is
449/// issued to a (one or more) pipeline(s). This event also causes an instruction
450/// state transition (i.e. from state IS_READY, to state IS_EXECUTING).
451/// An Instruction leaves the IssuedQueue when it reaches the write-back stage.
452class Scheduler {
453 const llvm::MCSchedModel &SM;
454
455 // Hardware resources that are managed by this scheduler.
456 std::unique_ptr<ResourceManager> Resources;
457 std::unique_ptr<LSUnit> LSU;
458
459 // The Backend gets notified when instructions are ready/issued/executed.
Clement Courbet844f22d2018-03-13 13:11:01 +0000460 Backend *const Owner;
461
462 // The dispatch unit gets notified when instructions are executed.
463 DispatchUnit *DU;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000464
465 using QueueEntryTy = std::pair<unsigned, Instruction *>;
466 std::map<unsigned, Instruction *> WaitQueue;
467 std::map<unsigned, Instruction *> ReadyQueue;
468 std::map<unsigned, Instruction *> IssuedQueue;
469
470 void notifyInstructionIssued(
471 unsigned Index,
472 const llvm::ArrayRef<std::pair<ResourceRef, unsigned>> &Used);
473 void notifyInstructionExecuted(unsigned Index);
474 void notifyInstructionReady(unsigned Index);
475 void notifyResourceAvailable(const ResourceRef &RR);
476
477 /// Issue instructions from the ready queue by giving priority to older
478 /// instructions.
479 void issue();
480
481 /// Issue an instruction without updating the ready queue.
482 void issueInstruction(Instruction *IS, unsigned InstrIndex);
483 void updatePendingQueue();
484 void updateIssuedQueue();
485
486public:
487 Scheduler(Backend *B, const llvm::MCSchedModel &Model, unsigned LoadQueueSize,
488 unsigned StoreQueueSize, bool AssumeNoAlias)
489 : SM(Model), Resources(llvm::make_unique<ResourceManager>(SM)),
490 LSU(llvm::make_unique<LSUnit>(LoadQueueSize, StoreQueueSize,
491 AssumeNoAlias)),
492 Owner(B) {}
493
Clement Courbet844f22d2018-03-13 13:11:01 +0000494 void setDispatchUnit(DispatchUnit *DispUnit) { DU = DispUnit; }
495
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000496 /// Scheduling events.
497 ///
498 /// The DispatchUnit is responsible for querying the Scheduler before
499 /// dispatching new instructions. Queries are performed through method
500 /// `Scheduler::CanBeDispatched`, which returns an instance of this enum to
501 /// tell if the dispatch would fail or not. If scheduling resources are
502 /// available, and the instruction can be dispatched, then the query returns
503 /// HWS_AVAILABLE. A values different than HWS_AVAILABLE means that the
504 /// instruction cannot be dispatched during this cycle.
505 ///
506 /// Each event name starts with prefix "HWS_", and it is followed by
507 /// a substring which describes the reason why the Scheduler was unavailable
508 /// (or "AVAILABLE" if the instruction is allowed to be dispatched).
509 ///
510 /// HWS_QUEUE_UNAVAILABLE is returned if there are not enough available slots
511 /// in the scheduler's queue. That means, one (or more) buffered resources
512 /// consumed by the instruction were full.
513 ///
514 /// HWS_LD_QUEUE_UNAVAILABLE is returned when an instruction 'mayLoad', and
515 /// the load queue in the load/store unit (implemented by class LSUnit) is
516 /// full. Similarly, HWS_ST_QUEUE_UNAVAILABLE is returned when the store
517 /// queue is full, and the instruction to be dispatched 'mayStore'.
518 ///
519 /// HWS_DISPATCH_GROUP_RESTRICTION is only returned in special cases where the
520 /// instruction consumes an in-order issue/dispatch resource (i.e. a resource
521 /// with `BufferSize=0`), and the pipeline resource is not immediately
522 /// available.
523 enum Event {
524 HWS_AVAILABLE,
525 HWS_QUEUE_UNAVAILABLE,
526 HWS_DISPATCH_GROUP_RESTRICTION,
527 HWS_LD_QUEUE_UNAVAILABLE,
528 HWS_ST_QUEUE_UNAVAILABLE
529 };
530
531 Event canBeDispatched(const InstrDesc &Desc) const;
532 Instruction *scheduleInstruction(unsigned Idx, Instruction *MCIS);
533
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000534 void cycleEvent(unsigned Cycle);
535
536 void getBuffersUsage(std::vector<BufferUsageEntry> &Usage) const {
537 Resources->getBuffersUsage(Usage);
538 }
539
540 const llvm::ArrayRef<uint64_t> getProcResourceMasks() const {
541 return Resources->getProcResMasks();
542 }
543
544#ifndef NDEBUG
545 void dump() const;
546#endif
547};
548
549} // Namespace mca
550
551#endif