diff --git a/src/cpu/testers/gpu_ruby_test/tester_thread.cc b/src/cpu/testers/gpu_ruby_test/tester_thread.cc index 2dfd54a2e4..760f8c2d87 100644 --- a/src/cpu/testers/gpu_ruby_test/tester_thread.cc +++ b/src/cpu/testers/gpu_ruby_test/tester_thread.cc @@ -152,6 +152,37 @@ TesterThread::issueNewEpisode() episodeHistory.push_back(curEpisode); } +int +TesterThread::getTokensNeeded() +{ + if (!tokenPort) { + return 0; + } + + int tokens_needed = 0; + curAction = curEpisode->peekCurAction(); + + switch(curAction->getType()) { + case Episode::Action::Type::ATOMIC: + tokens_needed = numLanes; + break; + case Episode::Action::Type::LOAD: + case Episode::Action::Type::STORE: + for (int lane = 0; lane < numLanes; ++lane) { + Location loc = curAction->getLocation(lane); + + if (loc != AddressManager::INVALID_LOCATION && loc >= 0) { + tokens_needed++; + } + } + break; + default: + tokens_needed = 0; + } + + return tokens_needed; +} + bool TesterThread::isNextActionReady() { @@ -162,10 +193,13 @@ TesterThread::isNextActionReady() // Only GPU wavefront threads have a token port. For all other types // of threads evaluate to true. - bool haveTokens = tokenPort ? tokenPort->haveTokens(numLanes) : true; + bool haveTokens = true; switch(curAction->getType()) { case Episode::Action::Type::ATOMIC: + haveTokens = tokenPort ? + tokenPort->haveTokens(getTokensNeeded()) : true; + // an atomic action must wait for all previous requests // to complete if (pendingLdStCount == 0 && @@ -206,7 +240,7 @@ TesterThread::isNextActionReady() assert(pendingAtomicCount == 0); // can't issue if there is a pending fence - if (pendingFenceCount > 0 || !haveTokens) { + if (pendingFenceCount > 0) { return false; } @@ -215,7 +249,7 @@ TesterThread::isNextActionReady() for (int lane = 0; lane < numLanes; ++lane) { Location loc = curAction->getLocation(lane); - if (loc != AddressManager::INVALID_LOCATION) { + if (loc != AddressManager::INVALID_LOCATION && loc >= 0) { Addr addr = addrManager->getAddress(loc); if (outstandingLoads.find(addr) != @@ -237,6 +271,12 @@ TesterThread::isNextActionReady() } } + haveTokens = tokenPort ? + tokenPort->haveTokens(getTokensNeeded()) : true; + if (!haveTokens) { + return false; + } + return true; default: panic("The tester got an invalid action\n"); @@ -250,7 +290,7 @@ TesterThread::issueNextAction() switch(curAction->getType()) { case Episode::Action::Type::ATOMIC: if (tokenPort) { - tokenPort->acquireTokens(numLanes); + tokenPort->acquireTokens(getTokensNeeded()); } issueAtomicOps(); break; @@ -262,13 +302,13 @@ TesterThread::issueNextAction() break; case Episode::Action::Type::LOAD: if (tokenPort) { - tokenPort->acquireTokens(numLanes); + tokenPort->acquireTokens(getTokensNeeded()); } issueLoadOps(); break; case Episode::Action::Type::STORE: if (tokenPort) { - tokenPort->acquireTokens(numLanes); + tokenPort->acquireTokens(getTokensNeeded()); } issueStoreOps(); break; diff --git a/src/cpu/testers/gpu_ruby_test/tester_thread.hh b/src/cpu/testers/gpu_ruby_test/tester_thread.hh index 5612df969e..9877d63c24 100644 --- a/src/cpu/testers/gpu_ruby_test/tester_thread.hh +++ b/src/cpu/testers/gpu_ruby_test/tester_thread.hh @@ -178,6 +178,7 @@ class TesterThread : public ClockedObject // constraints and is ready to issue bool isNextActionReady(); void issueNextAction(); + int getTokensNeeded(); // issue Ops to Ruby memory // must be implemented by a child class