ruby: Remove transactional access types (e.g. LD_XACT) from CacheRequestType
1. Modified enumeration 2. Also modified profiler 3. Remove transactions from Tester 4. Edited XACT_MEM out of Synthetic Driver
This commit is contained in:
parent
9f34659c52
commit
b271090923
9 changed files with 0 additions and 1710 deletions
|
@ -131,12 +131,6 @@ enumeration(CacheRequestType, desc="...", default="CacheRequestType_NULL") {
|
|||
IO, desc="I/O";
|
||||
REPLACEMENT, desc="Replacement";
|
||||
COMMIT, desc="Commit version";
|
||||
LD_XACT, desc="Transactional Load";
|
||||
LDX_XACT, desc="Transactional Load-Intend-To-Modify";
|
||||
ST_XACT, desc="Transactional Store";
|
||||
BEGIN_XACT, desc="Begin Transaction";
|
||||
COMMIT_XACT, desc="Commit Transaction";
|
||||
ABORT_XACT, desc="Abort Transaction";
|
||||
NULL, desc="Invalid request type";
|
||||
}
|
||||
|
||||
|
@ -162,12 +156,6 @@ enumeration(GenericRequestType, desc="...", default="GenericRequestType_NULL") {
|
|||
WB_ACK, desc="WriteBack ack";
|
||||
EXE_ACK, desc="Execlusive ack";
|
||||
COMMIT, desc="Commit version";
|
||||
LD_XACT, desc="Transactional Load";
|
||||
LDX_XACT, desc="Transactional Load-Intend-Modify";
|
||||
ST_XACT, desc="Transactional Store";
|
||||
BEGIN_XACT, desc="Begin Transaction";
|
||||
COMMIT_XACT, desc="Commit Transaction";
|
||||
ABORT_XACT, desc="Abort Transaction";
|
||||
NULL, desc="null request type";
|
||||
}
|
||||
|
||||
|
|
|
@ -1006,15 +1006,6 @@ GenericRequestType Profiler::CacheRequestType_to_GenericRequestType(const CacheR
|
|||
case CacheRequestType_IFETCH:
|
||||
return GenericRequestType_IFETCH;
|
||||
break;
|
||||
case CacheRequestType_LD_XACT:
|
||||
return GenericRequestType_LD_XACT;
|
||||
break;
|
||||
case CacheRequestType_LDX_XACT:
|
||||
return GenericRequestType_LDX_XACT;
|
||||
break;
|
||||
case CacheRequestType_ST_XACT:
|
||||
return GenericRequestType_ST_XACT;
|
||||
break;
|
||||
case CacheRequestType_NULL:
|
||||
return GenericRequestType_NULL;
|
||||
break;
|
||||
|
|
|
@ -1,263 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mem/ruby/profiler/XactProfiler.hh"
|
||||
#include "mem/protocol/CacheMsg.hh"
|
||||
#include "mem/gems_common/Map.hh"
|
||||
#include "mem/ruby/common/Debug.hh"
|
||||
#include "mem/protocol/MachineType.hh"
|
||||
#include "TransactionInterfaceManager.hh"
|
||||
#include "mem/ruby/common/Driver.hh"
|
||||
#include "interface.hh"
|
||||
|
||||
extern std::ostream * debug_cout_ptr;
|
||||
|
||||
XactProfiler::XactProfiler()
|
||||
{
|
||||
int num_processors = RubyConfig::numberOfProcessors() * RubyConfig::numberofSMTThreads();
|
||||
|
||||
m_xactTransCycles = new long long int[num_processors];
|
||||
m_xactStallTransCycles = new long long int[num_processors];
|
||||
m_xactStallNonTransCycles = new long long int[num_processors];
|
||||
m_xactAbortingCycles = new long long int[num_processors];
|
||||
m_xactCommitingCycles = new long long int[num_processors];
|
||||
m_xactBackoffCycles = new long long int[num_processors];
|
||||
m_BarrierCycles = new long long int[num_processors];
|
||||
|
||||
m_xactGoodTransCycles = new long long int[num_processors];
|
||||
m_xactNonTransCycles = new long long int[num_processors];
|
||||
|
||||
m_xactTimedCycles = new long long int[num_processors];
|
||||
m_xactBeginTimer = new long long int[num_processors];
|
||||
|
||||
clearStats();
|
||||
}
|
||||
|
||||
XactProfiler::~XactProfiler()
|
||||
{
|
||||
delete [] m_xactTransCycles;
|
||||
delete [] m_xactStallTransCycles;
|
||||
delete [] m_xactStallNonTransCycles;
|
||||
delete [] m_xactAbortingCycles;
|
||||
delete [] m_xactBackoffCycles;
|
||||
|
||||
delete [] m_xactGoodTransCycles;
|
||||
delete [] m_xactNonTransCycles;
|
||||
|
||||
delete [] m_xactTimedCycles;
|
||||
delete [] m_xactBeginTimer;
|
||||
}
|
||||
|
||||
void XactProfiler::printConfig(ostream& out) const
|
||||
{
|
||||
out << endl;
|
||||
out << "XactProfiler Configuration" << endl;
|
||||
out << "----------------------" << endl;
|
||||
}
|
||||
|
||||
void XactProfiler::print(ostream& out) const
|
||||
{
|
||||
out << "[XactProfiler]";
|
||||
}
|
||||
|
||||
void XactProfiler::printStats(ostream& out, bool short_stats)
|
||||
{
|
||||
int num_processors = RubyConfig::numberOfProcessors() * RubyConfig::numberofSMTThreads();
|
||||
out << endl;
|
||||
|
||||
out << "XactProfiler Stats" << endl;
|
||||
out << "--------------" << endl;
|
||||
|
||||
if (max_hashFunction >= 0){
|
||||
out << "Hash values distribution" << endl;
|
||||
out << "------------------------" << endl;
|
||||
for(int i = 0; i <= max_hashFunction; i++){
|
||||
out << "Hash function " << i << ": " << m_hashProfile[i] << endl;
|
||||
}
|
||||
out << endl;
|
||||
}
|
||||
|
||||
out << "xact_cycle_breakdown" << endl;
|
||||
out << "--------------------" << endl;
|
||||
long long int total_trans_cycles = 0;
|
||||
long long int total_aborting_trans_cycles = 0;
|
||||
long long int total_commiting_trans_cycles = 0;
|
||||
long long int total_backoff_trans_cycles = 0;
|
||||
long long int total_stall_trans_cycles = 0;
|
||||
long long int total_stall_nontrans_cycles = 0;
|
||||
long long int total_barrier_cycles = 0;
|
||||
|
||||
long long int total_good_trans_cycles = 0;
|
||||
long long int total_nontrans_cycles = 0;
|
||||
|
||||
long long int total_timed_cycles = 0;
|
||||
|
||||
for(int i=0; i < num_processors; ++i){
|
||||
if (!short_stats){
|
||||
out << "xact_trans_cycles_processor_" << i << ": " << m_xactTransCycles[i] << endl;
|
||||
out << "xact_aborting_cycles_processor_" << i << ": " << m_xactAbortingCycles[i] << endl;
|
||||
out << "xact_barrier_cycles_processor_" << i << ": " << m_BarrierCycles[i] << endl;
|
||||
out << "xact_backoff_cycles_processor_" << i << ": " << m_xactBackoffCycles[i] << endl;
|
||||
out << "xact_stall_trans_cycles_processor_" << i << ": " << m_xactStallTransCycles[i] << endl;
|
||||
out << "xact_nontrans_cycles_processor_" << i << ": " << m_xactNonTransCycles[i] << endl;
|
||||
out << "xact_stall_nontrans_cycles_processor_" << i << ": " << m_xactStallNonTransCycles[i] << endl;
|
||||
out << "timed_cycles_processor_" << i << ": " << m_xactTimedCycles[i] << endl;
|
||||
}
|
||||
|
||||
total_trans_cycles += m_xactTransCycles[i];
|
||||
total_stall_trans_cycles += m_xactStallTransCycles[i];
|
||||
total_aborting_trans_cycles += m_xactAbortingCycles[i];
|
||||
total_commiting_trans_cycles += m_xactCommitingCycles[i];
|
||||
total_backoff_trans_cycles += m_xactBackoffCycles[i];
|
||||
total_barrier_cycles += m_BarrierCycles[i];
|
||||
total_nontrans_cycles += m_xactNonTransCycles[i];
|
||||
total_good_trans_cycles += m_xactGoodTransCycles[i];
|
||||
total_stall_nontrans_cycles += m_xactStallNonTransCycles[i];
|
||||
total_timed_cycles += m_xactTimedCycles[i];
|
||||
|
||||
}
|
||||
out << endl;
|
||||
out << " XACT CYCLE BREAKDOWN " << endl;
|
||||
out << " XACT_BREAKDOWN_NON_TRANS_CYCLES: " << total_nontrans_cycles << endl;
|
||||
out << " XACT_BREAKDOWN_TRANS_CYCLES: " << total_trans_cycles << endl;
|
||||
out << " XACT_BREAKDOWN_GOOD_TRANS_CYCLES: " << total_good_trans_cycles << endl;
|
||||
out << " XACT_BREAKDOWN_ABORTING_CYCLES: " << total_aborting_trans_cycles << endl;
|
||||
out << " XACT_BREAKDOWN_COMMITING_CYCLES: " << total_commiting_trans_cycles << endl;
|
||||
out << " XACT_BREAKDOWN_BACKOFF_CYCLES: " << total_backoff_trans_cycles << endl;
|
||||
out << " XACT_BREAKDOWN_BARRIER_CYCLES: " << total_barrier_cycles << endl;
|
||||
out << " XACT_BREAKDOWN_STALL_CYCLES: " << total_stall_trans_cycles << endl;
|
||||
out << endl;
|
||||
out << " XACT_TIMED_CYCLES: " << total_timed_cycles << endl;
|
||||
out << endl;
|
||||
|
||||
}
|
||||
|
||||
void XactProfiler::clearStats()
|
||||
{
|
||||
int num_processors = RubyConfig::numberOfProcessors() * RubyConfig::numberofSMTThreads();
|
||||
for(int i=0; i < num_processors; ++i){
|
||||
m_xactTransCycles[i] = 0;
|
||||
m_xactStallTransCycles[i] = 0;
|
||||
m_xactGoodTransCycles[i] = 0;
|
||||
m_xactBackoffCycles[i] = 0;
|
||||
m_xactAbortingCycles[i] = 0;
|
||||
m_xactCommitingCycles[i] = 0;
|
||||
m_xactNonTransCycles[i] = 0;
|
||||
m_xactStallNonTransCycles[i] = 0;
|
||||
m_BarrierCycles[i] = 0;
|
||||
m_xactTimedCycles[i] = 0;
|
||||
}
|
||||
|
||||
max_hashFunction = -1;
|
||||
m_hashProfile.setSize(16);
|
||||
for (int i = 0; i < 15; i++) {
|
||||
m_hashProfile[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
void XactProfiler::profileTransCycles(int proc, int cycles){
|
||||
m_xactTransCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
long long int XactProfiler::getTransCycles(int proc){
|
||||
return m_xactTransCycles[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileStallTransCycles(int proc, int cycles){
|
||||
m_xactStallTransCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
long long int XactProfiler::getStallTransCycles(int proc){
|
||||
return m_xactStallTransCycles[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileGoodTransCycles(int proc, int cycles){
|
||||
m_xactGoodTransCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
long long int XactProfiler::getGoodTransCycles(int proc){
|
||||
return m_xactGoodTransCycles[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileAbortingTransCycles(int proc, int cycles){
|
||||
m_xactAbortingCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
long long int XactProfiler::getAbortingTransCycles(int proc){
|
||||
return m_xactAbortingCycles[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileCommitingTransCycles(int proc, int cycles){
|
||||
m_xactCommitingCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
long long int XactProfiler::getCommitingTransCycles(int proc){
|
||||
return m_xactCommitingCycles[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileBackoffTransCycles(int proc, int cycles){
|
||||
m_xactBackoffCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
long long int XactProfiler::getBackoffTransCycles(int proc){
|
||||
return m_xactBackoffCycles[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileStallNonTransCycles(int proc, int cycles){
|
||||
m_xactStallNonTransCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
void XactProfiler::profileNonTransCycles(int proc, int cycles){
|
||||
m_xactNonTransCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
long long int XactProfiler::getNonTransCycles(int proc){
|
||||
return m_xactNonTransCycles[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileBarrierCycles(int proc, int cycles){
|
||||
m_BarrierCycles[proc] += cycles;
|
||||
}
|
||||
|
||||
long long int XactProfiler::getBarrierCycles(int proc){
|
||||
return m_BarrierCycles[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileBeginTimer(int proc){
|
||||
m_xactBeginTimer[proc] = (long long int) g_eventQueue_ptr->getTime();
|
||||
}
|
||||
|
||||
void XactProfiler::profileEndTimer(int proc){
|
||||
m_xactTimedCycles[proc] += (long long int) g_eventQueue_ptr->getTime() - m_xactBeginTimer[proc];
|
||||
}
|
||||
|
||||
void XactProfiler::profileHashValue(int hashFunction, int hashValue){
|
||||
if (hashFunction > max_hashFunction) max_hashFunction = hashFunction;
|
||||
|
||||
m_hashProfile[hashFunction].add(hashValue);
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef XACTPROFILER_H
|
||||
#define XACTPROFILER_H
|
||||
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/protocol/GenericMachineType.hh"
|
||||
#include "mem/ruby/config/RubyConfig.hh"
|
||||
#include "mem/ruby/common/Histogram.hh"
|
||||
#include "mem/ruby/common/Consumer.hh"
|
||||
#include "mem/protocol/AccessModeType.hh"
|
||||
#include "mem/protocol/AccessType.hh"
|
||||
#include "mem/ruby/system/NodeID.hh"
|
||||
#include "mem/ruby/system/MachineID.hh"
|
||||
#include "mem/protocol/PrefetchBit.hh"
|
||||
#include "mem/ruby/common/Address.hh"
|
||||
#include "mem/ruby/common/Set.hh"
|
||||
#include "mem/protocol/CacheRequestType.hh"
|
||||
#include "mem/protocol/GenericRequestType.hh"
|
||||
|
||||
template <class KEY_TYPE, class VALUE_TYPE> class Map;
|
||||
|
||||
class XactProfiler {
|
||||
public:
|
||||
// Constructors
|
||||
XactProfiler();
|
||||
|
||||
// Destructor
|
||||
~XactProfiler();
|
||||
|
||||
void printStats(ostream& out, bool short_stats=false);
|
||||
void printShortStats(ostream& out) { printStats(out, true); }
|
||||
void clearStats();
|
||||
void printConfig(ostream& out) const;
|
||||
|
||||
void print(ostream& out) const;
|
||||
|
||||
void profileTransCycles(int proc, int cycles);
|
||||
void profileNonTransCycles(int proc, int cycles);
|
||||
void profileStallTransCycles(int proc, int cycles);
|
||||
void profileStallNonTransCycles(int proc, int cycles);
|
||||
void profileAbortingTransCycles(int proc, int cycles);
|
||||
void profileCommitingTransCycles(int proc, int cycles);
|
||||
void profileBarrierCycles(int proc, int cycles);
|
||||
void profileBackoffTransCycles(int proc, int cycles);
|
||||
void profileGoodTransCycles(int proc, int cycles);
|
||||
|
||||
void profileBeginTimer(int proc);
|
||||
void profileEndTimer(int proc);
|
||||
|
||||
long long int getTransCycles(int proc_no);
|
||||
long long int getGoodTransCycles(int proc_no);
|
||||
long long int getStallTransCycles(int proc_no);
|
||||
long long int getAbortingTransCycles(int proc_no);
|
||||
long long int getCommitingTransCycles(int proc_no);
|
||||
long long int getBackoffTransCycles(int proc_no);
|
||||
long long int getNonTransCycles(int proc_no);
|
||||
long long int getBarrierCycles(int proc_no);
|
||||
|
||||
void profileHashValue(int hashFunction, int hashValue);
|
||||
|
||||
private:
|
||||
|
||||
long long int * m_xactTransCycles;
|
||||
long long int * m_xactStallTransCycles;
|
||||
long long int * m_xactStallNonTransCycles;
|
||||
long long int * m_xactAbortingCycles;
|
||||
long long int * m_xactCommitingCycles;
|
||||
long long int * m_xactBackoffCycles;
|
||||
long long int * m_BarrierCycles;
|
||||
|
||||
long long int * m_xactGoodTransCycles;
|
||||
long long int * m_xactNonTransCycles;
|
||||
|
||||
long long int * m_xactTimedCycles;
|
||||
long long int * m_xactBeginTimer;
|
||||
|
||||
int max_hashFunction;
|
||||
Vector<Histogram> m_hashProfile;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
ostream& operator<<(ostream& out, const XactProfiler& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
ostream& operator<<(ostream& out, const XactProfiler& obj)
|
||||
{
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif //XACTPROFILER_H
|
||||
|
||||
|
|
@ -36,11 +36,7 @@
|
|||
#include "mem/ruby/system/System.hh"
|
||||
#include "mem/ruby/tester/SyntheticDriver.hh"
|
||||
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
|
||||
//#ifndef XACT_MEM
|
||||
#include "mem/ruby/tester/RequestGenerator.hh"
|
||||
//#endif
|
||||
//#include "mem/ruby/tester/XactAbortRequestGenerator.hh"
|
||||
//#include "mem/ruby/tester/XactRequestGenerator.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
#include "mem/protocol/Chip.hh"
|
||||
|
||||
|
@ -150,7 +146,6 @@ void SyntheticDriver::notifyReceiveNackFinal(int proc, const Address & addr){
|
|||
//reqGen->notifyReceiveNackFinal(addr);
|
||||
}
|
||||
else{
|
||||
cout << "notifyReceiveNackFinal NOT USING TM" << endl;
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,403 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999 by Mark Hill and David Wood for the Wisconsin
|
||||
* Multifacet Project. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* ##HEADER##
|
||||
*
|
||||
* This software is furnished under a license and may be used and
|
||||
* copied only in accordance with the terms of such license and the
|
||||
* inclusion of the above copyright notice. This software or any
|
||||
* other copies thereof or any derivative works may not be provided or
|
||||
* otherwise made available to any other persons. Title to and
|
||||
* ownership of the software is retained by Mark Hill and David Wood.
|
||||
* Any use of this software must include the above copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS". THE LICENSOR MAKES NO
|
||||
* WARRANTIES ABOUT ITS CORRECTNESS OR PERFORMANCE.
|
||||
* */
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef XACT_MEM
|
||||
|
||||
#include "mem/ruby/tester/XactAbortRequestGenerator.hh"
|
||||
#include "mem/protocol/LockStatus.hh"
|
||||
#include "mem/ruby/system/Sequencer.hh"
|
||||
#include "mem/ruby/system/System.hh"
|
||||
#include "mem/ruby/config/RubyConfig.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
#include "mem/ruby/tester/SyntheticDriver.hh"
|
||||
#include "mem/protocol/Chip.hh"
|
||||
#include "mem/ruby/tester/Instruction.hh"
|
||||
#include "TransactionManager.hh"
|
||||
|
||||
//uint8 XactAbortRequestGenerator::testArray[MAX_ADDRESS];
|
||||
//uint8 XactAbortRequestGenerator::dataArray[MAX_ADDRESS];
|
||||
Vector<uint8> XactAbortRequestGenerator::testArray;
|
||||
|
||||
XactAbortRequestGenerator::XactAbortRequestGenerator(NodeID node, SyntheticDriver& driver) :
|
||||
RequestGenerator(node, driver), m_driver(driver)
|
||||
{
|
||||
//DEBUG_EXPR(TESTER_COMP, MedPrio, "#### -- Creating XactAbortRequestGenerator\n");
|
||||
cout << "#### -- Creating XactAbortRequestGenerator " << node << endl;
|
||||
|
||||
testArray.setSize(g_MEMORY_SIZE_BYTES);
|
||||
assert(testArray.size() == g_MEMORY_SIZE_BYTES);
|
||||
// Create instructions
|
||||
m_instructions = new Instruction[XACT_LENGTH];
|
||||
newTransaction();
|
||||
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Ready;
|
||||
m_last_transition = 0;
|
||||
m_node = node;
|
||||
//pickAddress();
|
||||
m_counter = 0;
|
||||
m_register = 5;
|
||||
m_pc = 0;
|
||||
|
||||
//for(int i=0; i<XACT_SIZE; ++i){
|
||||
//testArray[i] = 64;
|
||||
//}
|
||||
|
||||
//testArray = new uint8[XACT_SIZE];
|
||||
//dataArray = new uint8[XACT_SIZE];
|
||||
g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::newTransaction(){
|
||||
int num_stores = 16;
|
||||
int num_loads = XACT_LENGTH - num_stores - 2;
|
||||
|
||||
for(int i=0; i<XACT_LENGTH; ++i){
|
||||
if (i == 0){
|
||||
m_instructions[i].init(Opcode_BEGIN, Address(1));
|
||||
} else if (i == XACT_LENGTH - 1){
|
||||
m_instructions[i].init(Opcode_COMMIT, Address(1));
|
||||
} else if (i < num_loads) {
|
||||
physical_address_t address = i % XACT_SIZE;
|
||||
ASSERT(address < XACT_SIZE);
|
||||
|
||||
int selectOpcode = random() % 2;
|
||||
Opcode op;
|
||||
switch(selectOpcode){
|
||||
case 0:
|
||||
op = Opcode_LD;
|
||||
break;
|
||||
case 1:
|
||||
op = Opcode_INC;
|
||||
break;
|
||||
};
|
||||
m_instructions[i].init(op, Address(address));
|
||||
} else {
|
||||
physical_address_t address = i - num_loads;
|
||||
ASSERT(address < XACT_SIZE);
|
||||
Opcode op = Opcode_ST;
|
||||
m_instructions[i].init(op, Address(address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XactAbortRequestGenerator::~XactAbortRequestGenerator()
|
||||
{
|
||||
delete m_instructions;
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::wakeup()
|
||||
{
|
||||
assert(m_xact_status == XactAbortRequestGeneratorStatus_Ready || m_xact_status == XactAbortRequestGeneratorStatus_Aborted);
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Blocked;
|
||||
DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
|
||||
DEBUG_EXPR(TESTER_COMP, MedPrio, m_xact_status);
|
||||
|
||||
m_last_transition = g_eventQueue_ptr->getTime();
|
||||
execute();
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::execute(){
|
||||
assert(m_pc >= 0 && m_pc < XACT_LENGTH);
|
||||
Instruction current = m_instructions[m_pc];
|
||||
//cout << " " << m_node << " executing pc: " << m_pc;
|
||||
switch (current.getOpcode()){
|
||||
case Opcode_BEGIN:
|
||||
//cout << " -- begin.";
|
||||
initiateBeginTransaction();
|
||||
break;
|
||||
case Opcode_LD:
|
||||
//cout << " -- load: " << current.getAddress();
|
||||
initiateLoad(current.getAddress());
|
||||
break;
|
||||
case Opcode_INC:
|
||||
//cout << " -- inc.";
|
||||
initiateInc(current.getAddress());
|
||||
break;
|
||||
case Opcode_ST:
|
||||
//cout << " -- store: " << current.getAddress();
|
||||
initiateStore(current.getAddress());
|
||||
break;
|
||||
case Opcode_COMMIT:
|
||||
//cout << " -- commit.";
|
||||
initiateCommit();
|
||||
break;
|
||||
default:
|
||||
WARN_EXPR(current.getOpcode());
|
||||
ERROR_MSG("Invalid opcode");
|
||||
};
|
||||
//cout << endl;
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::performCallback(NodeID proc, SubBlock& data)
|
||||
{
|
||||
assert(m_xact_status == XactAbortRequestGeneratorStatus_Waiting ||
|
||||
m_xact_status == XactAbortRequestGeneratorStatus_Aborted);
|
||||
assert(proc == m_node);
|
||||
|
||||
Address address = data.getAddress();
|
||||
|
||||
DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
|
||||
DEBUG_EXPR(TESTER_COMP, LowPrio, m_xact_status);
|
||||
DEBUG_EXPR(TESTER_COMP, LowPrio, address);
|
||||
DEBUG_EXPR(TESTER_COMP, LowPrio, data);
|
||||
|
||||
m_last_transition = g_eventQueue_ptr->getTime();
|
||||
|
||||
//cout << " " << m_node << " in performCallback, pc:" << m_pc
|
||||
// << ", addr:" << address << endl;
|
||||
if(m_xact_status == XactAbortRequestGeneratorStatus_Aborted){
|
||||
cout << " " << m_node << " aborted, resetting pc." << endl;
|
||||
m_pc = 0;
|
||||
m_register = 5;
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, waitTime());
|
||||
} else {
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Blocked;
|
||||
|
||||
bool found;
|
||||
uint8 value;
|
||||
switch (m_instructions[m_pc].getOpcode()){
|
||||
case Opcode_BEGIN:
|
||||
m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
m_register = 5;
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, waitTime());
|
||||
m_pc++;
|
||||
break;
|
||||
case Opcode_LD:
|
||||
m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
m_register = data.getByte(0);
|
||||
//cout << " " << m_node << " " << g_eventQueue_ptr->getTime() << " Callback--LD: " << (int) m_register << endl;
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, waitTime());
|
||||
m_pc++;
|
||||
break;
|
||||
//case Opcode_INC: // We shouldn't get a callback for this!
|
||||
//m_driver.recordSwapLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
|
||||
// break;
|
||||
case Opcode_ST:
|
||||
m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
//data.setByte(address.getOffset(), m_register);
|
||||
data.setByte(0, m_register);
|
||||
//cout << " " << m_node << " " << g_eventQueue_ptr->getTime() << " Callback--ST: " << (int) m_register << endl;
|
||||
|
||||
//dataArray[address.getAddress()] = m_register;
|
||||
found = sequencer()->setRubyMemoryValue(address, (char *) (&m_register), 1);
|
||||
assert(found);
|
||||
found = sequencer()->getRubyMemoryValue(address, (char *) (&value), 1);
|
||||
assert(found);
|
||||
assert(value == m_register);
|
||||
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, thinkTime());
|
||||
m_pc++;
|
||||
break;
|
||||
case Opcode_COMMIT:
|
||||
m_counter++;
|
||||
cout << " " << m_node << " callback--commit, counter is " << m_counter << " length is: " << g_tester_length << endl;
|
||||
// Check for correctness
|
||||
checkCorrectness();
|
||||
|
||||
m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
|
||||
if (m_counter < g_tester_length) {
|
||||
m_last_transition = g_eventQueue_ptr->getTime();
|
||||
//pickAddress(); // Necessary?
|
||||
|
||||
// Create new random transaction
|
||||
newTransaction();
|
||||
m_pc = 0;
|
||||
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, thinkTime());
|
||||
} else {
|
||||
cout << "Ending" << endl;
|
||||
m_driver.reportDone();
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Done;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_MSG("Invalid Opcode");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
int XactAbortRequestGenerator::thinkTime() const
|
||||
{
|
||||
return g_think_time;
|
||||
}
|
||||
|
||||
int XactAbortRequestGenerator::waitTime() const
|
||||
{
|
||||
return g_wait_time;
|
||||
}
|
||||
|
||||
int XactAbortRequestGenerator::holdTime() const
|
||||
{
|
||||
return g_hold_time;
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::pickAddress()
|
||||
{
|
||||
//m_address = m_driver.pickAddress(m_node);
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::initiateBeginTransaction()
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Begin Transaction");
|
||||
cout << "### -- initiating Begin " << m_node << endl;
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Waiting;
|
||||
sequencer()->makeRequest(CacheMsg(Address(physical_address_t(0)), Address(physical_address_t(0)), CacheRequestType_BEGIN_XACT, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0));
|
||||
transactionManager()->beginTransaction();
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::initiateStore(Address addr)
|
||||
{
|
||||
//DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Store");
|
||||
//cout << "### -- initiating Store " << m_node << endl;
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Waiting;
|
||||
ASSERT(transactionManager()->inTransaction(0));
|
||||
sequencer()->makeRequest(CacheMsg(addr, addr, CacheRequestType_ST_XACT, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0));
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::initiateCommit()
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Commit ");
|
||||
cout << "### -- initiating Commit " << m_node << endl;
|
||||
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Waiting;
|
||||
sequencer()->makeRequest(CacheMsg(Address(physical_address_t(0)), Address(physical_address_t(0)), CacheRequestType_COMMIT_XACT, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0));
|
||||
transactionManager()->commitTransaction();
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::initiateLoad(Address addr)
|
||||
{
|
||||
//DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Load ");
|
||||
//cout << "### -- initiating Load " << m_node << endl;
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Waiting;
|
||||
ASSERT(transactionManager()->inTransaction(0));
|
||||
sequencer()->makeRequest(CacheMsg(addr, addr, CacheRequestType_LD_XACT, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0));
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::initiateInc(Address addr)
|
||||
{
|
||||
//DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Load ");
|
||||
//cout << "### -- initiating Inc " << m_node << endl;
|
||||
m_register++;
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, holdTime());
|
||||
m_pc++;
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::checkCorrectness(){
|
||||
// Execute the transaction on the test array
|
||||
int testPC = 0;
|
||||
bool done = false;
|
||||
for(int i=0; i<XACT_LENGTH && !done; ++i){
|
||||
Opcode op = m_instructions[i].getOpcode();
|
||||
Address addr = m_instructions[i].getAddress();
|
||||
ASSERT(addr.getAddress() < testArray.size());
|
||||
uint8 reg_val;
|
||||
switch(op){
|
||||
case Opcode_BEGIN:
|
||||
reg_val = 0;
|
||||
break; // do nothing
|
||||
case Opcode_LD:
|
||||
reg_val = testArray[addr.getAddress()];
|
||||
//cout << m_node << " LD: " << addr << ", " << (int) reg_val << endl;
|
||||
break;
|
||||
case Opcode_INC:
|
||||
reg_val++;
|
||||
//cout << m_node << " INC: " << (int) reg_val << endl;
|
||||
break;
|
||||
case Opcode_ST:
|
||||
testArray[addr.getAddress()] = reg_val;
|
||||
//cout << m_node << " ST: " << addr << ", " << (int) reg_val << endl;
|
||||
break;
|
||||
case Opcode_COMMIT:
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
ERROR_MSG("Invalid Opcode.");
|
||||
};
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
uint8 ruby_value;
|
||||
bool found = false;
|
||||
for(int i=0; i<XACT_LENGTH && !done; ++i){
|
||||
Opcode op = m_instructions[i].getOpcode();
|
||||
Address addr = m_instructions[i].getAddress();
|
||||
|
||||
uint8 reg_val;
|
||||
switch(op){
|
||||
case Opcode_BEGIN:
|
||||
case Opcode_INC:
|
||||
break; // do nothing
|
||||
case Opcode_LD:
|
||||
case Opcode_ST:
|
||||
found = sequencer()->getRubyMemoryValue(m_instructions[i].getAddress(), (char *) &ruby_value, 1);
|
||||
assert(found);
|
||||
|
||||
if (ruby_value != testArray[i]){
|
||||
success = false;
|
||||
WARN_MSG("DATA MISMATCH!");
|
||||
WARN_EXPR((int) ruby_value);
|
||||
WARN_EXPR((int) testArray[i]);
|
||||
WARN_EXPR(i);
|
||||
assert(success);
|
||||
}
|
||||
break;
|
||||
case Opcode_COMMIT:
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
ERROR_MSG("Invalid Opcode.");
|
||||
};
|
||||
}
|
||||
cout << m_node << " CORRECT!" << endl;
|
||||
}
|
||||
|
||||
Sequencer* XactAbortRequestGenerator::sequencer() const
|
||||
{
|
||||
return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
|
||||
}
|
||||
|
||||
TransactionManager* XactAbortRequestGenerator::transactionManager() const
|
||||
{
|
||||
return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getTransactionManager(m_node%RubyConfig::numberOfProcsPerChip());
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::print(ostream& out) const
|
||||
{
|
||||
}
|
||||
|
||||
void XactAbortRequestGenerator::abortTransaction(){
|
||||
cout << " " << m_node << " *** ABORT! ***" << endl;
|
||||
//m_pc = 0;
|
||||
//m_register = 5;
|
||||
m_xact_status = XactAbortRequestGeneratorStatus_Aborted;
|
||||
}
|
||||
|
||||
#endif //XACT_MEM
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999 by Mark Hill and David Wood for the Wisconsin
|
||||
* Multifacet Project. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* ##HEADER##
|
||||
*
|
||||
* This software is furnished under a license and may be used and
|
||||
* copied only in accordance with the terms of such license and the
|
||||
* inclusion of the above copyright notice. This software or any
|
||||
* other copies thereof or any derivative works may not be provided or
|
||||
* otherwise made available to any other persons. Title to and
|
||||
* ownership of the software is retained by Mark Hill and David Wood.
|
||||
* Any use of this software must include the above copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS". THE LICENSOR MAKES NO
|
||||
* WARRANTIES ABOUT ITS CORRECTNESS OR PERFORMANCE.
|
||||
* */
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XACTABORTREQUESTGENERATOR_H
|
||||
#define XACTABORTREQUESTGENERATOR_H
|
||||
|
||||
#ifdef XACT_MEM
|
||||
|
||||
#include "mem/ruby/tester/RequestGenerator.hh"
|
||||
#include "global.hh"
|
||||
#include "mem/ruby/common/Consumer.hh"
|
||||
#include "mem/ruby/system/NodeID.hh"
|
||||
#include "mem/ruby/common/Address.hh"
|
||||
|
||||
class Sequencer;
|
||||
class SubBlock;
|
||||
class SyntheticDriver;
|
||||
class Instruction;
|
||||
class TransactionManager;
|
||||
|
||||
#define MAX_ADDRESS 16777216
|
||||
|
||||
enum XactAbortRequestGeneratorStatus {
|
||||
XactAbortRequestGeneratorStatus_Waiting,
|
||||
XactAbortRequestGeneratorStatus_Ready,
|
||||
XactAbortRequestGeneratorStatus_Blocked,
|
||||
XactAbortRequestGeneratorStatus_Aborted,
|
||||
XactAbortRequestGeneratorStatus_Done
|
||||
};
|
||||
|
||||
class XactAbortRequestGenerator : public RequestGenerator {
|
||||
public:
|
||||
// Constructors
|
||||
XactAbortRequestGenerator(NodeID node, SyntheticDriver& driver);
|
||||
|
||||
// Destructor
|
||||
~XactAbortRequestGenerator();
|
||||
|
||||
// Public Methods
|
||||
void wakeup();
|
||||
void performCallback(NodeID proc, SubBlock& data);
|
||||
void abortTransaction();
|
||||
|
||||
void print(ostream& out) const;
|
||||
private:
|
||||
// Private Methods
|
||||
int thinkTime() const;
|
||||
int waitTime() const;
|
||||
int holdTime() const;
|
||||
void initiateBeginTransaction();
|
||||
void initiateStore(Address a);
|
||||
void initiateCommit();
|
||||
void initiateInc(Address a);
|
||||
void initiateLoad(Address a);
|
||||
void pickAddress();
|
||||
Sequencer* sequencer() const;
|
||||
TransactionManager* transactionManager() const;
|
||||
void execute();
|
||||
|
||||
void checkCorrectness();
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
XactAbortRequestGenerator(const XactAbortRequestGenerator& obj);
|
||||
XactAbortRequestGenerator& operator=(const XactAbortRequestGenerator& obj);
|
||||
|
||||
void newTransaction();
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
SyntheticDriver& m_driver;
|
||||
NodeID m_node;
|
||||
XactAbortRequestGeneratorStatus m_xact_status;
|
||||
int m_counter;
|
||||
Time m_last_transition;
|
||||
Address m_address;
|
||||
|
||||
Instruction *m_instructions;
|
||||
int m_pc;
|
||||
uint8 m_register;
|
||||
static Vector<uint8> testArray;
|
||||
//static uint8 dataArray[];
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
ostream& operator<<(ostream& out, const XactAbortRequestGenerator& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
ostream& operator<<(ostream& out, const XactAbortRequestGenerator& obj)
|
||||
{
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif //XACT_MEM
|
||||
|
||||
#endif //REQUESTGENERATOR_H
|
||||
|
|
@ -1,637 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999 by Mark Hill and David Wood for the Wisconsin
|
||||
* Multifacet Project. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* ##HEADER##
|
||||
*
|
||||
* This software is furnished under a license and may be used and
|
||||
* copied only in accordance with the terms of such license and the
|
||||
* inclusion of the above copyright notice. This software or any
|
||||
* other copies thereof or any derivative works may not be provided or
|
||||
* otherwise made available to any other persons. Title to and
|
||||
* ownership of the software is retained by Mark Hill and David Wood.
|
||||
* Any use of this software must include the above copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS". THE LICENSOR MAKES NO
|
||||
* WARRANTIES ABOUT ITS CORRECTNESS OR PERFORMANCE.
|
||||
* */
|
||||
|
||||
/*
|
||||
* $Id: XactRequestGenerator.C 1.7 05/09/22 16:49:19-05:00 xu@s0-29.cs.wisc.edu $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mem/ruby/tester/XactRequestGenerator.hh"
|
||||
#include "mem/protocol/LockStatus.hh"
|
||||
#include "mem/ruby/system/Sequencer.hh"
|
||||
#include "mem/ruby/system/System.hh"
|
||||
#include "mem/ruby/config/RubyConfig.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
#include "mem/ruby/tester/SyntheticDriver.hh"
|
||||
#include "mem/protocol/Chip.hh"
|
||||
#include "mem/ruby/tester/Instruction.hh"
|
||||
|
||||
XactRequestGenerator::XactRequestGenerator(NodeID node, SyntheticDriver& driver) :
|
||||
m_driver(driver), RequestGenerator(node, driver)
|
||||
{
|
||||
DEBUG_EXPR(TESTER_COMP, MedPrio, "#### -- Creating XactRequestGenerator\n");
|
||||
cout << "#### -- Creating XactRequestGenerator " << node << endl;
|
||||
|
||||
assert(XACT_SIZE > 0);
|
||||
testArray = new uint8[g_MEMORY_SIZE_BYTES];;
|
||||
// Create instructions
|
||||
m_instructions = new Instruction[XACT_LENGTH];
|
||||
newTransaction(true);
|
||||
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
m_last_transition = 0;
|
||||
m_node = node;
|
||||
//pickAddress();
|
||||
m_counter = 0;
|
||||
m_register = 5;
|
||||
m_pc = 0;
|
||||
|
||||
m_abortPending = false;
|
||||
g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
|
||||
}
|
||||
|
||||
void XactRequestGenerator::newTransaction(bool init){
|
||||
// important: reset abort flag
|
||||
m_abortPending = false;
|
||||
|
||||
int depth = 0;
|
||||
bool prev_ldst = false;
|
||||
m_size = (random() % (XACT_LENGTH-2)) + 2;
|
||||
cout << "XactRequestGenerator::newTransaction m_size=" << m_size << endl;
|
||||
ASSERT(m_size >= 2);
|
||||
if (!init)
|
||||
ASSERT(!transactionManager()->inTransaction(0));
|
||||
m_transaction = (random() % 2);
|
||||
|
||||
if(m_transaction){
|
||||
cout << " " << m_node << " new transaction " << endl;
|
||||
} else {
|
||||
cout << " " << m_node << " new NON-transaction " << endl;
|
||||
}
|
||||
|
||||
cout << "***INSTR STREAM ";
|
||||
for(int i=0; i<m_size; ++i){
|
||||
if (i == 0 && m_transaction){ // new xact must start with begin
|
||||
m_instructions[i].init(Opcode_BEGIN, Address(1));
|
||||
depth++;
|
||||
cout << "begin ";
|
||||
prev_ldst = false;
|
||||
} else if (i == m_size - 1){
|
||||
if(m_transaction) { // new xact must end with commit
|
||||
m_instructions[i].init(Opcode_COMMIT, Address(1));
|
||||
depth--;
|
||||
cout << "commit ";
|
||||
} else {
|
||||
m_instructions[i].init(Opcode_DONE, Address(1));
|
||||
cout << "done ";
|
||||
}
|
||||
} else {
|
||||
int selectAction;
|
||||
if (!m_transaction) { // non-xact: must choose op
|
||||
selectAction = 1;
|
||||
} else { // xact
|
||||
if (depth == m_size - i) { // must choose commit
|
||||
selectAction = 0;
|
||||
} else if (prev_ldst) { // only choose xact if intervenient ld/st
|
||||
if (m_size - i < depth + 3) { // can choose op or
|
||||
// commit (can't choose
|
||||
// begin)
|
||||
selectAction = (random() % 2);
|
||||
} else if (depth == 0) { // can choose begin or op (can't
|
||||
// choose commit)
|
||||
selectAction = (random() % 2);
|
||||
if (selectAction == 0) selectAction = 2;
|
||||
} else { // can choose begin, op, or commit
|
||||
selectAction = (random() % 3);
|
||||
}
|
||||
} else {
|
||||
selectAction = 1;
|
||||
}
|
||||
}
|
||||
|
||||
physical_address_t address;
|
||||
int selectOpcode;
|
||||
switch (selectAction) {
|
||||
case 0: // commit
|
||||
m_instructions[i].init(Opcode_COMMIT, Address(1));
|
||||
depth--;
|
||||
cout << "commit ";
|
||||
prev_ldst = false;
|
||||
break;
|
||||
case 1:
|
||||
address = (random() % XACT_SIZE);
|
||||
//cout << "address: " << address << endl;
|
||||
//cout << "XACT_SIZE: " << XACT_SIZE << endl;
|
||||
|
||||
//assert(address < XACT_SIZE);
|
||||
//physical_address_t address = 0;
|
||||
selectOpcode = random() % 3;
|
||||
Opcode op;
|
||||
switch(selectOpcode){
|
||||
case 0:
|
||||
op = Opcode_LD;
|
||||
cout << "ld ";
|
||||
break;
|
||||
case 1:
|
||||
op = Opcode_ST;
|
||||
cout << "st ";
|
||||
break;
|
||||
case 2:
|
||||
op = Opcode_INC;
|
||||
cout << "inc ";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
};
|
||||
assert(op < Opcode_NUM_OPCODES);
|
||||
m_instructions[i].init(op, Address(address));
|
||||
prev_ldst = true;
|
||||
break;
|
||||
case 2:
|
||||
m_instructions[i].init(Opcode_BEGIN, Address(1));
|
||||
depth++;
|
||||
cout << "begin ";
|
||||
prev_ldst = false;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
};
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
if(m_transaction){
|
||||
ASSERT(m_instructions[0].getOpcode() == Opcode_BEGIN);
|
||||
}
|
||||
}
|
||||
|
||||
XactRequestGenerator::~XactRequestGenerator()
|
||||
{
|
||||
if(testArray){
|
||||
delete [] testArray;
|
||||
testArray = NULL;
|
||||
}
|
||||
delete m_instructions;
|
||||
}
|
||||
|
||||
void XactRequestGenerator::wakeup()
|
||||
{
|
||||
DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
|
||||
DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
|
||||
|
||||
assert(m_status == XactRequestGeneratorStatus_Ready || m_status == XactRequestGeneratorStatus_Aborted);
|
||||
m_status = XactRequestGeneratorStatus_Blocked;
|
||||
|
||||
m_last_transition = g_eventQueue_ptr->getTime();
|
||||
execute();
|
||||
}
|
||||
|
||||
void XactRequestGenerator::execute(){
|
||||
cout << "XactRequestGenerator::execute m_node=" << m_node << " m_pc=" << m_pc << " m_size=" << m_size << endl;
|
||||
assert(m_pc >= 0);
|
||||
assert(m_pc < m_size);
|
||||
assert(m_pc < XACT_LENGTH);
|
||||
|
||||
Instruction current = m_instructions[m_pc];
|
||||
switch (current.getOpcode()){
|
||||
case Opcode_BEGIN:
|
||||
cout << " -- begin.";
|
||||
initiateBeginTransaction();
|
||||
break;
|
||||
case Opcode_LD:
|
||||
cout << " -- load: " << current.getAddress();
|
||||
initiateLoad(current.getAddress());
|
||||
break;
|
||||
case Opcode_INC:
|
||||
cout << " -- inc.";
|
||||
initiateInc(current.getAddress());
|
||||
break;
|
||||
case Opcode_ST:
|
||||
cout << " -- store: " << current.getAddress();
|
||||
initiateStore(current.getAddress());
|
||||
break;
|
||||
case Opcode_COMMIT:
|
||||
cout << " -- commit.";
|
||||
initiateCommit();
|
||||
break;
|
||||
case Opcode_DONE:
|
||||
cout << " -- done.";
|
||||
initiateDone();
|
||||
break;
|
||||
default:
|
||||
WARN_EXPR(current.getOpcode());
|
||||
ERROR_MSG("Invalid opcode");
|
||||
};
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
void XactRequestGenerator::performCallback(NodeID proc, SubBlock& data)
|
||||
{
|
||||
cout << "XactRequestGenerator::performCallback m_node=" << m_node << endl;
|
||||
assert(m_status == XactRequestGeneratorStatus_Waiting ||
|
||||
m_status == XactRequestGeneratorStatus_Aborted);
|
||||
assert(proc == m_node);
|
||||
|
||||
Address address = data.getAddress();
|
||||
//assert(address == m_address);
|
||||
|
||||
DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
|
||||
DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
|
||||
DEBUG_EXPR(TESTER_COMP, LowPrio, address);
|
||||
DEBUG_EXPR(TESTER_COMP, LowPrio, data);
|
||||
|
||||
m_last_transition = g_eventQueue_ptr->getTime();
|
||||
|
||||
cout << " " << m_node << " in performCallback, pc:" << m_pc
|
||||
<< ", addr:" << address << endl;
|
||||
|
||||
|
||||
int depth;
|
||||
if(m_status == XactRequestGeneratorStatus_Aborted){
|
||||
depth = transactionManager()->postAbortIndex(0);
|
||||
m_pc = pc_stack[depth];
|
||||
cout << "XactRequestGenerator::performCallback m_node=" << m_node << " setting m_pc=" << m_pc << endl;
|
||||
printPcStack(depth);
|
||||
m_register = 5;
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, ABORT_RETRY_TIME);
|
||||
} else {
|
||||
m_status = XactRequestGeneratorStatus_Blocked;
|
||||
bool found, outermost;
|
||||
uint8 value;
|
||||
switch (m_instructions[m_pc].getOpcode()){
|
||||
case Opcode_BEGIN:
|
||||
m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
m_register = 5;
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, waitTime());
|
||||
depth = transactionManager()->getDepth(0);
|
||||
if (!transactionManager()->isSubsuming(0)) {
|
||||
pc_stack[depth - 1] = m_pc;
|
||||
cout << "XactRequestGenerator::performCallback m_node=" << m_node << " SETTING PC_STACK" << endl;
|
||||
printPcStack(depth);
|
||||
}
|
||||
m_pc++;
|
||||
break;
|
||||
case Opcode_LD:
|
||||
m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
m_register = data.getByte(0);
|
||||
//cout << " " << m_node << " " << g_eventQueue_ptr->getTime() << " Callback--LD: " << (int) m_register << endl;
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, waitTime());
|
||||
m_pc++;
|
||||
break;
|
||||
//case Opcode_INC: // We shouldn't get a callback for this!
|
||||
//m_driver.recordSwapLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
|
||||
// break;
|
||||
case Opcode_ST:
|
||||
m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
//data.setByte(address.getOffset(), m_register);
|
||||
data.setByte(0, m_register);
|
||||
//cout << " " << m_node << " " << g_eventQueue_ptr->getTime() << " Callback--ST: " << (int) m_register << endl;
|
||||
|
||||
//dataArray[address.getAddress()] = m_register;
|
||||
found = sequencer()->setRubyMemoryValue(address, (char *) (&m_register), 1);
|
||||
assert(found);
|
||||
found = sequencer()->getRubyMemoryValue(address, (char *) (&value), 1);
|
||||
assert(found);
|
||||
assert(value == m_register);
|
||||
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, thinkTime());
|
||||
m_pc++;
|
||||
break;
|
||||
case Opcode_COMMIT:
|
||||
outermost = transactionManager()->getDepth(0) == 1;
|
||||
if (outermost) { // about to commit outermost
|
||||
m_counter++;
|
||||
}
|
||||
|
||||
cout << " " << m_node << " callback--commit, counter is " << m_counter << " length is: " << g_tester_length << endl;
|
||||
// Check for correctness
|
||||
|
||||
checkCorrectness();
|
||||
transactionManager()->commitTransaction();
|
||||
|
||||
m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
|
||||
|
||||
if (outermost) {
|
||||
if (m_counter < g_tester_length) {
|
||||
m_last_transition = g_eventQueue_ptr->getTime();
|
||||
//pickAddress(); // Necessary?
|
||||
|
||||
// Create new random transaction
|
||||
cout << "CREATING NEW RANDOM XACT SET" << endl;
|
||||
newTransaction(false);
|
||||
m_pc = 0;
|
||||
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, thinkTime());
|
||||
} else {
|
||||
cout << " " << m_node << " Done." << endl;
|
||||
m_driver.reportDone();
|
||||
m_status = XactRequestGeneratorStatus_Done;
|
||||
}
|
||||
} else {
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, thinkTime());
|
||||
m_pc++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_MSG("Invalid Opcode");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
int XactRequestGenerator::thinkTime() const
|
||||
{
|
||||
return g_think_time;
|
||||
}
|
||||
|
||||
int XactRequestGenerator::waitTime() const
|
||||
{
|
||||
return g_wait_time;
|
||||
}
|
||||
|
||||
int XactRequestGenerator::holdTime() const
|
||||
{
|
||||
return g_hold_time;
|
||||
}
|
||||
|
||||
void XactRequestGenerator::pickAddress()
|
||||
{
|
||||
//m_address = m_driver.pickAddress(m_node);
|
||||
}
|
||||
|
||||
void XactRequestGenerator::initiateBeginTransaction()
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Begin Transaction");
|
||||
cout << "### -- initiating Begin " << m_node << endl;
|
||||
m_status = XactRequestGeneratorStatus_Waiting;
|
||||
sequencer()->makeRequest(CacheMsg(Address(physical_address_t(0)), Address(physical_address_t(0)), CacheRequestType_BEGIN_XACT, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0));
|
||||
transactionManager()->beginTransaction();
|
||||
}
|
||||
|
||||
void XactRequestGenerator::initiateStore(Address addr)
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Store");
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, addr);
|
||||
cout << "### -- initiating Store " << m_node << endl;
|
||||
m_status = XactRequestGeneratorStatus_Waiting;
|
||||
if(m_transaction){
|
||||
sequencer()->makeRequest(CacheMsg(addr, addr, CacheRequestType_ST_XACT, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0));
|
||||
} else {
|
||||
sequencer()->makeRequest(CacheMsg(addr, addr, CacheRequestType_ST, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0),transactionManager()->inExposedAction(0), 0));
|
||||
}
|
||||
}
|
||||
|
||||
void XactRequestGenerator::initiateCommit()
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Commit ");
|
||||
cout << "### -- initiating Commit " << m_node << endl;
|
||||
|
||||
m_status = XactRequestGeneratorStatus_Waiting;
|
||||
sequencer()->makeRequest(CacheMsg(Address(physical_address_t(0)), Address(physical_address_t(0)), CacheRequestType_COMMIT_XACT, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0));
|
||||
}
|
||||
|
||||
void XactRequestGenerator::initiateLoad(Address addr)
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Load ");
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, addr);
|
||||
|
||||
m_status = XactRequestGeneratorStatus_Waiting;
|
||||
if(m_transaction){
|
||||
cout << "### -- initiating Load XACT" << m_node << endl;
|
||||
sequencer()->makeRequest(CacheMsg(addr, addr, CacheRequestType_LD_XACT, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0 ));
|
||||
} else {
|
||||
cout << "### -- initiating Load " << m_node << endl;
|
||||
sequencer()->makeRequest(CacheMsg(addr, addr, CacheRequestType_LD, Address(m_pc), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false, Address(0), transactionManager()->getTransactionLevel(0), 0, 0 /* only 1 SMT thread */, transactionManager()->getTimestamp(0), transactionManager()->inExposedAction(0), 0));
|
||||
}
|
||||
}
|
||||
|
||||
void XactRequestGenerator::initiateInc(Address addr)
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Inc ");
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, addr);
|
||||
cout << "### -- initiating Inc " << m_node << endl;
|
||||
m_register++;
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, holdTime());
|
||||
m_pc++;
|
||||
}
|
||||
|
||||
void XactRequestGenerator::initiateDone()
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "### -- initiating Done ");
|
||||
cout << "### -- initiating Done " << m_node << endl;
|
||||
newTransaction(false);
|
||||
m_pc = 0;
|
||||
//m_register = 5;
|
||||
|
||||
m_status = XactRequestGeneratorStatus_Ready;
|
||||
g_eventQueue_ptr->scheduleEvent(this, thinkTime());
|
||||
|
||||
}
|
||||
|
||||
void XactRequestGenerator::checkCorrectness(){
|
||||
// Execute the transaction on the test array
|
||||
int testPC = 0;
|
||||
bool done = false;
|
||||
for(int i=0; i<XACT_LENGTH && !done; ++i){
|
||||
Opcode op = m_instructions[i].getOpcode();
|
||||
Address addr = m_instructions[i].getAddress();
|
||||
|
||||
uint8 reg_val;
|
||||
switch(op){
|
||||
case Opcode_BEGIN:
|
||||
reg_val = 0;
|
||||
break; // do nothing
|
||||
case Opcode_LD:
|
||||
//cout << "\tcheckCorrectness " << m_node << " LD: " << addr << " address = " << hex << addr.getAddress() << endl;
|
||||
ASSERT(addr.getAddress() < g_MEMORY_SIZE_BYTES);
|
||||
reg_val = testArray[addr.getAddress()];
|
||||
//cout << m_node << " LD: " << addr << ", " << (int) reg_val << endl;
|
||||
break;
|
||||
case Opcode_INC:
|
||||
reg_val++;
|
||||
//cout << m_node << " INC: " << (int) reg_val << endl;
|
||||
break;
|
||||
case Opcode_ST:
|
||||
//cout << "\tcheckCorrectness " << m_node << " ST: " << addr << " address = " << hex << addr.getAddress() << endl;
|
||||
ASSERT(addr.getAddress() < g_MEMORY_SIZE_BYTES);
|
||||
testArray[addr.getAddress()] = reg_val;
|
||||
//cout << m_node << " ST: " << addr << ", " << (int) reg_val << endl;
|
||||
break;
|
||||
case Opcode_DONE:
|
||||
case Opcode_COMMIT:
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
ERROR_MSG("Invalid Opcode.");
|
||||
};
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
uint8 ruby_value;
|
||||
done = false;
|
||||
bool found = false;
|
||||
for(int i=0; i<XACT_LENGTH && !done; ++i){
|
||||
Opcode op = m_instructions[i].getOpcode();
|
||||
Address addr = m_instructions[i].getAddress();
|
||||
|
||||
uint8 reg_val;
|
||||
switch(op){
|
||||
case Opcode_BEGIN:
|
||||
case Opcode_INC:
|
||||
break; // do nothing
|
||||
case Opcode_LD:
|
||||
case Opcode_ST:
|
||||
found = sequencer()->getRubyMemoryValue(m_instructions[i].getAddress(), (char *) &ruby_value, 1);
|
||||
assert(found);
|
||||
|
||||
if (ruby_value != testArray[i]){
|
||||
success = false;
|
||||
WARN_MSG("DATA MISMATCH!");
|
||||
WARN_EXPR((int) ruby_value);
|
||||
WARN_EXPR((int) testArray[i]);
|
||||
WARN_EXPR(i);
|
||||
assert(success);
|
||||
}
|
||||
|
||||
break;
|
||||
case Opcode_COMMIT:
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
ERROR_MSG("Invalid Opcode.");
|
||||
};
|
||||
}
|
||||
cout << m_node << " CORRECT!" << endl;
|
||||
}
|
||||
|
||||
Sequencer* XactRequestGenerator::sequencer() const
|
||||
{
|
||||
return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
|
||||
}
|
||||
|
||||
TransactionManager* XactRequestGenerator::transactionManager() const
|
||||
{
|
||||
return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getTransactionManager(m_node%RubyConfig::numberOfProcsPerChip());
|
||||
}
|
||||
|
||||
void XactRequestGenerator::print(ostream& out) const
|
||||
{
|
||||
}
|
||||
|
||||
void XactRequestGenerator::abortTransaction(){
|
||||
cout << " " << m_node << " *** ABORT! ***" << endl;
|
||||
m_status = XactRequestGeneratorStatus_Aborted;
|
||||
}
|
||||
|
||||
void XactRequestGenerator::printPcStack(int depth) {
|
||||
cout << "XactRequestGenerator::printPcStack m_node=" << m_node << " [";
|
||||
for (int i = 0; i < depth; i++) {
|
||||
cout << pc_stack[i] << ", ";
|
||||
}
|
||||
cout << "]" << endl;
|
||||
}
|
||||
|
||||
void XactRequestGenerator::notifySendNack( const Address & physicalAddr, uint64 remote_timestamp, const MachineID & remote_id) {
|
||||
Address addr = physicalAddr;
|
||||
addr.makeLineAddress();
|
||||
TransactionManager * xact_mgr = transactionManager();
|
||||
bool isOlder = xact_mgr->isOlder(remote_timestamp, remote_id, addr );
|
||||
if(isOlder){
|
||||
bool inReadSet = xact_mgr->isInReadSetFilter(physicalAddr, 0);
|
||||
bool inWriteSet = xact_mgr->isInWriteSetFilter(physicalAddr, 0);
|
||||
// addr should be in perfect or Bloom filter
|
||||
ASSERT( inReadSet || inWriteSet );
|
||||
cout << "notifySendNack addr = " << addr << " setting POSSIBLE CYCLE " << " my_ts = " << xact_mgr->getTimestamp(0) << " remote_ts = " << remote_timestamp << " proc = " << m_node << endl;
|
||||
xact_mgr->setPossibleCycle(addr, L1CacheMachIDToProcessorNum(remote_id), 0 /*remote thread*/ , remote_timestamp, 0 /*our thread*/);
|
||||
}
|
||||
// otherwise don't set the proc possible cycle flag
|
||||
}
|
||||
|
||||
void XactRequestGenerator::notifyReceiveNack( const Address & physicalAddr, uint64 remote_timestamp, const MachineID & remote_id ) {
|
||||
Address addr = physicalAddr;
|
||||
addr.makeLineAddress();
|
||||
// check whether the possible cycle is set, and whether remote_timestamp is older.
|
||||
// we only have 1 SMT thread
|
||||
TransactionManager * xact_mgr = transactionManager();
|
||||
int local_timestamp = xact_mgr->getTimestamp(0);
|
||||
bool possible_cycle = xact_mgr->possibleCycle(0);
|
||||
// calculate isOlder() only if possible_cycle is set. This is because isOlder assumes proc is in a transaction
|
||||
bool isOlder = false;
|
||||
if(possible_cycle){
|
||||
isOlder = xact_mgr->isOlder(remote_timestamp, remote_id, addr );
|
||||
}
|
||||
|
||||
if(isOlder && possible_cycle){
|
||||
// set our pendingAbort flag
|
||||
cout << "notifyReceiveNack Setting Abort Pending Flag addr= " << addr << " ID = " << m_node << " possible_cycle = " << possible_cycle << " time = " << g_eventQueue_ptr->getTime() << endl;
|
||||
m_abortPending = true;
|
||||
assert(possible_cycle);
|
||||
assert(isOlder);
|
||||
}
|
||||
|
||||
// profile this nack
|
||||
xact_mgr->profileNack(addr, IDToInt(L1CacheMachIDToProcessorNum(remote_id)), remote_timestamp, 0, 0);
|
||||
}
|
||||
|
||||
void XactRequestGenerator::notifyReceiveNackFinal(const Address & physicalAddr) {
|
||||
Address addr = physicalAddr;
|
||||
addr.makeLineAddress();
|
||||
TransactionManager * xact_mgr = transactionManager();
|
||||
int local_timestamp = xact_mgr->getTimestamp(0);
|
||||
bool possible_cycle = xact_mgr->possibleCycle(0);
|
||||
|
||||
// we should still have an active request
|
||||
if(m_abortPending){
|
||||
cout << "notifyReceiveNackFinal ABORTING addr= " << addr << " ID = " << m_node << " possible_cycle = " << possible_cycle << " time = " << g_eventQueue_ptr->getTime() << endl;
|
||||
assert(possible_cycle);
|
||||
|
||||
// we abort
|
||||
// Step 1: remove the aborting request from sequencer, and mark it as "Trap" in our request table if needed
|
||||
// Note: by marking request as "Trap" we can simulate HW abort delay
|
||||
switch (m_instructions[m_pc].getOpcode()){
|
||||
case Opcode_LD:
|
||||
sequencer()->readCallbackAbort(addr, 0);
|
||||
break;
|
||||
case Opcode_ST:
|
||||
sequencer()->writeCallbackAbort(addr, 0);
|
||||
break;
|
||||
default:
|
||||
cout << "Invalid Opcode = " << m_instructions[m_pc].getOpcode() << endl;
|
||||
ASSERT(0);
|
||||
};
|
||||
// Step 2: call the abort handler explicitly. If using software handler + trap aborts we wait until
|
||||
// Simics transfers control to us again
|
||||
// Note: it is impossible for this request to be a prefetch, so don't need that check
|
||||
xact_mgr->abortTransaction(0, 0, -1 /*dummy remote ID*/, addr);
|
||||
//reset the abort flag
|
||||
m_abortPending = false;
|
||||
}
|
||||
else{
|
||||
// retry the request
|
||||
// figure out whether to retry transactional load or store
|
||||
switch (m_instructions[m_pc].getOpcode()){
|
||||
case Opcode_LD:
|
||||
cout << "RETRYING LOAD " << addr << " of proc = " << m_node << " transactionLevel = " << xact_mgr->getTransactionLevel(0) << " time = " << g_eventQueue_ptr->getTime() << endl;
|
||||
sequencer()->issueInterProcLoadRetryRequest(addr, 0);
|
||||
break;
|
||||
case Opcode_ST:
|
||||
cout << "RETRYING STORE " << addr << " of proc = " << m_node << " transactionLevel = " << xact_mgr->getTransactionLevel(0) << " time = " << g_eventQueue_ptr->getTime() << endl;
|
||||
sequencer()->issueInterProcStoreRetryRequest(addr, 0);
|
||||
break;
|
||||
default:
|
||||
cout << "Invalid Opcode = " << m_instructions[m_pc].getOpcode() << endl;
|
||||
ASSERT(0);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999 by Mark Hill and David Wood for the Wisconsin
|
||||
* Multifacet Project. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* ##HEADER##
|
||||
*
|
||||
* This software is furnished under a license and may be used and
|
||||
* copied only in accordance with the terms of such license and the
|
||||
* inclusion of the above copyright notice. This software or any
|
||||
* other copies thereof or any derivative works may not be provided or
|
||||
* otherwise made available to any other persons. Title to and
|
||||
* ownership of the software is retained by Mark Hill and David Wood.
|
||||
* Any use of this software must include the above copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS". THE LICENSOR MAKES NO
|
||||
* WARRANTIES ABOUT ITS CORRECTNESS OR PERFORMANCE.
|
||||
* */
|
||||
|
||||
/*
|
||||
* $Id: XactRequestGenerator.h 1.4 05/07/07 10:35:32-05:00 kmoore@s0-30.cs.wisc.edu $
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XACTREQUESTGENERATOR_H
|
||||
#define XACTREQUESTGENERATOR_H
|
||||
|
||||
#include "global.hh"
|
||||
#include "mem/ruby/tester/RequestGenerator.hh"
|
||||
#include "mem/ruby/common/Consumer.hh"
|
||||
#include "mem/ruby/system/NodeID.hh"
|
||||
#include "mem/ruby/common/Address.hh"
|
||||
#include "TransactionManager.hh"
|
||||
|
||||
class Sequencer;
|
||||
class SubBlock;
|
||||
class SyntheticDriver;
|
||||
class Instruction;
|
||||
class TransactionManager;
|
||||
|
||||
#define MAX_ADDRESS 16777216
|
||||
const int TESTER_MAX_DEPTH = 16;
|
||||
|
||||
enum XactRequestGeneratorStatus {
|
||||
XactRequestGeneratorStatus_Waiting,
|
||||
XactRequestGeneratorStatus_Ready,
|
||||
XactRequestGeneratorStatus_Blocked,
|
||||
XactRequestGeneratorStatus_Aborted,
|
||||
XactRequestGeneratorStatus_Done
|
||||
};
|
||||
|
||||
class XactRequestGenerator : public RequestGenerator {
|
||||
public:
|
||||
// Constructors
|
||||
XactRequestGenerator(NodeID node, SyntheticDriver& driver);
|
||||
|
||||
// Destructor
|
||||
~XactRequestGenerator();
|
||||
|
||||
// Public Methods
|
||||
void wakeup();
|
||||
void performCallback(NodeID proc, SubBlock& data);
|
||||
void abortTransaction();
|
||||
|
||||
void print(ostream& out) const;
|
||||
|
||||
// For dealing with NACKs/retries
|
||||
void notifySendNack(const Address & addr, uint64 remote_timestamp, const MachineID & remote_id);
|
||||
void notifyReceiveNack(const Address & addr, uint64 remote_timestamp, const MachineID & remote_id);
|
||||
void notifyReceiveNackFinal(const Address & addr);
|
||||
private:
|
||||
// Private Methods
|
||||
int thinkTime() const;
|
||||
int waitTime() const;
|
||||
int holdTime() const;
|
||||
void initiateBeginTransaction();
|
||||
void initiateStore(Address a);
|
||||
void initiateCommit();
|
||||
void initiateInc(Address a);
|
||||
void initiateLoad(Address a);
|
||||
void initiateDone();
|
||||
void pickAddress();
|
||||
Sequencer* sequencer() const;
|
||||
TransactionManager* transactionManager() const;
|
||||
void execute();
|
||||
void scheduleEvent(int time);
|
||||
void checkCorrectness();
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
XactRequestGenerator(const XactRequestGenerator& obj);
|
||||
XactRequestGenerator& operator=(const XactRequestGenerator& obj);
|
||||
|
||||
void newTransaction(bool init);
|
||||
void printPcStack(int depth);
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
SyntheticDriver& m_driver;
|
||||
NodeID m_node;
|
||||
XactRequestGeneratorStatus m_status;
|
||||
int m_counter;
|
||||
int m_size;
|
||||
Time m_last_transition;
|
||||
Address m_address;
|
||||
|
||||
Instruction *m_instructions;
|
||||
int m_pc;
|
||||
int pc_stack[TESTER_MAX_DEPTH];
|
||||
bool m_transaction;
|
||||
uint8 m_register;
|
||||
uint8 * testArray;
|
||||
//static uint8 dataArray[];
|
||||
bool m_eventPending;
|
||||
|
||||
// for pending aborts
|
||||
bool m_abortPending;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
ostream& operator<<(ostream& out, const XactRequestGenerator& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
ostream& operator<<(ostream& out, const XactRequestGenerator& obj)
|
||||
{
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif //XACTREQUESTGENERATOR_H
|
||||
|
Loading…
Reference in a new issue