The Sparta Modeling Framework
Loading...
Searching...
No Matches
Execute.cpp
1// <Execute.cpp> -*- C++ -*-
2
4
5#include "Execute.hpp"
6
7namespace core_example
8{
9 const char Execute::name[] = "execute";
11 const ExecuteParameterSet * p) :
12 sparta::Unit(node),
13 ignore_inst_execute_time_(p->ignore_inst_execute_time),
14 execute_time_(p->execute_time),
15 scheduler_size_(p->scheduler_size),
16 in_order_issue_(p->in_order_issue),
17 collected_inst_(node, node->getName())
18 {
19 in_execute_inst_.
20 registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA(Execute, getInstsFromDispatch_,
22
23 in_reorder_flush_.
24 registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA(Execute, flushInst_,
25 FlushManager::FlushingCriteria));
26 // Startup handler for sending initiatl credits
27 sparta::StartupEvent(node, CREATE_SPARTA_HANDLER(Execute, sendInitialCredits_));
28 // Set up the precedence between issue and complete
29 // Complete should come before issue because it schedules issue with a 0 cycle delay
30 // issue should always schedule complete with a non-zero delay (which corresponds to the
31 // insturction latency)
32 complete_inst_ >> issue_inst_;
33
35 info_logger_ << "Execute construct: #" << node->getGroupIdx();
36 }
37
38 }
39
40 void Execute::sendInitialCredits_()
41 {
42 out_scheduler_credits_.send(scheduler_size_);
43 }
44
46 // Callbacks
47 void Execute::getInstsFromDispatch_(const ExampleInstPtr & ex_inst)
48 {
49 // Insert at the end if we are doing in order issue or if the scheduler is empty
50 if (in_order_issue_ == true || ready_queue_.size() == 0) {
51 ready_queue_.emplace_back(ex_inst);
52 }
53 else {
54 // Stick the instructions in a random position in the ready queue
55 uint64_t issue_pos = std::rand() % ready_queue_.size();
56 if (issue_pos == ready_queue_.size()-1) {
57 ready_queue_.emplace_back(ex_inst);
58 }
59 else {
60 uint64_t pos = 0;
61 auto iter = ready_queue_.begin();
62 while (iter != ready_queue_.end()) {
63 if (pos == issue_pos) {
64 ready_queue_.insert(iter, ex_inst);
65 break;
66 }
67 ++iter;
68 ++pos;
69 }
70 }
71 }
72 // Schedule issue if the alu is not busy
73 if (unit_busy_ == false) {
74 issue_inst_.schedule(sparta::Clock::Cycle(0));
75 }
76 }
77
78 void Execute::issueInst_() {
79 // Issue a random instruction from the ready queue
80 sparta_assert_context(unit_busy_ == false && ready_queue_.size() > 0,
81 "Somehow we're issuing on a busy unit or empty ready_queue");
82 // Issue the first instruction
83 ExampleInstPtr & ex_inst_ptr = ready_queue_.front();
84 auto & ex_inst = *ex_inst_ptr;
85 ex_inst.setStatus(ExampleInst::Status::SCHEDULED);
86 const uint32_t exe_time =
87 ignore_inst_execute_time_ ? execute_time_ : ex_inst.getExecuteTime();
88 collected_inst_.collectWithDuration(ex_inst, exe_time);
90 info_logger_ << "Executing: " << ex_inst << " for "
91 << exe_time + getClock()->currentCycle();
92 }
93 sparta_assert(exe_time != 0);
94
95 ++total_insts_issued_;
96 // Mark the instruction complete later...
97 complete_inst_.preparePayload(ex_inst_ptr)->schedule(exe_time);
98 // Mark the alu as busy
99 unit_busy_ = true;
100 // Pop the insturction from the scheduler and send a credit back to dispatch
101 ready_queue_.pop_front();
102 out_scheduler_credits_.send(1, 0);
103 }
104
105 // Called by the scheduler, scheduled by complete_inst_.
106 void Execute::completeInst_(const ExampleInstPtr & ex_inst) {
108 info_logger_ << "Completing inst: " << ex_inst;
109 }
110
111 ++total_insts_executed_;
112 ex_inst->setStatus(ExampleInst::Status::COMPLETED);
113 // We're not busy anymore
114 unit_busy_ = false;
115 // Schedule issue if we have instructions to issue
116 if (ready_queue_.size() > 0) {
117 issue_inst_.schedule(sparta::Clock::Cycle(0));
118 }
119 }
120
121 void Execute::flushInst_(const FlushManager::FlushingCriteria & criteria)
122 {
124 info_logger_ << "Got flush for criteria: " << criteria;
125 }
126
127 // Flush instructions in the ready queue
128 ReadyQueue::iterator it = ready_queue_.begin();
129 uint32_t credits_to_send = 0;
130 while(it != ready_queue_.end()) {
131 if((*it)->getUniqueID() >= uint64_t(criteria)) {
132 ready_queue_.erase(it++);
133 ++credits_to_send;
134 }
135 else {
136 ++it;
137 }
138 }
139 if(credits_to_send) {
140 out_scheduler_credits_.send(credits_to_send, 0);
141 }
142
143 // Cancel outstanding instructions awaiting completion and
144 // instructions on their way to issue
145 auto cancel_critera = [criteria](const ExampleInstPtr & inst) -> bool {
146 if(inst->getUniqueID() >= uint64_t(criteria)) {
147 return true;
148 }
149 return false;
150 };
151 complete_inst_.cancelIf(cancel_critera);
152 issue_inst_.cancel();
153
154 if(complete_inst_.getNumOutstandingEvents() == 0) {
155 unit_busy_ = false;
156 collected_inst_.closeRecord();
157 }
158 }
159
160}
#define sparta_assert_context(e, insertions)
Check condition and throw a sparta exception if condition evaluates to false or 0....
Definition Resource.hpp:402
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
#define CREATE_SPARTA_HANDLER_WITH_DATA(clname, meth, dataT)
#define CREATE_SPARTA_HANDLER(clname, meth)
Parameters for Execute model.
Definition Execute.hpp:41
Execute(sparta::TreeNode *node, const ExecuteParameterSet *p)
Constructor for Execute.
Definition Execute.cpp:10
static const char name[]
Name of this resource. Required by sparta::UnitFactory.
Definition Execute.hpp:64
Cycle currentCycle() const
Get the current cycle (uses current tick from the Scheduler)
Definition Clock.hpp:176
void send(const DataT &dat, sparta::Clock::Cycle rel_time=0)
Send data to bound receivers.
Definition DataPort.hpp:145
const Clock * getClock() const
void cancel()
Cancel all the times that this Scheduleable was placed on the Scheduler.
StartupEvent is a simple class for scheduling a starting event on the Scheduler. It does not support ...
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
group_idx_type getGroupIdx() const
Gets the group index of this node.
void schedule()
Schedule this event with its pre-set delay using the pre-set Clock.
log::MessageSource info_logger_
Default info logger.
Definition Unit.hpp:161
Macros for handling exponential backoff.