diff options
author | Nathan Binkert <nate@binkert.org> | 2009-05-11 10:38:43 -0700 |
---|---|---|
committer | Nathan Binkert <nate@binkert.org> | 2009-05-11 10:38:43 -0700 |
commit | 2f30950143cc70bc42a3c8a4111d7cf8198ec881 (patch) | |
tree | 708f6c22edb3c6feb31dd82866c26623a5329580 /src/mem/ruby/tester/XactAbortRequestGenerator.cc | |
parent | c70241810d4e4f523f173c1646b008dc40faad8e (diff) | |
download | gem5-2f30950143cc70bc42a3c8a4111d7cf8198ec881.tar.xz |
ruby: Import ruby and slicc from GEMS
We eventually plan to replace the m5 cache hierarchy with the GEMS
hierarchy, but for now we will make both live alongside eachother.
Diffstat (limited to 'src/mem/ruby/tester/XactAbortRequestGenerator.cc')
-rw-r--r-- | src/mem/ruby/tester/XactAbortRequestGenerator.cc | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/src/mem/ruby/tester/XactAbortRequestGenerator.cc b/src/mem/ruby/tester/XactAbortRequestGenerator.cc new file mode 100644 index 000000000..e562aa760 --- /dev/null +++ b/src/mem/ruby/tester/XactAbortRequestGenerator.cc @@ -0,0 +1,403 @@ +/* + * 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 "XactAbortRequestGenerator.hh" +#include "LockStatus.hh" +#include "Sequencer.hh" +#include "System.hh" +#include "RubyConfig.hh" +#include "SubBlock.hh" +#include "SyntheticDriver.hh" +#include "Chip.hh" +#include "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 |