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:
Polina Dudnik 2009-05-11 10:38:46 -07:00
parent 9f34659c52
commit b271090923
9 changed files with 0 additions and 1710 deletions

View file

@ -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";
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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);
};
}
}

View file

@ -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