1 /* Copyright (c) 2015 Regents of the University of California
3 * Author: Brian Demsky <bdemsky@uci.edu>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
11 #include "mcexecution.h"
12 #include "mcschedule.h"
17 Planner::Planner(MCExecution * execution) :
19 changeset(new ChangeHashSet()),
20 completedset(new ChangeHashSet()),
21 cgen(new ConstGen(execution)),
32 bool Planner::is_finished() {
36 void Planner::plan() {
38 e->get_scheduler()->reset();
40 if (!cgen->canReuseEncoding()) {
48 void Planner::addChange(MCChange *change) {
49 if (!changeset->add(change)) {
54 void Planner::processChanges() {
55 ChangeIterator *cit=changeset->iterator();
56 for(;cit->hasNext();) {
57 MCChange *change=cit->next();
59 if (completedset->contains(change)) {
63 if (change->isFunction()) {
64 processFunction(change);
65 } else if (change->isEquals()) {
66 processEquals(change);
67 } else if (change->isLoad()) {
69 } else if (change->isRMW()) {
71 } else if (change->isStore()) {
74 completedset->add(change);
78 for(cit=completedset->iterator();cit->hasNext();) {
79 MCChange *change=cit->next();
86 void Planner::processFunction(MCChange * change) {
87 processNewReturnValue(change);
90 void Planner::processEquals(MCChange * change) {
91 processNewReturnValue(change);
94 void Planner::processRMW(MCChange * change) {
95 switch(change->getIndex()) {
97 processNewStoreAddress(change);
100 processNewStoreValue(change);
103 //Return value of the RMW action
104 processNewReturnValue(change);
111 void Planner::processLoad(MCChange * change) {
112 switch(change->getIndex()) {
114 processNewLoadAddress(change);
117 processNewReturnValue(change);
124 void Planner::processStore(MCChange * change) {
125 switch(change->getIndex()) {
127 processNewStoreAddress(change);
130 processNewStoreValue(change);
137 /** This function propagate news values that a function or add
138 operation may generate.
141 void Planner::processNewReturnValue(MCChange *change) {
142 EPRecord *record=change->getRecord();
143 EPRecordSet *dependences=e->getDependences(record);
144 if (dependences==NULL)
146 EPRecordIterator *rit=dependences->iterator();
147 while(rit->hasNext()) {
148 struct RecordIntPair *deprecord=rit->next();
149 registerValue(deprecord->record, change->getValue(), deprecord->index);
154 /** This function registers a new address for a load operation. We
155 iterate over all stores to that new address and grab their values
159 void Planner::processNewLoadAddress(MCChange *change) {
160 EPRecord *load=change->getRecord();
161 void *addr=(void *)change->getValue();
162 RecordSet *storeset=e->getStoreTable(addr);
163 if (storeset == NULL)
165 RecordIterator *rit=storeset->iterator();
166 while(rit->hasNext()) {
167 EPRecord *store=rit->next();
168 if (e->compatibleStoreLoad(store, load)) {
169 IntIterator * it=store->getStoreSet()->iterator();
170 while(it->hasNext()) {
171 uint64_t st_val=it->next();
172 //should propagate value further
173 //we should worry about redudant values...
174 registerValue(load, st_val, VC_RFINDEX);
182 /** This function processes a new address for a store. We push our
183 values to all loads from that address. */
185 void Planner::processNewStoreAddress(MCChange *change) {
186 EPRecord *store=change->getRecord();
187 void *addr=(void *)change->getValue();
188 RecordSet *rset=e->getLoadTable(addr);
191 RecordIterator *rit=rset->iterator();
192 IntHashSet *valset=store->getStoreSet();
193 while(rit->hasNext()) {
194 EPRecord *load=rit->next();
195 if (e->compatibleStoreLoad(store, load)) {
196 //iterate through all values
197 IntIterator *iit=valset->iterator();
198 while(iit->hasNext()) {
199 uint64_t val=iit->next();
200 registerValue(load, val, VC_RFINDEX);
209 /** This function pushes a new store value to all loads that share an
212 void Planner::processNewStoreValue(MCChange *change) {
213 EPRecord *store=change->getRecord();
214 uint64_t val=change->getValue();
215 IntHashSet *addrset=store->getSet(VC_ADDRINDEX);
216 IntIterator *ait=addrset->iterator();
217 while(ait->hasNext()) {
218 void *addr=(void*)ait->next();
219 RecordSet *rset=e->getLoadTable(addr);
222 RecordIterator *rit=rset->iterator();
223 while(rit->hasNext()) {
224 EPRecord *load=rit->next();
225 if (e->compatibleStoreLoad(store, load)) {
226 registerValue(load, val, VC_RFINDEX);
235 void Planner::registerValue(EPRecord *record, uint64_t val, unsigned int index) {
236 switch(record->getType()) {
238 registerLoadValue(record, val, index);
241 registerRMWValue(record, val, index);
244 registerStoreValue(record, val, index);
247 registerFunctionValue(record, val, index);
250 registerEqualsValue(record, val, index);
253 registerBranchValue(record, val, index);
258 model_print("Unrecognized event %u\n",record->getType());
262 void Planner::registerBranchValue(EPRecord *record, uint64_t val, unsigned int index) {
263 record->getSet(index)->add(val);
266 void Planner::registerLoadValue(EPRecord *record, uint64_t val, unsigned int index) {
267 if (index==VC_ADDRINDEX)
268 val+=record->getOffset();
270 bool is_new=record->getSet(index)->add(val);
274 e->addLoadTable((void *)val, record);
275 MCChange *change=new MCChange(record, val, VC_ADDRINDEX);
280 //New value we can read...Push it...
281 MCChange *change=new MCChange(record, val, VC_VALOUTINDEX);
292 void Planner::registerRMWValue(EPRecord *record, uint64_t val, unsigned int index) {
293 if (index==VC_ADDRINDEX)
294 val+=record->getOffset();
296 bool is_new=record->getSet(index)->add(val);
300 doRMWNewAddrChange(record, val);
303 doRMWRFChange(record, val);
306 doRMWBaseChange(record, val);
308 case VC_OLDVALCASINDEX:
309 ASSERT(record->getOp()==CAS);
310 doRMWOldValChange(record);
318 void Planner::doRMWNewAddrChange(EPRecord *record, uint64_t val) {
319 e->addLoadTable((void *)val, record);
320 e->addStoreTable((void *)val, record);
322 //propagate our value to new loads
323 MCChange * change=new MCChange(record, val, VC_ADDRINDEX);
326 //look at new stores and update our read from set
327 RecordSet *storeset=e->getStoreTable((void *)val);
328 RecordIterator *rit=storeset->iterator();
329 while(rit->hasNext()) {
330 EPRecord *store=rit->next();
332 if (e->compatibleStoreLoad(store, record)) {
333 IntIterator * it=store->getStoreSet()->iterator();
334 while(it->hasNext()) {
335 uint64_t st_val=it->next();
336 //should propagate value further
337 //we should worry about redudant values...
338 registerRMWValue(record, st_val, VC_RFINDEX);
346 void Planner::doRMWRFChange(EPRecord *record, uint64_t readval) {
347 //Register the new value we might return
348 MCChange *change=new MCChange(record, readval, VC_VALOUTINDEX);
351 if (record->getOp()==CAS) {
352 //Register the new value we might store if we are a CAS
353 bool is_new=record->getStoreSet()->add(readval);
355 MCChange *change=new MCChange(record, readval, VC_RMWOUTINDEX);
361 void Planner::doRMWBaseChange(EPRecord *record, uint64_t baseval) {
362 if (record->getOp()==CAS) {
363 //Just push the value as though it is our output
364 bool is_new=record->getStoreSet()->add(baseval);
366 MCChange *change=new MCChange(record, baseval, VC_RMWOUTINDEX);
369 } else if (record->getOp()==ADD) {
370 //Tricky here because we could create an infinite propagation...
372 //TODO: HANDLE THIS CASE
373 } else if (record->getOp()==EXC) {
374 //no need to propagate output
380 void Planner::doRMWOldValChange(EPRecord *record) {
381 //Do nothing, no need to propagate old value...
384 void Planner::registerStoreValue(EPRecord *record, uint64_t val, unsigned int index) {
385 if (index==VC_ADDRINDEX)
386 val+=record->getOffset();
388 bool is_new=record->getSet(index)->add(val);
390 if (index==VC_ADDRINDEX) {
392 e->addStoreTable((void *)val, record);
393 MCChange * change=new MCChange(record, val, index);
395 } else if (index==VC_BASEINDEX) {
396 MCChange * change=new MCChange(record, val, index);
398 } else model_print("ERROR in RSV\n");
401 void Planner::registerEqualsValue(EPRecord *record, uint64_t val, unsigned int index) {
402 record->getSet(index)->add(val);
405 void Planner::registerFunctionValue(EPRecord *record, uint64_t val, unsigned int index) {
406 bool newval=record->getSet(index)->add(val);
408 if (record->getPhi()) {
409 MCChange * change=new MCChange(record, val, VC_FUNCOUTINDEX);
412 } else if (newval && record->isSharedGoals()) {
413 CGoalIterator *cit=record->completedGoalSet()->iterator();
414 while(cit->hasNext()) {
415 CGoal *goal=cit->next();
416 if (goal->getValue(index)==val) {
417 e->evalGoal(record, goal);