summaryrefslogtreecommitdiff
path: root/src/mem/ruby/tester
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/ruby/tester')
-rw-r--r--src/mem/ruby/tester/BarrierGenerator.cc333
-rw-r--r--src/mem/ruby/tester/BarrierGenerator.hh138
-rw-r--r--src/mem/ruby/tester/Check.cc310
-rw-r--r--src/mem/ruby/tester/Check.hh107
-rw-r--r--src/mem/ruby/tester/CheckTable.cc128
-rw-r--r--src/mem/ruby/tester/DetermGETXGenerator.cc72
-rw-r--r--src/mem/ruby/tester/DetermGETXGenerator.hh17
-rw-r--r--src/mem/ruby/tester/DetermInvGenerator.cc100
-rw-r--r--src/mem/ruby/tester/DetermInvGenerator.hh11
-rw-r--r--src/mem/ruby/tester/DetermSeriesGETSGenerator.cc56
-rw-r--r--src/mem/ruby/tester/DetermSeriesGETSGenerator.hh11
-rw-r--r--src/mem/ruby/tester/DeterministicDriver.cc145
-rw-r--r--src/mem/ruby/tester/DeterministicDriver.hh54
-rw-r--r--src/mem/ruby/tester/Driver_Tester.cc (renamed from src/mem/ruby/tester/CheckTable.hh)61
-rw-r--r--src/mem/ruby/tester/Driver_Tester.hh (renamed from src/mem/ruby/tester/Tester.hh)71
-rw-r--r--src/mem/ruby/tester/EventQueue_Tester.hh118
-rw-r--r--src/mem/ruby/tester/Global_Tester.hh (renamed from src/mem/ruby/tester/RequestGenerator.hh)110
-rw-r--r--src/mem/ruby/tester/Instruction.cc51
-rw-r--r--src/mem/ruby/tester/Instruction.hh57
-rw-r--r--src/mem/ruby/tester/RaceyDriver.cc67
-rw-r--r--src/mem/ruby/tester/RaceyDriver.hh32
-rw-r--r--src/mem/ruby/tester/RaceyPseudoThread.cc353
-rw-r--r--src/mem/ruby/tester/RaceyPseudoThread.hh151
-rw-r--r--src/mem/ruby/tester/RequestGenerator.cc220
-rw-r--r--src/mem/ruby/tester/SpecifiedGenerator.cc4
-rw-r--r--src/mem/ruby/tester/SpecifiedGenerator.hh8
-rw-r--r--src/mem/ruby/tester/SyntheticDriver.cc286
-rw-r--r--src/mem/ruby/tester/SyntheticDriver.hh118
-rw-r--r--src/mem/ruby/tester/Tester.cc112
-rw-r--r--src/mem/ruby/tester/main.cc9
-rw-r--r--src/mem/ruby/tester/main.hh9
-rw-r--r--src/mem/ruby/tester/test_framework.cc433
-rw-r--r--src/mem/ruby/tester/test_framework.hh4
33 files changed, 1210 insertions, 2546 deletions
diff --git a/src/mem/ruby/tester/BarrierGenerator.cc b/src/mem/ruby/tester/BarrierGenerator.cc
deleted file mode 100644
index 9dbcf39fd..000000000
--- a/src/mem/ruby/tester/BarrierGenerator.cc
+++ /dev/null
@@ -1,333 +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.
- */
-
-/*
- * $Id: BarrierGenerator.C 1.3 2005/01/19 13:12:35-06:00 mikem@maya.cs.wisc.edu $
- *
- */
-
-#include "mem/ruby/tester/BarrierGenerator.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"
-
-BarrierGenerator::BarrierGenerator(NodeID node, SyntheticDriver& driver) :
- m_driver(driver)
-{
- m_status = BarrierGeneratorStatus_Thinking;
- m_last_transition = 0;
- m_node = node;
- m_counter = 0;
- proc_counter = 0;
- m_local_sense = false;
-
- m_total_think = 0;
- m_think_periods = 0;
-
- g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
-}
-
-BarrierGenerator::~BarrierGenerator()
-{
-}
-
-void BarrierGenerator::wakeup()
-{
- DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
- DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
-
- if (m_status == BarrierGeneratorStatus_Thinking) {
- m_barrier_done = false;
- m_local_sense = !m_local_sense;
- m_status = BarrierGeneratorStatus_Test_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateTest(); // Test
- } else if (m_status == BarrierGeneratorStatus_Test_Waiting) {
- m_status = BarrierGeneratorStatus_Test_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateTest(); // Test
- } else if (m_status == BarrierGeneratorStatus_Release_Waiting) {
- m_status = BarrierGeneratorStatus_Release_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateRelease(); // Test
- } else if (m_status == BarrierGeneratorStatus_StoreBarrierCounter_Waiting) {
- m_status = BarrierGeneratorStatus_StoreBarrierCounter_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateStoreCtr();
- } else if (m_status == BarrierGeneratorStatus_StoreFlag_Waiting) {
- m_status = BarrierGeneratorStatus_StoreFlag_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateStoreFlag();
- } else if (m_status == BarrierGeneratorStatus_Holding) {
- m_status = BarrierGeneratorStatus_Release_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateRelease(); // Release
- } else if (m_status == BarrierGeneratorStatus_Before_Swap) {
- m_status = BarrierGeneratorStatus_Swap_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateSwap();
- } else if (m_status == BarrierGeneratorStatus_SpinFlag_Ready) {
- m_status = BarrierGeneratorStatus_SpinFlag_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateLoadFlag();
- } else {
- WARN_EXPR(m_status);
- ERROR_MSG("Invalid status");
- }
-}
-
-void BarrierGenerator::performCallback(NodeID proc, SubBlock& data)
-{
- Address address = data.getAddress();
- assert(proc == m_node);
-
- 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);
-
- if (m_status == BarrierGeneratorStatus_Test_Pending) {
- uint8 dat = data.readByte();
- uint8 lock = dat >> 7;
- if (lock == 1) {
- // Locked - keep spinning
- m_status = BarrierGeneratorStatus_Test_Waiting;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
- } else {
- // Unlocked - try the swap
- m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- m_status = BarrierGeneratorStatus_Before_Swap;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
- }
- } else if (m_status == BarrierGeneratorStatus_Swap_Pending) {
- m_driver.recordSwapLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- uint8 dat = data.readByte();
- uint8 lock = dat >> 7;
- if (lock == 1) {
- // We failed to aquire the lock
- m_status = BarrierGeneratorStatus_Test_Waiting;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
- } else {
- // We acquired the lock
- dat = dat | 0x80;
- data.writeByte(dat);
- m_status = BarrierGeneratorStatus_StoreBarrierCounter_Waiting;
- m_last_transition = g_eventQueue_ptr->getTime();
- DEBUG_MSG(TESTER_COMP, HighPrio, "Acquired");
- DEBUG_EXPR(TESTER_COMP, HighPrio, proc);
- DEBUG_EXPR(TESTER_COMP, HighPrio, g_eventQueue_ptr->getTime());
- // g_eventQueue_ptr->scheduleEvent(this, holdTime());
-
- g_eventQueue_ptr->scheduleEvent(this, 1);
-
- // initiateLoadCtr();
- }
- } else if (m_status == BarrierGeneratorStatus_StoreBarrierCounter_Pending) {
-
- // if value == p, reset counter and set local sense flag
- uint8 ctr = data.readByte();
- //uint8 sense = ctr >> 4;
- ctr = ctr & 0x0F;
-
- ctr++;
- data.writeByte( ctr | 0x80); // store counter and lock
-
- //cout << m_node << " incremented Barrier_ctr to " << (int)ctr << ", " << data << "\n";
-
- if (ctr == (uint8) 16) {
-
- data.writeByte( 0x0 );
- m_status = BarrierGeneratorStatus_StoreFlag_Waiting;
- m_barrier_done = true;
-
- g_eventQueue_ptr->scheduleEvent(this, 1);
- }
- else {
-
- m_status = BarrierGeneratorStatus_Release_Waiting;
- g_eventQueue_ptr->scheduleEvent(this, 1);
- }
- } else if (m_status == BarrierGeneratorStatus_StoreFlag_Pending) {
-
- // write flag
- if (m_local_sense) {
- data.writeByte( 0x01 );
- }
- else {
- data.writeByte( 0x00 );
- }
-
- m_status = BarrierGeneratorStatus_Release_Waiting;
- g_eventQueue_ptr->scheduleEvent(this, 1);
-
- } else if (m_status == BarrierGeneratorStatus_Release_Pending) {
- m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- // We're releasing the lock
- uint8 dat = data.readByte();
- dat = dat & 0x7F;
- data.writeByte(dat);
-
- if (m_barrier_done) {
- m_counter++;
- proc_counter++;
- if (m_counter < g_tester_length) {
- m_status = BarrierGeneratorStatus_Thinking;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, thinkTime());
- } else {
-
- m_driver.reportDone(proc_counter, m_node);
- m_last_transition = g_eventQueue_ptr->getTime();
- }
- }
- else {
- m_status = BarrierGeneratorStatus_SpinFlag_Ready;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
- }
- } else if (m_status == BarrierGeneratorStatus_SpinFlag_Pending) {
-
- uint8 sense = data.readByte();
-
-
- if (sense != m_local_sense) {
- m_status = BarrierGeneratorStatus_SpinFlag_Ready;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
- }
- else {
- m_counter++;
- proc_counter++;
- if (m_counter < g_tester_length) {
- m_status = BarrierGeneratorStatus_Thinking;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, thinkTime());
- } else {
- m_driver.reportDone(proc_counter, m_node);
- m_status = BarrierGeneratorStatus_Done;
- m_last_transition = g_eventQueue_ptr->getTime();
- }
- }
-
- } else {
- WARN_EXPR(m_status);
- ERROR_MSG("Invalid status");
- }
-}
-
-int BarrierGenerator::thinkTime()
-{
- int ret;
- float ratio = g_think_fudge_factor;
-
- // return 400;
-
- if (ratio == 0) {
- return g_think_time;
- }
-
- int r = random();
- int x = (int) ( (float)g_think_time*ratio*2.0);
- int mod = r % x;
-
-
- int rand = ( mod+1 - ((float)g_think_time*ratio) );
-
- ret = (g_think_time + rand);
-
- m_total_think += ret;
- m_think_periods++;
-
- return ret;
-}
-
-int BarrierGenerator::waitTime() const
-{
- return g_wait_time;
-}
-
-
-void BarrierGenerator::initiateTest()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Test");
- sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_LD, Address(1), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateSwap()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Swap");
- sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_ATOMIC, Address(2), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateRelease()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Release");
- sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateLoadCtr()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating load of barrier counter");
- sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_LD, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateStoreCtr()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating load of barrier counter");
- sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateStoreFlag()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating load of barrier counter");
- sequencer()->makeRequest(CacheMsg(Address(0x00), CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateLoadFlag()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating load of barrier counter");
- sequencer()->makeRequest(CacheMsg(Address(0x00), CacheRequestType_LD, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-
-Sequencer* BarrierGenerator::sequencer() const
-{
- return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
-}
-
-void BarrierGenerator::print(ostream& out) const
-{
-}
-
diff --git a/src/mem/ruby/tester/BarrierGenerator.hh b/src/mem/ruby/tester/BarrierGenerator.hh
deleted file mode 100644
index e0fa497da..000000000
--- a/src/mem/ruby/tester/BarrierGenerator.hh
+++ /dev/null
@@ -1,138 +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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef BARRIERGENERATOR_H
-#define BARRIERGENERATOR_H
-
-#include "mem/ruby/common/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;
-
-
-enum BarrierGeneratorStatus {
- BarrierGeneratorStatus_FIRST,
- BarrierGeneratorStatus_Thinking = BarrierGeneratorStatus_FIRST,
- BarrierGeneratorStatus_Test_Pending,
- BarrierGeneratorStatus_Test_Waiting,
- BarrierGeneratorStatus_Before_Swap,
- BarrierGeneratorStatus_Swap_Pending,
- BarrierGeneratorStatus_Holding,
- BarrierGeneratorStatus_Release_Pending,
- BarrierGeneratorStatus_Release_Waiting,
- BarrierGeneratorStatus_StoreFlag_Waiting,
- BarrierGeneratorStatus_StoreFlag_Pending,
- BarrierGeneratorStatus_Done,
- BarrierGeneratorStatus_SpinFlag_Ready,
- BarrierGeneratorStatus_SpinFlag_Pending,
- BarrierGeneratorStatus_LoadBarrierCounter_Pending,
- BarrierGeneratorStatus_StoreBarrierCounter_Pending,
- BarrierGeneratorStatus_StoreBarrierCounter_Waiting,
- BarrierGeneratorStatus_NUM
-};
-
-
-// UNCOMMENT THIS FOR A SINGLE WORK QUEUE
-// static int m_counter;
-
-class BarrierGenerator : public Consumer {
-public:
- // Constructors
- BarrierGenerator(NodeID node, SyntheticDriver& driver);
-
- // Destructor
- ~BarrierGenerator();
-
- // Public Methods
- void wakeup();
- void performCallback(NodeID proc, SubBlock& data);
-
- void print(ostream& out) const;
-private:
- // Private Methods
- int thinkTime() ;
- int waitTime() const;
- void initiateTest();
- void initiateSwap();
- void initiateRelease();
- void initiateLoadCtr();
- void initiateStoreCtr();
- void initiateLoadFlag();
- void initiateStoreFlag();
- Sequencer* sequencer() const;
-
- // Private copy constructor and assignment operator
- BarrierGenerator(const BarrierGenerator& obj);
- BarrierGenerator& operator=(const BarrierGenerator& obj);
-
- // Data Members (m_ prefix)
- SyntheticDriver& m_driver;
- NodeID m_node;
- BarrierGeneratorStatus m_status;
- int proc_counter;
-
- int m_counter;
-
- bool m_local_sense;
- bool m_barrier_done;
-
- Time m_last_transition;
- Address m_address;
-
- int m_total_think;
- int m_think_periods;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const BarrierGenerator& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const BarrierGenerator& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-#endif //REQUESTGENERATOR_H
-
diff --git a/src/mem/ruby/tester/Check.cc b/src/mem/ruby/tester/Check.cc
deleted file mode 100644
index 7896b572a..000000000
--- a/src/mem/ruby/tester/Check.cc
+++ /dev/null
@@ -1,310 +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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/tester/Check.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/protocol/Chip.hh"
-#include "mem/packet.hh"
-
-Check::Check(const Address& address, const Address& pc)
-{
- m_status = TesterStatus_Idle;
-
- pickValue();
- pickInitiatingNode();
- changeAddress(address);
- m_pc = pc;
- m_access_mode = AccessModeType(random() % AccessModeType_NUM);
- m_store_count = 0;
-}
-
-void Check::initiate()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating");
- DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
-
- // current CMP protocol doesn't support prefetches
- if (!Protocol::m_CMP && (random() & 0xf) == 0) { // 1 in 16 chance
- initiatePrefetch(); // Prefetch from random processor
- }
-
- if(m_status == TesterStatus_Idle) {
- initiateAction();
- } else if(m_status == TesterStatus_Ready) {
- initiateCheck();
- } else {
- // Pending - do nothing
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating action/check - failed: action/check is pending\n");
- }
-}
-
-void Check::initiatePrefetch(Sequencer* targetSequencer_ptr)
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating prefetch");
-
- CacheRequestType type;
- if ((random() & 0x7) != 0) { // 1 in 8 chance
- if ((random() & 0x1) == 0) { // 50% chance
- type = CacheRequestType_LD;
- } else {
- type = CacheRequestType_IFETCH;
- }
- } else {
- type = CacheRequestType_ST;
- }
-
- Addr data_addr = m_address.getAddress();
- Addr pc_addr = m_pc.getAddress();
- Request request(0, data_addr, 0, Flags<unsigned int>(Request::PREFETCH), pc_addr, 0, 0);
- MemCmd::Command command;
- if (type == CacheRequestType_IFETCH) {
- command = MemCmd::ReadReq;
- request.setFlags(Request::INST_FETCH);
- } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
- command = MemCmd::ReadReq;
- } else if (type == CacheRequestType_ST) {
- command = MemCmd::WriteReq;
- } else if (type == CacheRequestType_ATOMIC) {
- command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
- } else {
- panic("Cannot convert request to packet");
- }
-
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
- assert(targetSequencer_ptr != NULL);
- if (targetSequencer_ptr->isReady(&pkt)) {
- targetSequencer_ptr->makeRequest(&pkt);
- }
-}
-
-void Check::initiatePrefetch()
-{
- // Any sequencer can issue a prefetch for this address
- Sequencer* targetSequencer_ptr = g_system_ptr->getChip(random() % RubyConfig::numberOfChips())->getSequencer(random() % RubyConfig::numberOfProcsPerChip());
- assert(targetSequencer_ptr != NULL);
- initiatePrefetch(targetSequencer_ptr);
-}
-
-void Check::initiateAction()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Action");
- assert(m_status == TesterStatus_Idle);
-
- CacheRequestType type = CacheRequestType_ST;
- if ((random() & 0x1) == 0) { // 50% chance
- type = CacheRequestType_ATOMIC;
- }
-
- Addr data_addr = m_address.getAddress()+m_store_count;
- Addr pc_addr = m_pc.getAddress();
- Request request(0, data_addr, 1, Flags<unsigned int>(), pc_addr, 0, 0);
- MemCmd::Command command;
- if (type == CacheRequestType_IFETCH) {
- command = MemCmd::ReadReq;
- request.setFlags(Request::INST_FETCH);
- } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
- command = MemCmd::ReadReq;
- } else if (type == CacheRequestType_ST) {
- command = MemCmd::WriteReq;
- } else if (type == CacheRequestType_ATOMIC) {
- command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
- } else {
- panic("Cannot convert request to packet");
- }
-
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
- Sequencer* sequencer_ptr = initiatingSequencer();
- if (sequencer_ptr->isReady(&pkt) == false) {
- DEBUG_MSG(TESTER_COMP, MedPrio, "failed to initiate action - sequencer not ready\n");
- } else {
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating action - successful\n");
- DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
- m_status = TesterStatus_Action_Pending;
-
- sequencer_ptr->makeRequest(&pkt);
- }
- DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
-}
-
-void Check::initiateCheck()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Check");
- assert(m_status == TesterStatus_Ready);
-
- CacheRequestType type = CacheRequestType_LD;
- if ((random() & 0x1) == 0) { // 50% chance
- type = CacheRequestType_IFETCH;
- }
-
-
- Addr data_addr = m_address.getAddress()+m_store_count;
- Addr pc_addr = m_pc.getAddress();
- Request request(0, data_addr, CHECK_SIZE, Flags<unsigned int>(), pc_addr, 0, 0);
- MemCmd::Command command;
- if (type == CacheRequestType_IFETCH) {
- command = MemCmd::ReadReq;
- request.setFlags(Request::INST_FETCH);
- } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
- command = MemCmd::ReadReq;
- } else if (type == CacheRequestType_ST) {
- command = MemCmd::WriteReq;
- } else if (type == CacheRequestType_ATOMIC) {
- command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
- } else {
- panic("Cannot convert request to packet");
- }
-
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
- Sequencer* sequencer_ptr = initiatingSequencer();
- if (sequencer_ptr->isReady(&pkt) == false) {
- DEBUG_MSG(TESTER_COMP, MedPrio, "failed to initiate check - sequencer not ready\n");
- } else {
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating check - successful\n");
- DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
- m_status = TesterStatus_Check_Pending;
-
- sequencer_ptr->makeRequest(&pkt);
- }
- DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
-}
-
-void Check::performCallback(NodeID proc, SubBlock& data)
-{
- Address address = data.getAddress();
- // assert(getAddress() == address); // This isn't exactly right since we now have multi-byte checks
- assert(getAddress().getLineAddress() == address.getLineAddress());
-
- DEBUG_MSG(TESTER_COMP, MedPrio, "Callback");
- DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
-
- if (m_status == TesterStatus_Action_Pending) {
- DEBUG_MSG(TESTER_COMP, MedPrio, "Action callback");
- // Perform store
- data.setByte(0, m_value+m_store_count); // We store one byte at a time
- m_store_count++;
-
- if (m_store_count == CHECK_SIZE) {
- m_status = TesterStatus_Ready;
- } else {
- m_status = TesterStatus_Idle;
- }
- } else if (m_status == TesterStatus_Check_Pending) {
- DEBUG_MSG(TESTER_COMP, MedPrio, "Check callback");
- // Perform load/check
- for(int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
- if (uint8(m_value+byte_number) != data.getByte(byte_number) && (DATA_BLOCK == true)) {
- WARN_EXPR(proc);
- WARN_EXPR(address);
- WARN_EXPR(data);
- WARN_EXPR(byte_number);
- WARN_EXPR((int)m_value+byte_number);
- WARN_EXPR((int)data.getByte(byte_number));
- WARN_EXPR(*this);
- WARN_EXPR(g_eventQueue_ptr->getTime());
- ERROR_MSG("Action/check failure");
- }
- }
- DEBUG_MSG(TESTER_COMP, HighPrio, "Action/check success:");
- DEBUG_EXPR(TESTER_COMP, HighPrio, *this);
- DEBUG_EXPR(TESTER_COMP, MedPrio, data);
-
- m_status = TesterStatus_Idle;
- pickValue();
-
- } else {
- WARN_EXPR(*this);
- WARN_EXPR(proc);
- WARN_EXPR(data);
- WARN_EXPR(m_status);
- WARN_EXPR(g_eventQueue_ptr->getTime());
- ERROR_MSG("Unexpected TesterStatus");
- }
-
- DEBUG_EXPR(TESTER_COMP, MedPrio, proc);
- DEBUG_EXPR(TESTER_COMP, MedPrio, data);
- DEBUG_EXPR(TESTER_COMP, MedPrio, getAddress().getLineAddress());
- DEBUG_MSG(TESTER_COMP, MedPrio, "Callback done");
- DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
-}
-
-void Check::changeAddress(const Address& address)
-{
- assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
- m_status = TesterStatus_Idle;
- m_address = address;
- m_store_count = 0;
-}
-
-Sequencer* Check::initiatingSequencer() const
-{
- return g_system_ptr->getChip(m_initiatingNode/RubyConfig::numberOfProcsPerChip())->getSequencer(m_initiatingNode%RubyConfig::numberOfProcsPerChip());
-}
-
-void Check::pickValue()
-{
- assert(m_status == TesterStatus_Idle);
- m_status = TesterStatus_Idle;
- // DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
- DEBUG_MSG(TESTER_COMP, MedPrio, *this);
- m_value = random() & 0xff; // One byte
- // DEBUG_MSG(TESTER_COMP, MedPrio, m_value);
- DEBUG_MSG(TESTER_COMP, MedPrio, *this);
- m_store_count = 0;
-}
-
-void Check::pickInitiatingNode()
-{
- assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
- m_status = TesterStatus_Idle;
- DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
- m_initiatingNode = (random() % RubyConfig::numberOfProcessors());
- DEBUG_MSG(TESTER_COMP, MedPrio, m_initiatingNode);
- m_store_count = 0;
-}
-
-void Check::print(ostream& out) const
-{
- out << "["
- << m_address << ", value: "
- << (int) m_value << ", status: "
- << m_status << ", initiating node: "
- << m_initiatingNode << ", store_count: "
- << m_store_count
- << "]" << flush;
-}
diff --git a/src/mem/ruby/tester/Check.hh b/src/mem/ruby/tester/Check.hh
deleted file mode 100644
index 8f08b3f40..000000000
--- a/src/mem/ruby/tester/Check.hh
+++ /dev/null
@@ -1,107 +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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef CHECK_H
-#define CHECK_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/protocol/TesterStatus.hh"
-#include "mem/protocol/AccessModeType.hh"
-class Sequencer;
-class SubBlock;
-
-const int CHECK_SIZE_BITS = 2;
-const int CHECK_SIZE = (1<<CHECK_SIZE_BITS);
-
-class Check {
-public:
- // Constructors
- Check(const Address& address, const Address& pc);
-
- // Default Destructor
- //~Check();
-
- // Public Methods
-
- void initiate(); // Does Action or Check or nether
- void performCallback(NodeID proc, SubBlock& data);
- const Address& getAddress() { return m_address; }
- void changeAddress(const Address& address);
-
- void print(ostream& out) const;
-private:
- // Private Methods
- void initiatePrefetch(Sequencer* targetSequencer_ptr);
- void initiatePrefetch();
- void initiateAction();
- void initiateCheck();
-
- Sequencer* initiatingSequencer() const;
-
- void pickValue();
- void pickInitiatingNode();
-
- // Using default copy constructor and assignment operator
- // Check(const Check& obj);
- // Check& operator=(const Check& obj);
-
- // Data Members (m_ prefix)
- TesterStatus m_status;
- uint8 m_value;
- int m_store_count;
- NodeID m_initiatingNode;
- Address m_address;
- Address m_pc;
- AccessModeType m_access_mode;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const Check& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const Check& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-#endif //CHECK_H
diff --git a/src/mem/ruby/tester/CheckTable.cc b/src/mem/ruby/tester/CheckTable.cc
deleted file mode 100644
index b8e57a646..000000000
--- a/src/mem/ruby/tester/CheckTable.cc
+++ /dev/null
@@ -1,128 +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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/tester/CheckTable.hh"
-#include "mem/ruby/tester/Check.hh"
-#include "mem/gems_common/Map.hh"
-
-CheckTable::CheckTable()
-{
- m_lookup_map_ptr = new Map<Address, Check*>;
- physical_address_t physical = 0;
- Address address;
-
- const int size1 = 32;
- const int size2 = 100;
-
- // The first set is to get some false sharing
- physical = 1000;
- for (int i=0; i<size1; i++) {
- // Setup linear addresses
- address.setAddress(physical);
- addCheck(address);
- physical += CHECK_SIZE;
- }
-
- // The next two sets are to get some limited false sharing and cache conflicts
- physical = 1000;
- for (int i=0; i<size2; i++) {
- // Setup linear addresses
- address.setAddress(physical);
- addCheck(address);
- physical += 256;
- }
-
- physical = 1000 + CHECK_SIZE;
- for (int i=0; i<size2; i++) {
- // Setup linear addresses
- address.setAddress(physical);
- addCheck(address);
- physical += 256;
- }
-}
-
-CheckTable::~CheckTable()
-{
- int size = m_check_vector.size();
- for (int i=0; i<size; i++) {
- delete m_check_vector[i];
- }
- delete m_lookup_map_ptr;
-}
-
-void CheckTable::addCheck(const Address& address)
-{
- if (log_int(CHECK_SIZE) != 0) {
- if (address.bitSelect(0,CHECK_SIZE_BITS-1) != 0) {
- ERROR_MSG("Check not aligned");
- }
- }
-
- for (int i=0; i<CHECK_SIZE; i++) {
- if (m_lookup_map_ptr->exist(Address(address.getAddress()+i))) {
- // A mapping for this byte already existed, discard the entire check
- return;
- }
- }
-
- Check* check_ptr = new Check(address, Address(100+m_check_vector.size()));
- for (int i=0; i<CHECK_SIZE; i++) {
- // Insert it once per byte
- m_lookup_map_ptr->add(Address(address.getAddress()+i), check_ptr);
- }
- m_check_vector.insertAtBottom(check_ptr);
-}
-
-Check* CheckTable::getRandomCheck()
-{
- return m_check_vector[random() % m_check_vector.size()];
-}
-
-Check* CheckTable::getCheck(const Address& address)
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "Looking for check by address");
- DEBUG_EXPR(TESTER_COMP, MedPrio, address);
-
- if (m_lookup_map_ptr->exist(address)) {
- Check* check = m_lookup_map_ptr->lookup(address);
- assert(check != NULL);
- return check;
- } else {
- return NULL;
- }
-}
-
-void CheckTable::print(ostream& out) const
-{
-}
diff --git a/src/mem/ruby/tester/DetermGETXGenerator.cc b/src/mem/ruby/tester/DetermGETXGenerator.cc
index e4d8addd2..6692fb80c 100644
--- a/src/mem/ruby/tester/DetermGETXGenerator.cc
+++ b/src/mem/ruby/tester/DetermGETXGenerator.cc
@@ -37,26 +37,23 @@
#include "mem/ruby/tester/DetermGETXGenerator.hh"
#include "mem/protocol/DetermGETXGeneratorStatus.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/DeterministicDriver.hh"
-#include "mem/protocol/Chip.hh"
-#include "mem/packet.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/tester/SpecifiedGenerator.hh"
+//#include "DMAController.hh"
+#include "mem/ruby/libruby.hh"
-DetermGETXGenerator::DetermGETXGenerator(NodeID node, DeterministicDriver& driver) :
- m_driver(driver)
+
+DetermGETXGenerator::DetermGETXGenerator(NodeID node, DeterministicDriver * driver)
{
m_status = DetermGETXGeneratorStatus_Thinking;
m_last_transition = 0;
m_node = node;
m_address = Address(9999); // initialize to null value
m_counter = 0;
-
+ parent_driver = driver;
// don't know exactly when this node needs to request so just guess randomly
- g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
+ parent_driver->eventQueue->scheduleEvent(this, 1+(random() % 200));
}
DetermGETXGenerator::~DetermGETXGenerator()
@@ -70,13 +67,13 @@ void DetermGETXGenerator::wakeup()
// determine if this node is next for the GETX round robin request
if (m_status == DetermGETXGeneratorStatus_Thinking) {
- if (m_driver.isStoreReady(m_node)) {
+ if (parent_driver->isStoreReady(m_node)) {
pickAddress();
m_status = DetermGETXGeneratorStatus_Store_Pending; // Store Pending
- m_last_transition = g_eventQueue_ptr->getTime();
+ m_last_transition = parent_driver->eventQueue->getTime();
initiateStore(); // GETX
} else { // I'll check again later
- g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+ parent_driver->eventQueue->scheduleEvent(this, thinkTime());
}
} else {
WARN_EXPR(m_status);
@@ -85,31 +82,28 @@ void DetermGETXGenerator::wakeup()
}
-void DetermGETXGenerator::performCallback(NodeID proc, SubBlock& data)
+void DetermGETXGenerator::performCallback(NodeID proc, Address address)
{
- Address address = data.getAddress();
assert(proc == m_node);
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);
if (m_status == DetermGETXGeneratorStatus_Store_Pending) {
- m_driver.recordStoreLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- data.writeByte(m_node);
- m_driver.storeCompleted(m_node, data.getAddress()); // advance the store queue
+ parent_driver->recordStoreLatency(parent_driver->eventQueue->getTime() - m_last_transition);
+ parent_driver->storeCompleted(m_node, address); // advance the store queue
m_counter++;
- if (m_counter < g_tester_length) {
+ if (m_counter < parent_driver->m_tester_length) {
m_status = DetermGETXGeneratorStatus_Thinking;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
+ m_last_transition = parent_driver->eventQueue->getTime();
+ parent_driver->eventQueue->scheduleEvent(this, waitTime());
} else {
- m_driver.reportDone();
+ parent_driver->reportDone();
m_status = DetermGETXGeneratorStatus_Done;
- m_last_transition = g_eventQueue_ptr->getTime();
+ m_last_transition = parent_driver->eventQueue->getTime();
}
} else {
@@ -120,38 +114,40 @@ void DetermGETXGenerator::performCallback(NodeID proc, SubBlock& data)
int DetermGETXGenerator::thinkTime() const
{
- return g_think_time;
+ return parent_driver->m_think_time;
}
int DetermGETXGenerator::waitTime() const
{
- return g_wait_time;
+ return parent_driver->m_wait_time;
}
void DetermGETXGenerator::pickAddress()
{
assert(m_status == DetermGETXGeneratorStatus_Thinking);
- m_address = m_driver.getNextStoreAddr(m_node);
+ m_address = parent_driver->getNextStoreAddr(m_node);
}
void DetermGETXGenerator::initiateStore()
{
DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Store");
- Addr data_addr = m_address.getAddress();
- Request request(0, data_addr, 1, Flags<unsigned int>(), 3, 0, 0);
- MemCmd::Command command;
- command = MemCmd::WriteReq;
+ uint8_t *write_data = new uint8_t[64];
+ for(int i=0; i < 64; i++) {
+ write_data[i] = m_node;
+ }
+
+ char name [] = "Sequencer_";
+ char port_name [13];
+ sprintf(port_name, "%s%d", name, m_node);
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+ int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_ST, RubyAccessMode_Supervisor));
- sequencer()->makeRequest(&pkt);
-}
+ // delete [] write_data;
-Sequencer* DetermGETXGenerator::sequencer() const
-{
- return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
+ ASSERT(parent_driver->requests.find(request_id) == parent_driver->requests.end());
+ parent_driver->requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
}
void DetermGETXGenerator::print(ostream& out) const
diff --git a/src/mem/ruby/tester/DetermGETXGenerator.hh b/src/mem/ruby/tester/DetermGETXGenerator.hh
index 1f5b67653..82e616e4b 100644
--- a/src/mem/ruby/tester/DetermGETXGenerator.hh
+++ b/src/mem/ruby/tester/DetermGETXGenerator.hh
@@ -40,28 +40,26 @@
#ifndef DETERMGETXGENERATOR_H
#define DETERMGETXGENERATOR_H
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/protocol/DetermGETXGeneratorStatus.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
+#include "Address_Tester.hh"
#include "mem/ruby/tester/SpecifiedGenerator.hh"
-class Sequencer;
-class SubBlock;
class DeterministicDriver;
+class DMAController;
class DetermGETXGenerator : public SpecifiedGenerator {
public:
// Constructors
- DetermGETXGenerator(NodeID node, DeterministicDriver& driver);
+ DetermGETXGenerator(NodeID node, DeterministicDriver * driver);
// Destructor
~DetermGETXGenerator();
// Public Methods
void wakeup();
- void performCallback(NodeID proc, SubBlock& data);
+ void performCallback(NodeID proc, Address address);
void print(ostream& out) const;
private:
@@ -69,20 +67,21 @@ private:
int thinkTime() const;
int waitTime() const;
void initiateStore();
+ void initiateDMA();
void pickAddress();
- Sequencer* sequencer() const;
+ DMAController* dma() const;
// copy constructor and assignment operator
DetermGETXGenerator(const DetermGETXGenerator& obj);
DetermGETXGenerator& operator=(const DetermGETXGenerator& obj);
+ DeterministicDriver * parent_driver;
// Data Members (m_ prefix)
DetermGETXGeneratorStatus m_status;
int m_counter;
Address m_address;
NodeID m_node;
- DeterministicDriver& m_driver;
Time m_last_transition;
};
diff --git a/src/mem/ruby/tester/DetermInvGenerator.cc b/src/mem/ruby/tester/DetermInvGenerator.cc
index bafaa18ae..eebe18057 100644
--- a/src/mem/ruby/tester/DetermInvGenerator.cc
+++ b/src/mem/ruby/tester/DetermInvGenerator.cc
@@ -38,13 +38,10 @@
#include "mem/ruby/tester/DetermInvGenerator.hh"
#include "mem/protocol/DetermInvGeneratorStatus.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/DeterministicDriver.hh"
-#include "mem/protocol/Chip.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
+//#include "DMAController.hh"
+#include "mem/ruby/libruby.hh"
DetermInvGenerator::DetermInvGenerator(NodeID node, DeterministicDriver& driver) :
m_driver(driver)
@@ -54,9 +51,8 @@ DetermInvGenerator::DetermInvGenerator(NodeID node, DeterministicDriver& driver)
m_node = node;
m_address = Address(9999); // initiate to a NULL value
m_counter = 0;
-
// don't know exactly when this node needs to request so just guess randomly
- g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
+ m_driver.eventQueue->scheduleEvent(this, 1+(random() % 200));
}
DetermInvGenerator::~DetermInvGenerator()
@@ -74,23 +70,23 @@ void DetermInvGenerator::wakeup()
if (m_driver.isLoadReady(m_node) && m_counter == m_driver.getStoresCompleted()) {
pickLoadAddress();
m_status = DetermInvGeneratorStatus_Load_Pending; // Load Pending
- m_last_transition = g_eventQueue_ptr->getTime();
+ m_last_transition = m_driver.eventQueue->getTime();
initiateLoad(); // GETS
} else { // I'll check again later
- g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+ m_driver.eventQueue->scheduleEvent(this, thinkTime());
}
} else if (m_status == DetermInvGeneratorStatus_Load_Complete) {
if (m_driver.isStoreReady(m_node, m_address)) { // do a store in this transaction or start the next one
if (m_driver.isLoadReady((0), m_address)) { // everyone is in S for this address i.e. back to node 0
m_status = DetermInvGeneratorStatus_Store_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
+ m_last_transition = m_driver.eventQueue->getTime();
initiateStore(); // GETX
} else { // I'm next, I just have to wait for all loads to complete
- g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+ m_driver.eventQueue->scheduleEvent(this, thinkTime());
}
} else { // I'm not next to store, go back to thinking
m_status = DetermInvGeneratorStatus_Thinking;
- g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+ m_driver.eventQueue->scheduleEvent(this, thinkTime());
}
} else {
WARN_EXPR(m_status);
@@ -99,48 +95,48 @@ void DetermInvGenerator::wakeup()
}
-void DetermInvGenerator::performCallback(NodeID proc, SubBlock& data)
+void DetermInvGenerator::performCallback(NodeID proc, Address address)
{
- Address address = data.getAddress();
assert(proc == m_node);
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);
if (m_status == DetermInvGeneratorStatus_Load_Pending) {
- m_driver.recordLoadLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- m_driver.loadCompleted(m_node, data.getAddress());
+ m_driver.recordLoadLatency(m_driver.eventQueue->getTime() - m_last_transition);
+ //NodeID firstByte = data.readByte(); // dummy read
+
+ m_driver.loadCompleted(m_node, address);
if (!m_driver.isStoreReady(m_node, m_address)) { // if we don't have to store, we are done for this transaction
m_counter++;
}
- if (m_counter < g_tester_length) {
+ if (m_counter < m_driver.m_tester_length) {
m_status = DetermInvGeneratorStatus_Load_Complete;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
+ m_last_transition = m_driver.eventQueue->getTime();
+ m_driver.eventQueue->scheduleEvent(this, waitTime());
} else {
m_driver.reportDone();
m_status = DetermInvGeneratorStatus_Done;
- m_last_transition = g_eventQueue_ptr->getTime();
+ m_last_transition = m_driver.eventQueue->getTime();
}
} else if (m_status == DetermInvGeneratorStatus_Store_Pending) {
- m_driver.recordStoreLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- data.writeByte(m_node);
- m_driver.storeCompleted(m_node, data.getAddress()); // advance the store queue
+ m_driver.recordStoreLatency(m_driver.eventQueue->getTime() - m_last_transition);
+ //data.writeByte(m_node);
+ m_driver.storeCompleted(m_node, address); // advance the store queue
m_counter++;
- if (m_counter < g_tester_length) {
+ if (m_counter < m_driver.m_tester_length) {
m_status = DetermInvGeneratorStatus_Thinking;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
+ m_last_transition = m_driver.eventQueue->getTime();
+ m_driver.eventQueue->scheduleEvent(this, waitTime());
} else {
m_driver.reportDone();
m_status = DetermInvGeneratorStatus_Done;
- m_last_transition = g_eventQueue_ptr->getTime();
+ m_last_transition = m_driver.eventQueue->getTime();
}
} else {
WARN_EXPR(m_status);
@@ -150,23 +146,22 @@ void DetermInvGenerator::performCallback(NodeID proc, SubBlock& data)
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);
}
int DetermInvGenerator::thinkTime() const
{
- return g_think_time;
+ return m_driver.m_think_time;
}
int DetermInvGenerator::waitTime() const
{
- return g_wait_time;
+ return m_driver.m_wait_time;
}
int DetermInvGenerator::holdTime() const
{
- return g_hold_time;
+ assert(0);
}
void DetermInvGenerator::pickLoadAddress()
@@ -179,35 +174,42 @@ void DetermInvGenerator::pickLoadAddress()
void DetermInvGenerator::initiateLoad()
{
DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Load");
+ // sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_LD, Address(1), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */));
+ uint8_t * read_data = new uint8_t[64];
- Addr data_addr = m_address.getAddress();
- Request request(0, data_addr, 1, Flags<unsigned int>(), 1, 0, 0);
- MemCmd::Command command;
- command = MemCmd::ReadReq;
+ char name [] = "Sequencer_";
+ char port_name [13];
+ sprintf(port_name, "%s%d", name, m_node);
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+ int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), read_data, 64, 0, RubyRequestType_LD, RubyAccessMode_Supervisor));
- sequencer()->makeRequest(&pkt);
+ //delete [] read_data;
+
+ ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+ m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
}
void DetermInvGenerator::initiateStore()
{
DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Store");
+ // sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */));
+ uint8_t *write_data = new uint8_t[64];
+ for(int i=0; i < 64; i++) {
+ write_data[i] = m_node;
+ }
- Addr data_addr = m_address.getAddress();
- Request request(0, data_addr, 1, Flags<unsigned int>(), 3, 0, 0);
- MemCmd::Command command;
- command = MemCmd::WriteReq;
+ char name [] = "Sequencer_";
+ char port_name [13];
+ sprintf(port_name, "%s%d", name, m_node);
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+ int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_ST, RubyAccessMode_Supervisor));
- sequencer()->makeRequest(&pkt);
-}
+ //delete [] write_data;
+
+ ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+ m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
-Sequencer* DetermInvGenerator::sequencer() const
-{
- return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
}
void DetermInvGenerator::print(ostream& out) const
diff --git a/src/mem/ruby/tester/DetermInvGenerator.hh b/src/mem/ruby/tester/DetermInvGenerator.hh
index 4f0712fbe..6127c3af4 100644
--- a/src/mem/ruby/tester/DetermInvGenerator.hh
+++ b/src/mem/ruby/tester/DetermInvGenerator.hh
@@ -41,15 +41,12 @@
#ifndef DETERMINVGENERATOR_H
#define DETERMINVGENERATOR_H
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/protocol/DetermInvGeneratorStatus.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
+#include "Address_Tester.hh"
#include "mem/ruby/tester/SpecifiedGenerator.hh"
-class Sequencer;
-class SubBlock;
class DeterministicDriver;
class DetermInvGenerator : public SpecifiedGenerator {
@@ -62,7 +59,7 @@ public:
// Public Methods
void wakeup();
- void performCallback(NodeID proc, SubBlock& data);
+ void performCallback(NodeID proc, Address address);
void print(ostream& out) const;
private:
@@ -75,8 +72,6 @@ private:
void pickLoadAddress();
void pickStoreAddress();
- Sequencer* sequencer() const;
-
// copy constructor and assignment operator
DetermInvGenerator(const DetermInvGenerator& obj);
DetermInvGenerator& operator=(const DetermInvGenerator& obj);
diff --git a/src/mem/ruby/tester/DetermSeriesGETSGenerator.cc b/src/mem/ruby/tester/DetermSeriesGETSGenerator.cc
index 5adc7aa5c..38688f10d 100644
--- a/src/mem/ruby/tester/DetermSeriesGETSGenerator.cc
+++ b/src/mem/ruby/tester/DetermSeriesGETSGenerator.cc
@@ -34,13 +34,7 @@
#include "mem/ruby/tester/DetermSeriesGETSGenerator.hh"
#include "mem/protocol/DetermSeriesGETSGeneratorStatus.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/DeterministicDriver.hh"
-#include "mem/protocol/Chip.hh"
DetermSeriesGETSGenerator::DetermSeriesGETSGenerator(NodeID node, DeterministicDriver& driver) :
m_driver(driver)
@@ -51,8 +45,9 @@ DetermSeriesGETSGenerator::DetermSeriesGETSGenerator(NodeID node, DeterministicD
m_address = Address(9999); // initialize to null value
m_counter = 0;
+
// don't know exactly when this node needs to request so just guess randomly
- g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
+ m_driver.eventQueue->scheduleEvent(this, 1+(random() % 200));
}
DetermSeriesGETSGenerator::~DetermSeriesGETSGenerator()
@@ -69,10 +64,10 @@ void DetermSeriesGETSGenerator::wakeup()
if (m_driver.isLoadReady(m_node)) {
pickAddress();
m_status = DetermSeriesGETSGeneratorStatus_Load_Pending; // Load Pending
- m_last_transition = g_eventQueue_ptr->getTime();
+ m_last_transition = m_driver.eventQueue->getTime();
initiateLoad(); // SeriesGETS
} else { // I'll check again later
- g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+ m_driver.eventQueue->scheduleEvent(this, thinkTime());
}
} else {
WARN_EXPR(m_status);
@@ -81,32 +76,30 @@ void DetermSeriesGETSGenerator::wakeup()
}
-void DetermSeriesGETSGenerator::performCallback(NodeID proc, SubBlock& data)
+void DetermSeriesGETSGenerator::performCallback(NodeID proc, Address address)
{
- Address address = data.getAddress();
assert(proc == m_node);
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);
if (m_status == DetermSeriesGETSGeneratorStatus_Load_Pending) {
- m_driver.recordLoadLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- data.writeByte(m_node);
- m_driver.loadCompleted(m_node, data.getAddress()); // advance the load queue
+ m_driver.recordLoadLatency(m_driver.eventQueue->getTime() - m_last_transition);
+ //data.writeByte(m_node);
+ m_driver.loadCompleted(m_node, address); // advance the load queue
m_counter++;
// do we still have more requests to complete before the next proc starts?
- if (m_counter < g_tester_length*g_NUM_COMPLETIONS_BEFORE_PASS) {
+ if (m_counter < m_driver.m_tester_length*m_driver.m_numCompletionsPerNode) {
m_status = DetermSeriesGETSGeneratorStatus_Thinking;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
+ m_last_transition = m_driver.eventQueue->getTime();
+ m_driver.eventQueue->scheduleEvent(this, waitTime());
} else {
m_driver.reportDone();
m_status = DetermSeriesGETSGeneratorStatus_Done;
- m_last_transition = g_eventQueue_ptr->getTime();
+ m_last_transition = m_driver.eventQueue->getTime();
}
} else {
@@ -117,12 +110,12 @@ void DetermSeriesGETSGenerator::performCallback(NodeID proc, SubBlock& data)
int DetermSeriesGETSGenerator::thinkTime() const
{
- return g_think_time;
+ return m_driver.m_think_time;
}
int DetermSeriesGETSGenerator::waitTime() const
{
- return g_wait_time;
+ return m_driver.m_wait_time;
}
void DetermSeriesGETSGenerator::pickAddress()
@@ -135,21 +128,20 @@ void DetermSeriesGETSGenerator::pickAddress()
void DetermSeriesGETSGenerator::initiateLoad()
{
DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Load");
+ //sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_IFETCH, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */));
- Addr data_addr = m_address.getAddress();
- Request request(0, data_addr, 1, Flags<unsigned int>(), 3, 0, 0);
- MemCmd::Command command;
- command = MemCmd::ReadReq;
- request.setFlags(Request::INST_FETCH);
+ uint8_t *read_data = new uint8_t[64];
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+ char name [] = "Sequencer_";
+ char port_name [13];
+ sprintf(port_name, "%s%d", name, m_node);
- sequencer()->makeRequest(&pkt);
-}
+ int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), read_data, 64, 0, RubyRequestType_LD, RubyAccessMode_Supervisor));
-Sequencer* DetermSeriesGETSGenerator::sequencer() const
-{
- return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
+ //delete [] read_data;
+
+ ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+ m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
}
void DetermSeriesGETSGenerator::print(ostream& out) const
diff --git a/src/mem/ruby/tester/DetermSeriesGETSGenerator.hh b/src/mem/ruby/tester/DetermSeriesGETSGenerator.hh
index 1e44dc3bc..225e45a11 100644
--- a/src/mem/ruby/tester/DetermSeriesGETSGenerator.hh
+++ b/src/mem/ruby/tester/DetermSeriesGETSGenerator.hh
@@ -42,15 +42,12 @@
#ifndef DETERMSERIESGETSGENERATOR_H
#define DETERMSERIESGETSGENERATOR_H
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/protocol/DetermSeriesGETSGeneratorStatus.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
+#include "Address_Tester.hh"
#include "mem/ruby/tester/SpecifiedGenerator.hh"
-class Sequencer;
-class SubBlock;
class DeterministicDriver;
class DetermSeriesGETSGenerator : public SpecifiedGenerator {
@@ -63,7 +60,7 @@ public:
// Public Methods
void wakeup();
- void performCallback(NodeID proc, SubBlock& data);
+ void performCallback(NodeID proc, Address address);
void print(ostream& out) const;
private:
@@ -73,8 +70,6 @@ private:
void initiateLoad();
void pickAddress();
- Sequencer* sequencer() const;
-
// copy constructor and assignment operator
DetermSeriesGETSGenerator(const DetermSeriesGETSGenerator& obj);
DetermSeriesGETSGenerator& operator=(const DetermSeriesGETSGenerator& obj);
diff --git a/src/mem/ruby/tester/DeterministicDriver.cc b/src/mem/ruby/tester/DeterministicDriver.cc
index 762672118..54b5f5e0d 100644
--- a/src/mem/ruby/tester/DeterministicDriver.cc
+++ b/src/mem/ruby/tester/DeterministicDriver.cc
@@ -32,67 +32,79 @@
*
*/
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/System.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
#include "mem/ruby/tester/DeterministicDriver.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/tester/SpecifiedGenerator.hh"
+#include "mem/ruby/tester/EventQueue_Tester.hh"
+//#include "DMAGenerator.hh"
#include "mem/ruby/tester/DetermGETXGenerator.hh"
-#include "mem/ruby/tester/DetermInvGenerator.hh"
-#include "mem/ruby/tester/DetermSeriesGETSGenerator.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/protocol/Chip.hh"
-#include "mem/packet.hh"
-DeterministicDriver::DeterministicDriver(RubySystem* sys_ptr)
+#define DATA_BLOCK_BYTES 64
+
+DeterministicDriver::DeterministicDriver(string generator_type, int num_completions, int num_procs, Time g_think_time, Time g_wait_time, int g_tester_length)
{
+ eventQueue = new RubyEventQueue;
m_finish_time = 0;
m_last_issue = -11;
m_done_counter = 0;
m_loads_completed = 0;
m_stores_completed = 0;
- m_numCompletionsPerNode = g_NUM_COMPLETIONS_BEFORE_PASS;
+ m_numCompletionsPerNode = num_completions;
+ m_num_procs = num_procs;
+ m_think_time = g_think_time;
+ m_wait_time = g_wait_time;
+ m_tester_length = g_tester_length;
+
- m_last_progress_vector.setSize(RubyConfig::numberOfProcessors());
+ m_last_progress_vector.setSize(num_procs);
for (int i=0; i<m_last_progress_vector.size(); i++) {
m_last_progress_vector[i] = 0;
}
- m_load_vector.setSize(g_deterministic_addrs);
+ m_load_vector.setSize(10);
for (int i=0; i<m_load_vector.size(); i++) {
m_load_vector[i] = -1; // No processor last held it
}
- m_store_vector.setSize(g_deterministic_addrs);
+ m_store_vector.setSize(10);
for (int i=0; i<m_store_vector.size(); i++) {
m_store_vector[i] = -1; // No processor last held it
}
- m_generator_vector.setSize(RubyConfig::numberOfProcessors());
+ m_generator_vector.setSize(num_procs);
- SpecifiedGeneratorType generator = string_to_SpecifiedGeneratorType(g_SpecifiedGenerator);
+ int generator = string_to_SpecifiedGeneratorType(generator_type);
for (int i=0; i<m_generator_vector.size(); i++) {
switch (generator) {
case SpecifiedGeneratorType_DetermGETXGenerator:
- m_generator_vector[i] = new DetermGETXGenerator(i, *this);
- break;
- case SpecifiedGeneratorType_DetermSeriesGETSGenerator:
- m_generator_vector[i] = new DetermSeriesGETSGenerator(i, *this);
+ m_generator_vector[i] = new DetermGETXGenerator(i, this);
break;
case SpecifiedGeneratorType_DetermInvGenerator:
m_generator_vector[i] = new DetermInvGenerator(i, *this);
break;
+ case SpecifiedGeneratorType_DetermSeriesGETSGenerator:
+ m_generator_vector[i] = new DetermSeriesGETSGenerator(i, *this);
+ break;
default:
ERROR_MSG("Unexpected specified generator type");
}
}
- // add the tester consumer to the global event queue
- g_eventQueue_ptr->scheduleEvent(this, 1);
+ //m_dma_generator = new DMAGenerator(0, this);
}
+
+void DeterministicDriver::go()
+{
+ // tick both queues until everyone is done
+ while (m_done_counter != m_num_procs) {
+ libruby_tick(1);
+ eventQueue->triggerEvents(eventQueue->getTime() + 1);
+ }
+}
+
+
DeterministicDriver::~DeterministicDriver()
{
for (int i=0; i<m_last_progress_vector.size(); i++) {
@@ -100,18 +112,27 @@ DeterministicDriver::~DeterministicDriver()
}
}
-void
-DeterministicDriver::hitCallback(Packet * pkt)
+//void DeterministicDriver::dmaHitCallback()
+//{
+// m_dma_generator->performCallback();
+//}
+
+void DeterministicDriver::wakeup() {
+ assert(0);
+ // this shouldn't be called as we are not scheduling the driver ever
+}
+
+void DeterministicDriver::hitCallback(int64_t request_id)
{
- NodeID proc = pkt->req->contextId();
- SubBlock data(Address(pkt->getAddr()), pkt->req->getSize());
- if (pkt->hasData()) {
- for (int i = 0; i < pkt->req->getSize(); i++) {
- data.setByte(i, *(pkt->getPtr<uint8>()+i));
- }
- }
- m_generator_vector[proc]->performCallback(proc, data);
- m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
+ ASSERT(requests.find(request_id) != requests.end());
+ int proc = requests[request_id].first;
+ Address address = requests[request_id].second;
+
+ m_generator_vector[proc]->performCallback(proc, address);
+
+ m_last_progress_vector[proc] = eventQueue->getTime();
+
+ requests.erase(request_id);
}
bool DeterministicDriver::isStoreReady(NodeID node)
@@ -121,6 +142,8 @@ bool DeterministicDriver::isStoreReady(NodeID node)
bool DeterministicDriver::isStoreReady(NodeID node, Address addr)
{
+ int addr_number = addr.getAddress()/DATA_BLOCK_BYTES;
+
return isAddrReady(node, m_store_vector, addr);
}
@@ -138,25 +161,26 @@ bool DeterministicDriver::isLoadReady(NodeID node, Address addr)
bool DeterministicDriver::isAddrReady(NodeID node, Vector<NodeID> addr_vector)
{
for (int i=0; i<addr_vector.size(); i++) {
- if (((addr_vector[i]+1)%RubyConfig::numberOfProcessors() == node) &&
+ if (((addr_vector[i]+1)%m_num_procs == node) &&
(m_loads_completed+m_stores_completed >= m_numCompletionsPerNode*node) && // is this node next
- (g_eventQueue_ptr->getTime() >= m_last_issue + 10)) { // controll rate of requests
+ (eventQueue->getTime() >= m_last_issue + 10)) { // controll rate of requests
return true;
}
}
+
return false;
}
// test for a particular addr
bool DeterministicDriver::isAddrReady(NodeID node, Vector<NodeID> addr_vector, Address addr)
{
- int addr_number = addr.getAddress()/RubyConfig::dataBlockBytes();
+ int addr_number = addr.getAddress()/DATA_BLOCK_BYTES;
ASSERT ((addr_number >= 0) && (addr_number < addr_vector.size()));
- if (((addr_vector[addr_number]+1)%RubyConfig::numberOfProcessors() == node) &&
+ if (((addr_vector[addr_number]+1)%m_num_procs == node) &&
(m_loads_completed+m_stores_completed >= m_numCompletionsPerNode*node) && // is this node next
- (g_eventQueue_ptr->getTime() >= m_last_issue + 10)) { // controll rate of requests
+ (eventQueue->getTime() >= m_last_issue + 10)) { // controll rate of requests
return true;
} else {
return false;
@@ -178,7 +202,7 @@ void DeterministicDriver::storeCompleted(NodeID node, Address addr)
void DeterministicDriver::setNextAddr(NodeID node, Address addr, Vector<NodeID>& addr_vector)
{
// mark the addr vector that this proc was the last to use the particular address
- int addr_number = addr.getAddress()/RubyConfig::dataBlockBytes();
+ int addr_number = addr.getAddress()/DATA_BLOCK_BYTES;
addr_vector[addr_number] = node;
}
@@ -204,17 +228,16 @@ Address DeterministicDriver::getNextAddr(NodeID node, Vector<NodeID> addr_vector
ASSERT(isAddrReady(node, addr_vector));
for (int addr_number=0; addr_number<addr_vector.size(); addr_number++) {
- //for (int addr_number=addr_vector.size()-1; addr_number>0; addr_number--) {
// is this node next in line for the addr
- if (((addr_vector[addr_number]+1)%RubyConfig::numberOfProcessors()) == node) {
+ if ((addr_vector[addr_number] != 1) && ((addr_vector[addr_number]+1)%m_num_procs) == node) {
// One addr per cache line
- addr.setAddress(addr_number * RubyConfig::dataBlockBytes());
+ addr.setAddress(addr_number * DATA_BLOCK_BYTES);
}
}
- m_last_issue = g_eventQueue_ptr->getTime();
+ m_last_issue = eventQueue->getTime();
return addr;
}
@@ -223,9 +246,9 @@ Address DeterministicDriver::getNextAddr(NodeID node, Vector<NodeID> addr_vector
void DeterministicDriver::reportDone()
{
m_done_counter++;
- if ((m_done_counter == RubyConfig::numberOfProcessors())) {
- //|| (m_done_counter == g_tester_length)) {
- m_finish_time = g_eventQueue_ptr->getTime();
+ if ((m_done_counter == m_num_procs)) {
+ m_finish_time = eventQueue->getTime();
+ //m_dma_generator->stop();
}
}
@@ -239,36 +262,6 @@ void DeterministicDriver::recordStoreLatency(Time time)
m_store_latency.add(time);
}
-void DeterministicDriver::wakeup()
-{
- // checkForDeadlock();
- if (m_done_counter < RubyConfig::numberOfProcessors()) {
- g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
- }
-}
-
-void DeterministicDriver::checkForDeadlock()
-{
- int size = m_last_progress_vector.size();
- Time current_time = g_eventQueue_ptr->getTime();
- for (int processor=0; processor<size; processor++) {
- if ((current_time - m_last_progress_vector[processor]) > g_DEADLOCK_THRESHOLD) {
- WARN_EXPR(processor);
-#ifndef NDEBUG
- Sequencer* seq_ptr = g_system_ptr->getChip(processor/RubyConfig::numberOfProcsPerChip())->getSequencer(processor%RubyConfig::numberOfProcsPerChip());
-#endif
- assert(seq_ptr != NULL);
- // if (seq_ptr->isRequestPending()) {
- // WARN_EXPR(seq_ptr->pendingAddress());
- // }
- WARN_EXPR(current_time);
- WARN_EXPR(m_last_progress_vector[processor]);
- WARN_EXPR(current_time - m_last_progress_vector[processor]);
- ERROR_MSG("Deadlock detected.");
- }
- }
-}
-
void DeterministicDriver::printStats(ostream& out) const
{
out << endl;
diff --git a/src/mem/ruby/tester/DeterministicDriver.hh b/src/mem/ruby/tester/DeterministicDriver.hh
index 710da7922..288ad5a15 100644
--- a/src/mem/ruby/tester/DeterministicDriver.hh
+++ b/src/mem/ruby/tester/DeterministicDriver.hh
@@ -36,25 +36,35 @@
#ifndef DETERMINISTICDRIVER_H
#define DETERMINISTICDRIVER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/ruby/common/Histogram.hh"
-#include "mem/protocol/CacheRequestType.hh"
-
-class RubySystem;
-class SpecifiedGenerator;
-class Packet;
-
-class DeterministicDriver : public Driver, public Consumer {
+#include <map>
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/common/Histogram.hh" // includes global, but doesn't use anything, so it should be fine
+#include "mem/protocol/CacheRequestType.hh" // includes global, but doesn't use anything, so it should be fine
+#include "Address_Tester.hh" // we redefined the address
+#include "mem/ruby/tester/DetermGETXGenerator.hh" // this is our file
+#include "mem/ruby/tester/DetermSeriesGETSGenerator.hh" // this is our file
+#include "mem/ruby/tester/DetermInvGenerator.hh" // this is our file
+#include "mem/ruby/libruby.hh"
+#include "mem/ruby/tester/Driver_Tester.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/tester/EventQueue_Tester.hh"
+#include "mem/protocol/SpecifiedGeneratorType.hh"
+
+//class DMAGenerator;
+
+class DeterministicDriver : public Driver_Tester, public Consumer {
public:
+ friend class DetermGETXGenerator;
+ friend class DetermSeriesGETSGenerator;
+ friend class DetermInvGenerator;
// Constructors
- DeterministicDriver(RubySystem* sys_ptr);
+ DeterministicDriver(string generator_type, int num_completions, int num_procs, Time g_think_time, Time g_wait_time, int g_tester_length);
// Destructor
~DeterministicDriver();
// Public Methods
+ void go();
bool isStoreReady(NodeID node);
bool isLoadReady(NodeID node);
bool isStoreReady(NodeID node, Address addr);
@@ -70,37 +80,47 @@ public:
void recordLoadLatency(Time time);
void recordStoreLatency(Time time);
- void hitCallback(Packet* pkt);
+// void dmaHitCallback();
+ void hitCallback(int64_t request_id);
void wakeup();
void printStats(ostream& out) const;
void clearStats() {}
void printConfig(ostream& out) const {}
void print(ostream& out) const;
+ // Public copy constructor and assignment operator
+ DeterministicDriver(const DeterministicDriver& obj);
+ DeterministicDriver& operator=(const DeterministicDriver& obj);
+
private:
// Private Methods
- void checkForDeadlock();
Address getNextAddr(NodeID node, Vector<NodeID> addr_vector);
bool isAddrReady(NodeID node, Vector<NodeID> addr_vector);
bool isAddrReady(NodeID node, Vector<NodeID> addr_vector, Address addr);
void setNextAddr(NodeID node, Address addr, Vector<NodeID>& addr_vector);
- // Private copy constructor and assignment operator
- DeterministicDriver(const DeterministicDriver& obj);
- DeterministicDriver& operator=(const DeterministicDriver& obj);
// Data Members (m_ prefix)
Vector<Time> m_last_progress_vector;
Vector<SpecifiedGenerator*> m_generator_vector;
+ //DMAGenerator* m_dma_generator;
Vector<NodeID> m_load_vector; // Processor last to load the addr
Vector<NodeID> m_store_vector; // Processor last to store the addr
+ int last_proc;
int m_done_counter;
int m_loads_completed;
int m_stores_completed;
// enforces the previous node to have a certain # of completions
// before next node starts
+
+ map <int64_t, pair <int, Address> > requests;
+ Time m_think_time;
+ Time m_wait_time;
+ int m_tester_length;
+ int m_num_procs;
+ RubyEventQueue * eventQueue;
int m_numCompletionsPerNode;
Histogram m_load_latency;
diff --git a/src/mem/ruby/tester/CheckTable.hh b/src/mem/ruby/tester/Driver_Tester.cc
index a7f486315..d29e6f988 100644
--- a/src/mem/ruby/tester/CheckTable.hh
+++ b/src/mem/ruby/tester/Driver_Tester.cc
@@ -30,64 +30,15 @@
/*
* $Id$
*
- * Description:
+ * Description: See Driver_Tester.hh
*
*/
-#ifndef CHECKTABLE_H
-#define CHECKTABLE_H
+#include "mem/ruby/tester/Driver_Tester.hh"
-#include "mem/ruby/common/Global.hh"
-#include "mem/gems_common/Vector.hh"
-
-class Address;
-class Check;
-template <class KEY_TYPE, class VALUE_TYPE> class Map;
-
-class CheckTable {
-public:
- // Constructors
- CheckTable();
-
- // Destructor
- ~CheckTable();
-
- // Public Methods
-
- Check* getRandomCheck();
- Check* getCheck(const Address& address);
-
- // bool isPresent(const Address& address) const;
- // void removeCheckFromTable(const Address& address);
- // bool isTableFull() const;
- // Need a method to select a check or retrieve a check
-
- void print(ostream& out) const;
-private:
- // Private Methods
- void addCheck(const Address& address);
-
- // Private copy constructor and assignment operator
- CheckTable(const CheckTable& obj);
- CheckTable& operator=(const CheckTable& obj);
-
- // Data Members (m_ prefix)
- Vector<Check*> m_check_vector;
- Map<Address, Check*>* m_lookup_map_ptr;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const CheckTable& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const CheckTable& obj)
-{
- obj.print(out);
- out << flush;
- return out;
+Driver_Tester::Driver_Tester() {
}
-#endif //CHECKTABLE_H
+// still need to be defined for subclasses
+Driver_Tester::~Driver_Tester() {
+}
diff --git a/src/mem/ruby/tester/Tester.hh b/src/mem/ruby/tester/Driver_Tester.hh
index 7b721e038..77cd4ed3c 100644
--- a/src/mem/ruby/tester/Tester.hh
+++ b/src/mem/ruby/tester/Driver_Tester.hh
@@ -34,60 +34,49 @@
*
*/
-#ifndef TESTER_H
-#define TESTER_H
+#ifndef Driver_Tester_H
+#define Driver_Tester_H
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/ruby/tester/CheckTable.hh"
-#include "mem/protocol/CacheRequestType.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/system/NodeID.hh"
+#include "Address_Tester.hh"
-class RubySystem;
-
-class Tester : public Driver, public Consumer {
+class Driver_Tester {
public:
// Constructors
- Tester(RubySystem* sys_ptr);
+ Driver_Tester();
// Destructor
- ~Tester();
+ virtual ~Driver_Tester() = 0;
// Public Methods
+ virtual void get_network_config() {}
+ virtual void dmaHitCallback() {};
+ virtual void hitCallback(int64_t id) = 0;
+ virtual void go() = 0;
+ virtual integer_t getInstructionCount(int procID) const { return 1; }
+ virtual integer_t getCycleCount(int procID) const { return 1; }
+ virtual void addThreadDependency(int procID, int requestor_thread, int conflict_thread) const { assert(0);}
+ virtual void printDebug(){}
- void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread);
- void wakeup();
- void printStats(ostream& out) const {}
- void clearStats() {}
- void printConfig(ostream& out) const {}
-
- void print(ostream& out) const;
-private:
- // Private Methods
+ virtual void printStats(ostream& out) const = 0;
+ virtual void clearStats() = 0;
- void checkForDeadlock();
+ virtual void printConfig(ostream& out) const = 0;
- // Private copy constructor and assignment operator
- Tester(const Tester& obj);
- Tester& operator=(const Tester& obj);
+ virtual integer_t readPhysicalMemory(int procID, physical_address_t address,
+ int len ){ ASSERT(0); return 0; }
- // Data Members (m_ prefix)
+ virtual void writePhysicalMemory( int procID, physical_address_t address,
+ integer_t value, int len ){ ASSERT(0); }
- CheckTable m_checkTable;
- Vector<Time> m_last_progress_vector;
-};
+protected:
+ // accessible by subclasses
-// Output operator declaration
-ostream& operator<<(ostream& out, const Tester& obj);
-
-// ******************* Definitions *******************
+private:
+ // inaccessible by subclasses
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const Tester& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
+};
-#endif //TESTER_H
+#endif //Driver_Tester_H
diff --git a/src/mem/ruby/tester/EventQueue_Tester.hh b/src/mem/ruby/tester/EventQueue_Tester.hh
new file mode 100644
index 000000000..fe600bb84
--- /dev/null
+++ b/src/mem/ruby/tester/EventQueue_Tester.hh
@@ -0,0 +1,118 @@
+
+/*
+ * 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.
+ */
+
+/*
+ * $Id$
+ *
+ * Description: The RubyEventQueue class implements an event queue which
+ * can be trigger events, allowing our simulation to be event driven.
+ *
+ * Currently, the only event we support is a Consumer being signaled
+ * by calling the consumer's wakeup() routine. Adding the event to
+ * the queue does not require a virtual function call, though calling
+ * wakeup() is a virtual function call.
+ *
+ * The method triggerEvents() is called with a global time. All
+ * events which are before or at this time are triggered in timestamp
+ * order. No ordering is enforced for events scheduled to occur at
+ * the same time. Events scheduled to wakeup the same consumer at the
+ * same time are combined into a single event.
+ *
+ * The method scheduleConsumerWakeup() is called with a global time
+ * and a consumer pointer. The event queue will call the wakeup()
+ * method of the consumer at the appropriate time.
+ *
+ * This implementation of RubyEventQueue uses a dynamically sized array
+ * managed as a heap. The algorithms used has O(lg n) for insert and
+ * O(lg n) for extract minimum element. (Based on chapter 7 of Cormen,
+ * Leiserson, and Rivest.) The array is dynamically sized and is
+ * automatically doubled in size when necessary.
+ *
+ */
+
+#ifndef EVENTQUEUE_H
+#define EVENTQUEUE_H
+
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/gems_common/Vector.hh"
+
+class Consumer;
+template <class TYPE> class PrioHeap;
+class RubyEventQueueNode;
+
+class RubyEventQueue {
+public:
+ // Constructors
+ RubyEventQueue();
+
+ // Destructor
+ ~RubyEventQueue();
+
+ // Public Methods
+
+ Time getTime() const { return m_globalTime; }
+ void scheduleEvent(Consumer* consumer, Time timeDelta) { scheduleEventAbsolute(consumer, timeDelta + m_globalTime); }
+ void scheduleEventAbsolute(Consumer* consumer, Time timeAbs);
+ void triggerEvents(Time t); // called to handle all events <= time t
+ void triggerAllEvents();
+ void print(ostream& out) const;
+ bool isEmpty() const;
+
+ Time getTimeOfLastRecovery() {return m_timeOfLastRecovery;}
+ void setTimeOfLastRecovery(Time t) {m_timeOfLastRecovery = t;}
+
+ // Private Methods
+private:
+ // Private copy constructor and assignment operator
+ void init();
+ RubyEventQueue(const RubyEventQueue& obj);
+ RubyEventQueue& operator=(const RubyEventQueue& obj);
+
+ // Data Members (m_ prefix)
+ PrioHeap<RubyEventQueueNode>* m_prio_heap_ptr;
+ Time m_globalTime;
+ Time m_timeOfLastRecovery;
+};
+
+// Output operator declaration
+inline extern
+ostream& operator<<(ostream& out, const RubyEventQueue& obj);
+
+// ******************* Definitions *******************
+
+// Output operator definition
+inline extern
+ostream& operator<<(ostream& out, const RubyEventQueue& obj)
+{
+ obj.print(out);
+ out << flush;
+ return out;
+}
+
+#endif //EVENTQUEUE_H
diff --git a/src/mem/ruby/tester/RequestGenerator.hh b/src/mem/ruby/tester/Global_Tester.hh
index 2859eb436..9d622bbf6 100644
--- a/src/mem/ruby/tester/RequestGenerator.hh
+++ b/src/mem/ruby/tester/Global_Tester.hh
@@ -30,73 +30,45 @@
/*
* $Id$
*
- * Description:
- *
- */
-
-#ifndef REQUESTGENERATOR_H
-#define REQUESTGENERATOR_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/protocol/RequestGeneratorStatus.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
-
-class Sequencer;
-class SubBlock;
-class SyntheticDriver;
-
-class RequestGenerator : public Consumer {
-public:
- // Constructors
- RequestGenerator(NodeID node, SyntheticDriver& driver);
-
- // Destructor
- ~RequestGenerator();
-
- // Public Methods
- void wakeup();
- void performCallback(NodeID proc, SubBlock& data);
-
- void print(ostream& out) const;
-private:
- // Private Methods
- int thinkTime() const;
- int waitTime() const;
- int holdTime() const;
- void initiateTest();
- void initiateSwap();
- void initiateRelease();
- void pickAddress();
- Sequencer* sequencer() const;
-
- // Private copy constructor and assignment operator
- RequestGenerator(const RequestGenerator& obj);
- RequestGenerator& operator=(const RequestGenerator& obj);
-
- // Data Members (m_ prefix)
- SyntheticDriver& m_driver;
- NodeID m_node;
- RequestGeneratorStatus m_status;
- int m_counter;
- Time m_last_transition;
- Address m_address;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const RequestGenerator& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const RequestGenerator& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-#endif //REQUESTGENERATOR_H
+ * */
+
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+
+typedef signed char int8;
+typedef int int32;
+typedef long long int64;
+
+typedef long long integer_t;
+typedef unsigned long long uinteger_t;
+
+typedef int64 Time;
+typedef uint64 physical_address_t;
+typedef uint64 la_t;
+typedef uint64 pa_t;
+typedef integer_t simtime_t;
+typedef int NodeID;
+
+#include "mem/ruby/common/TypeDefines.hh"
+#include "mem/gems_common/std-includes.hh"
+#include "Debug_Tester.hh"
+
+// simple type declarations
+typedef Time LogicalTime;
+typedef int64 Index; // what the address bit ripper returns
+typedef int word; // one word of a cache line
+typedef unsigned int uint;
+typedef int SwitchID;
+typedef int LinkID;
+
+
+class Debug;
+extern Debug * debug_ptr;
+class RubyEventQueue;
+extern RubyEventQueue * eventQueue;
+#endif //GLOBAL_H
diff --git a/src/mem/ruby/tester/Instruction.cc b/src/mem/ruby/tester/Instruction.cc
deleted file mode 100644
index 1f4d56fc2..000000000
--- a/src/mem/ruby/tester/Instruction.cc
+++ /dev/null
@@ -1,51 +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: Instruction.C 1.2 05/08/26 00:54:48-05:00 xu@s0-32.cs.wisc.edu $
- *
- * Description:
- *
- */
-
-#include "mem/ruby/tester/Instruction.hh"
-
-Instruction::Instruction(){
- m_opcode = Opcode_NUM_OPCODES;
- m_address = Address(physical_address_t(0));
-}
-
-Instruction::Instruction(Opcode op, Address addr){
- m_opcode = op;
- m_address = addr;
- assert(addr.getAddress() == 0);
-}
-
-void Instruction::init(Opcode op, Address addr){
- m_opcode = op;
- m_address = addr;
- //cout << "Instruction(" << op << ", " << m_address << ")" << endl;
-}
-
-Opcode Instruction::getOpcode(){
- return m_opcode;
-}
-
-Address Instruction::getAddress(){
- return m_address;
-}
diff --git a/src/mem/ruby/tester/Instruction.hh b/src/mem/ruby/tester/Instruction.hh
deleted file mode 100644
index 35791dcba..000000000
--- a/src/mem/ruby/tester/Instruction.hh
+++ /dev/null
@@ -1,57 +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: Instruction.hh 1.2 05/05/24 12:15:47-05:00 kmoore@balder.cs.wisc.edu $
- *
- * Description:
- *
- */
-
-#ifndef INSTRUCTION_H
-#define INSTRUCTION_H
-
-#include "mem/ruby/common/Address.hh"
-
-
-enum Opcode {
- Opcode_BEGIN,
- Opcode_LD,
- Opcode_ST,
- Opcode_INC,
- Opcode_COMMIT,
- Opcode_DONE,
- Opcode_NUM_OPCODES
-};
-
-class Instruction {
- public:
- Instruction();
- Instruction(Opcode op, Address addr);
-
- void init(Opcode op, Address addr);
- Opcode getOpcode();
- Address getAddress();
-
- private:
- Opcode m_opcode;
- Address m_address;
-
-};
-
-#endif
diff --git a/src/mem/ruby/tester/RaceyDriver.cc b/src/mem/ruby/tester/RaceyDriver.cc
index c56557645..dfecfa796 100644
--- a/src/mem/ruby/tester/RaceyDriver.cc
+++ b/src/mem/ruby/tester/RaceyDriver.cc
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,36 +32,31 @@
*
*/
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/System.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
#include "mem/ruby/tester/RaceyDriver.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "RaceyPseudoThread.hh"
-#include "mem/ruby/common/SubBlock.hh"
+#include "mem/ruby/tester/EventQueue_Tester.hh"
+#include "mem/ruby/tester/RaceyPseudoThread.hh"
-RaceyDriver::RaceyDriver()
+RaceyDriver::RaceyDriver(int num_procs, int tester_length)
{
- // debug transition?
- if(false) {
- assert(g_debug_ptr);
- g_debug_ptr->setDebugTime(1);
- }
-
m_finish_time = 0;
m_done_counter = 0;
m_wakeup_thread0 = false;
+ m_num_procs = num_procs;
+ m_tester_length = tester_length;
+ eventQueue = new RubyEventQueue;
// racey at least need two processors
- assert(RubyConfig::numberOfProcessors() >= 2);
+ assert(m_num_procs >= 2);
// init all racey pseudo threads
- m_racey_pseudo_threads.setSize(RubyConfig::numberOfProcessors());
+ m_racey_pseudo_threads.setSize(m_num_procs);
for (int i=0; i<m_racey_pseudo_threads.size(); i++) {
m_racey_pseudo_threads[i] = new RaceyPseudoThread(i, *this);
}
// add this driver to the global event queue, for deadlock detection
- g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
+ eventQueue->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
}
RaceyDriver::~RaceyDriver()
@@ -71,20 +66,38 @@ RaceyDriver::~RaceyDriver()
}
}
-void RaceyDriver::hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread)
+void RaceyDriver::go() {
+ // tick both queues until everyone is done
+ while (m_done_counter != m_num_procs) {
+ libruby_tick(1);
+ eventQueue->triggerEvents(eventQueue->getTime() + 1);
+ }
+}
+
+
+void RaceyDriver::hitCallback(int64_t request_id)
{
- DEBUG_EXPR(TESTER_COMP, MedPrio, data);
- m_racey_pseudo_threads[proc]->performCallback(proc, data);
+ ASSERT(requests.find(request_id) != requests.end());
+ int proc = requests[request_id].first;
+ Address address = requests[request_id].second.address;
+ uint8_t * data = new uint8_t[4];
+ for (int i = 0; i < 4; i++) {
+ data[i] = requests[request_id].second.data[i];
+ }
+ requests[request_id].second.data;
+ m_racey_pseudo_threads[proc]->performCallback(proc, address, data);
+ requests.erase(request_id);
}
integer_t RaceyDriver::getInstructionCount(int procID) const
{
- return m_racey_pseudo_threads[procID]->getInstructionCounter();
+ // return m_racey_pseudo_threads[procID]->getInstructionCounter();
+ assert(0);
}
int RaceyDriver::runningThreads()
{
- return RubyConfig::numberOfProcessors() - m_done_counter;
+ return m_num_procs - m_done_counter;
}
// used to wake up thread 0 whenever other thread finishes
@@ -96,12 +109,12 @@ void RaceyDriver::registerThread0Wakeup()
void RaceyDriver::joinThread()
{
m_done_counter++;
- if (m_done_counter == RubyConfig::numberOfProcessors()) {
- m_finish_time = g_eventQueue_ptr->getTime();
+ if (m_done_counter == m_num_procs) {
+ m_finish_time = eventQueue->getTime();
}
if(m_wakeup_thread0) {
- g_eventQueue_ptr->scheduleEvent(m_racey_pseudo_threads[0], 1);
+ eventQueue->scheduleEvent(m_racey_pseudo_threads[0], 1);
m_wakeup_thread0 = false;
}
}
@@ -114,14 +127,14 @@ void RaceyDriver::wakeup()
}
// schedule next wakeup
- if (m_done_counter < RubyConfig::numberOfProcessors()) {
- g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
+ if (m_done_counter < m_num_procs) {
+ eventQueue->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
}
}
void RaceyDriver::printStats(ostream& out) const
{
- assert(m_done_counter == RubyConfig::numberOfProcessors());
+ assert(m_done_counter == m_num_procs);
out << endl;
out << "RaceyDriver Stats" << endl;
out << "---------------------" << endl;
diff --git a/src/mem/ruby/tester/RaceyDriver.hh b/src/mem/ruby/tester/RaceyDriver.hh
index a3e35b47c..cc2130ef9 100644
--- a/src/mem/ruby/tester/RaceyDriver.hh
+++ b/src/mem/ruby/tester/RaceyDriver.hh
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,15 +38,25 @@
#ifndef RACEYDRIVER_H
#define RACEYDRIVER_H
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Driver.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/tester/Driver_Tester.hh"
+#include "mem/ruby/tester/RaceyPseudoThread.hh"
+#include <map>
+#include "mem/ruby/libruby.hh"
-class RaceyPseudoThread;
+#define g_DEADLOCK_THRESHOLD 5000
-class RaceyDriver : public Driver, public Consumer {
+
+struct address_data {
+ Address address;
+ uint8_t * data;
+};
+
+class RaceyDriver : public Driver_Tester, public Consumer {
public:
+ friend class RaceyPseudoThread;
// Constructors
- RaceyDriver();
+ RaceyDriver(int num_procs, int tester_length);
// Destructor
~RaceyDriver();
@@ -59,11 +69,12 @@ public:
return m_racey_pseudo_threads[0]->getInitializedState();
};
- void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread);
+ void hitCallback(int64_t request_id);
void wakeup();
void printStats(ostream& out) const;
void clearStats() {}
void printConfig(ostream& out) const {}
+ void go();
integer_t getInstructionCount(int procID) const;
@@ -81,6 +92,7 @@ public:
}
void print(ostream& out) const;
+
private:
// Private copy constructor and assignment operator
@@ -91,8 +103,11 @@ private:
Vector<RaceyPseudoThread*> m_racey_pseudo_threads;
int m_done_counter;
bool m_wakeup_thread0;
-
Time m_finish_time;
+ map <int64_t, pair <int, struct address_data> > requests;
+ RubyEventQueue * eventQueue;
+ int m_num_procs;
+ int m_tester_length;
};
// Output operator declaration
@@ -110,3 +125,4 @@ ostream& operator<<(ostream& out, const RaceyDriver& obj)
}
#endif //RACEYDRIVER_H
+
diff --git a/src/mem/ruby/tester/RaceyPseudoThread.cc b/src/mem/ruby/tester/RaceyPseudoThread.cc
new file mode 100644
index 000000000..e5e1c1169
--- /dev/null
+++ b/src/mem/ruby/tester/RaceyPseudoThread.cc
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 1999 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.
+ */
+
+/*
+ * Description: see RaceyPseudoThread.hh
+ */
+
+#include "mem/ruby/tester/RaceyPseudoThread.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/tester/RaceyDriver.hh"
+#include "gzstream.hh"
+
+RaceyPseudoThread::RaceyPseudoThread(NodeID id, RaceyDriver& driver)
+ : m_driver(driver), m_proc_id(id) {
+
+ resetIC(); // IC contains the committed instruction number
+ m_last_progress = 0;
+ m_done = false;
+ m_stop = 0;
+ m_driver.eventQueue->scheduleEvent(this, 1);
+}
+
+RaceyPseudoThread::~RaceyPseudoThread() {
+}
+
+void RaceyPseudoThread::checkForDeadlock() {
+ Time current_time = m_driver.eventQueue->getTime();
+ if(!m_done && (current_time - m_last_progress) > g_DEADLOCK_THRESHOLD) {
+ WARN_EXPR(m_proc_id);
+ WARN_EXPR(m_ic_counter);
+ WARN_EXPR(m_last_progress);
+ ERROR_MSG("Deadlock detected.");
+ }
+}
+
+void RaceyPseudoThread::performCallback(int proc, Address address, uint8_t * data ) {
+ assert(proc == m_proc_id);
+
+ DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
+ DEBUG_EXPR(TESTER_COMP, LowPrio, address);
+
+
+ m_last_progress = m_driver.eventQueue->getTime();
+
+ if(m_read) {
+ int b0, b1, b2, b3;
+ b0 = data[0]; b0 <<= 0;
+ b1 = data[1]; b1 <<= 8;
+ b2 = data[2]; b2 <<= 16;
+ b3 = data[3]; b3 <<= 24;
+ m_value = b0 | b1 | b2 | b3;
+ } else {
+ char b0, b1, b2, b3;
+ b0 = (m_value>>0)&0xFF; data[0] = b0;
+ b1 = (m_value>>8)&0xFF; data[1] = b1;
+ b2 = (m_value>>16)&0xFF; data[2] = b2;
+ b3 = (m_value>>24)&0xFF; data[3] = b3;
+ }
+
+ // schedule wakeup for next requests in next cycle
+ m_driver.eventQueue->scheduleEvent(this, 1);
+
+ // new instruction
+ m_ic_counter++;
+
+}
+
+void RaceyPseudoThread::wakeup() {
+ // for debug
+ if(m_stop != 0) {
+ cout << m_proc_id << " " << m_stop << ((m_read)? " read ":" written ") << m_value;
+ if(0) cout << " [" << m_driver.eventQueue->getTime() << "]";
+ cout << endl;
+ }
+
+ assert(!m_done);
+
+ // Note, this function can not have ANY local variable!
+
+ switch(m_stop) {
+ case 0:
+ break;
+ case 1:
+ goto L1;
+ case 2:
+ goto L2;
+ case 3:
+ goto L3;
+ case 4:
+ goto L4;
+ case 5:
+ goto L5;
+ case 6:
+ goto L6;
+ case 7:
+ goto L7;
+ case 8:
+ goto L8;
+ case 9:
+ goto L9;
+ case 10:
+ goto L10;
+ default:
+ WARN_EXPR(m_stop);
+ ERROR_MSG("RaceyPseudoThread: Bad context point!");
+ }
+
+ //
+ // initialization
+ //
+ if(m_proc_id == 0) {
+ for(m_looper = 0; m_looper < m_driver.m_num_procs; m_looper++) {
+ store_sig(m_looper, m_looper+1);
+ m_stop = 6; return;
+L6: {};
+ }
+ for(m_looper = 0; m_looper < M_ELEM; m_looper++) {
+ store_m(m_looper, M_ELEM-m_looper);
+ m_stop = 7; return;
+L7: {};
+ }
+
+ // init done
+ m_initialized = true;
+ } else {
+ // other processors
+ if(!m_driver.Thread0Initialized()) {
+ // wait for processors 0
+ m_driver.eventQueue->scheduleEvent(this, 1);
+ return;
+ }
+ }
+
+ cout << "Thread " << m_proc_id << " started in parallel phase" << endl;
+
+ //
+ // main thread body
+ //
+ for(m_looper = 0 ; m_looper < m_driver.m_tester_length; m_looper++) {
+ /* m_value = */ load_sig(m_proc_id);
+ m_stop = 1; return;
+L1: {};
+ m_num = m_value;
+ m_index1 = m_num%M_ELEM;
+ /* m_value = */ load_m(m_index1);
+ m_stop = 2; return;
+L2: {};
+ m_num = mix(m_num, m_value);
+ m_index2 = m_num%M_ELEM;
+ /* m_value = */ load_m(m_index2);
+ m_stop = 3; return;
+L3: {};
+ m_num = mix(m_num, m_value);
+ store_m(m_index2, m_num);
+ m_stop = 4; return;
+L4: {};
+ store_sig(m_proc_id, m_num);
+ m_stop = 5; return;
+L5: {};
+ } // end for
+
+ //
+ // compute final sig
+ //
+ if(m_proc_id == 0) {
+ // wait for other threads
+ while (m_driver.runningThreads() > 1) {
+ m_driver.registerThread0Wakeup();
+ m_stop = 10; return;
+L10: {};
+ }
+
+ /* m_value = */ load_sig(0);
+ m_stop = 8; return;
+L8: {};
+ m_final_sig = m_value;
+ for(m_looper = 1; m_looper < m_driver.m_num_procs; m_looper++) {
+ /* m_value = */ load_sig(m_looper);
+ m_stop = 9; return;
+L9: {};
+ m_final_sig = mix(m_value, m_final_sig);
+ }
+ } // processors 0
+
+ // done
+ m_driver.joinThread();
+ m_done = true;
+}
+
+void RaceyPseudoThread::load_sig(unsigned index) {
+ cout << m_proc_id << " : load_sig " << index << endl;
+
+ m_read = true;
+ // timestamp, threadid, action, and logical address are used only by transactional memory, should be augmented
+ uint8_t * read_data = new uint8_t[4];
+
+ char name [] = "Sequencer_";
+ char port_name [13];
+ sprintf(port_name, "%s%d", name, m_proc_id);
+
+ // pc is zero, problem?
+ int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(sig(index), read_data, 4, 0, RubyRequestType_LD, RubyAccessMode_User));
+
+ ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+
+ struct address_data request_data;
+ request_data.address = Address(sig(index));
+ request_data.data = read_data;
+ m_driver.requests.insert(make_pair(request_id, make_pair(m_proc_id, request_data)));
+
+ /*sequencer()->makeRequest(CacheMsg(Address(sig(index)), Address(sig(index)), CacheRequestType_LD,
+ Address(physical_address_t(1)),
+ AccessModeType_UserMode, 4,
+ PrefetchBit_No, 0, Address(0),
+ 0, 0 , false)); */
+}
+
+void RaceyPseudoThread::load_m(unsigned index) {
+ // cout << m_proc_id << " : load_m " << index << endl;
+
+ m_read = true;
+ uint8_t * read_data = new uint8_t[4];
+
+ char name [] = "Sequencer_";
+ char port_name [13];
+ sprintf(port_name, "%s%d", name, m_proc_id);
+
+ // pc is zero, problem?
+ int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m(index), read_data, 4, 0, RubyRequestType_LD, RubyAccessMode_User));
+
+ ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+
+ struct address_data request_data;
+ request_data.address = Address(m(index));
+ request_data.data = read_data;
+ m_driver.requests.insert(make_pair(request_id, make_pair(m_proc_id, request_data)));
+
+ /*sequencer()->makeRequest(CacheMsg(Address(m(index)), Address(m(index)), CacheRequestType_LD,
+ Address(physical_address_t(1)),
+ AccessModeType_UserMode, 4,
+ PrefetchBit_No, 0, Address(0),
+ 0, 0, false)); */
+}
+
+void RaceyPseudoThread::store_sig(unsigned index, unsigned value) {
+ cout << m_proc_id << " : store_sig " << index << " " << value << endl;
+
+ m_read = false;
+ m_value = value;
+ uint8_t * write_data = new uint8_t[4];
+
+ memcpy(write_data, &value, 4);
+
+ char name [] = "Sequencer_";
+ char port_name [13];
+ sprintf(port_name, "%s%d", name, m_proc_id);
+
+ // pc is zero, problem?
+ int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(sig(index), write_data, 4, 0, RubyRequestType_ST, RubyAccessMode_User));
+
+ ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+
+ struct address_data request_data;
+ request_data.address = Address(sig(index));
+ request_data.data = write_data;
+ m_driver.requests.insert(make_pair(request_id, make_pair(m_proc_id, request_data)));
+
+ /*sequencer()->makeRequest(CacheMsg(Address(sig(index)), Address(sig(index)), CacheRequestType_ST,
+ Address(physical_address_t(1)),
+ AccessModeType_UserMode, 4,
+ PrefetchBit_No, 0, Address(0),
+ 0, 0, false)); */
+}
+
+void RaceyPseudoThread::store_m(unsigned index, unsigned value) {
+ //cout << m_proc_id << " : store_m " << index << endl;
+
+ m_read = false;
+ m_value = value;
+ uint8_t * write_data = new uint8_t[4];
+ memcpy(write_data, &value, 4);
+
+ char name [] = "Sequencer_";
+ char port_name [13];
+ sprintf(port_name, "%s%d", name, m_proc_id);
+
+ // pc is zero, problem?
+ int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m(index), write_data, 4, 0, RubyRequestType_ST, RubyAccessMode_User));
+
+ ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+
+ struct address_data request_data;
+ request_data.address = Address(m(index));
+ request_data.data = write_data;
+ m_driver.requests.insert(make_pair(request_id, make_pair(m_proc_id, request_data)));
+
+ /*sequencer()->makeRequest(CacheMsg(Address(m(index)), Address(m(index)), CacheRequestType_ST,
+ Address(physical_address_t(1)),
+ AccessModeType_UserMode, 4,
+ PrefetchBit_No, 0, Address(0),
+ 0, 0, false)); */
+}
+
+// Save and Load context of a thread
+void RaceyPseudoThread::saveCPUStates(string filename) {
+ ogzstream out(filename.c_str());
+ out.write((char*)&m_looper, sizeof(int));
+ out.write((char*)&m_num, sizeof(unsigned));
+ out.write((char*)&m_index1, sizeof(unsigned));
+ out.write((char*)&m_index2, sizeof(unsigned));
+ out.write((char*)&m_stop, sizeof(unsigned));
+ out.close();
+}
+
+void RaceyPseudoThread::loadCPUStates(string filename) {
+ igzstream out(filename.c_str());
+ out.read((char*)&m_looper, sizeof(int));
+ out.read((char*)&m_num, sizeof(unsigned));
+ out.read((char*)&m_index1, sizeof(unsigned));
+ out.read((char*)&m_index2, sizeof(unsigned));
+ out.read((char*)&m_stop, sizeof(unsigned));
+ out.close();
+}
+
+void RaceyPseudoThread::print(ostream& out) const {
+ out << "[Racey Pseudo Thread: " << m_proc_id << "]" << endl;
+}
+
diff --git a/src/mem/ruby/tester/RaceyPseudoThread.hh b/src/mem/ruby/tester/RaceyPseudoThread.hh
new file mode 100644
index 000000000..9db4ad04a
--- /dev/null
+++ b/src/mem/ruby/tester/RaceyPseudoThread.hh
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1999 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.
+ */
+
+/*
+ * Description: This implements a pseudo racey thread which drives ruby timing
+ * simulator with access to two shared arrays.
+ *
+ */
+
+#ifndef RACEYPSEUDOTHREAD_H
+#define RACEYPSEUDOTHREAD_H
+
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/system/NodeID.hh"
+#include "Address_Tester.hh"
+#include "mem/ruby/libruby.hh"
+
+class RaceyDriver;
+
+class RaceyPseudoThread : public Consumer {
+private:
+ // constants
+ static const int PRIME1 = 103072243;
+ static const int PRIME2 = 103995407;
+ static const int M_ELEM = 64;
+
+ // m and sig array's starting address,
+ // each signature should occupy a cacheline
+ static const int SIG_ARR = 0;
+ static const int M_ARR = 0x10000;
+ static const int LINESIZE = 64;
+
+ // get address of a element from the m and sig arrays
+ physical_address_t sig(unsigned index) {
+ assert(index < M_ARR/64);
+ return SIG_ARR + (index*64);
+ };
+ physical_address_t m(unsigned index) { return M_ARR + (index*64); };
+
+public:
+ // Constructors
+ RaceyPseudoThread(NodeID node, RaceyDriver& driver);
+
+ // Destructor
+ ~RaceyPseudoThread();
+
+ // Public Methods
+ void performCallback(int proc, Address address, uint8_t * data);
+
+ void wakeup();
+
+ integer_t getInstructionCount() { return m_ic_counter; };
+
+ unsigned getSignature() { assert(m_proc_id == 0); return m_final_sig; };
+
+ void checkForDeadlock();
+
+ // save and restore the thread state
+ void saveCPUStates(string filename);
+ void loadCPUStates(string filename);
+
+ // reset IC to zero for next checkpoint
+ void resetIC() { m_ic_counter = 0; };
+
+ bool getInitializedState() { return m_initialized; };
+
+ void print(ostream& out) const;
+private:
+ // Private Methods
+
+ // mix two numbers
+ unsigned mix (unsigned i, unsigned j) { return (i + j * PRIME2) % PRIME1; };
+
+ // load or store the array
+ void load_sig(unsigned index);
+ void load_m(unsigned index);
+ void store_sig(unsigned index, unsigned value);
+ void store_m(unsigned index, unsigned value);
+
+ // Private copy constructor and assignment operator
+ RaceyPseudoThread(const RaceyPseudoThread& obj);
+ RaceyPseudoThread& operator=(const RaceyPseudoThread& obj);
+
+ // Data Members (m_ prefix)
+ RaceyDriver& m_driver;
+ NodeID m_proc_id;
+
+ // are we done?
+ bool m_done;
+
+ // [committed] instruction counter
+ int m_ic_counter;
+
+ // last time we made progress
+ Time m_last_progress;
+
+ // value of the callback block
+ bool m_read;
+ unsigned m_value;
+
+ // final signature
+ unsigned m_final_sig;
+
+ // local variables for the pseudo thread
+ int m_looper;
+ unsigned m_num, m_index1, m_index2, m_stop;
+ bool m_initialized;
+};
+
+// Output operator declaration
+ostream& operator<<(ostream& out, const RaceyPseudoThread& obj);
+
+// ******************* Definitions *******************
+
+// Output operator definition
+extern inline
+ostream& operator<<(ostream& out, const RaceyPseudoThread& obj)
+{
+ obj.print(out);
+ out << flush;
+ return out;
+}
+
+#endif //RACEYPSEUDOTHREAD_H
+
diff --git a/src/mem/ruby/tester/RequestGenerator.cc b/src/mem/ruby/tester/RequestGenerator.cc
deleted file mode 100644
index 4ee24544f..000000000
--- a/src/mem/ruby/tester/RequestGenerator.cc
+++ /dev/null
@@ -1,220 +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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/tester/RequestGenerator.hh"
-#include "mem/protocol/RequestGeneratorStatus.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"
-
-RequestGenerator::RequestGenerator(NodeID node, SyntheticDriver& driver) :
- m_driver(driver)
-{
- m_status = RequestGeneratorStatus_Thinking;
- m_last_transition = 0;
- m_node = node;
- pickAddress();
- m_counter = 0;
-
- //g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
-}
-
-RequestGenerator::~RequestGenerator()
-{
-}
-
-void RequestGenerator::wakeup()
-{
- DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
- DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
-
- if (m_status == RequestGeneratorStatus_Thinking) {
- m_status = RequestGeneratorStatus_Test_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateTest(); // Test
- } else if (m_status == RequestGeneratorStatus_Holding) {
- m_status = RequestGeneratorStatus_Release_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateRelease(); // Release
- } else if (m_status == RequestGeneratorStatus_Before_Swap) {
- m_status = RequestGeneratorStatus_Swap_Pending;
- m_last_transition = g_eventQueue_ptr->getTime();
- initiateSwap();
- } else {
- WARN_EXPR(m_status);
- ERROR_MSG("Invalid status");
- }
-}
-
-void RequestGenerator::performCallback(NodeID proc, SubBlock& data)
-{
- Address address = data.getAddress();
- assert(proc == m_node);
- 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);
-
- if (m_status == RequestGeneratorStatus_Test_Pending) {
- // m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- if (data.readByte() == LockStatus_Locked) {
- // Locked - keep spinning
- m_status = RequestGeneratorStatus_Thinking;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
- } else {
- // Unlocked - try the swap
- m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- m_status = RequestGeneratorStatus_Before_Swap;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
- }
- } else if (m_status == RequestGeneratorStatus_Swap_Pending) {
- m_driver.recordSwapLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- if (data.readByte() == LockStatus_Locked) {
- // We failed to aquire the lock
- m_status = RequestGeneratorStatus_Thinking;
- m_last_transition = g_eventQueue_ptr->getTime();
- g_eventQueue_ptr->scheduleEvent(this, waitTime());
- } else {
- // We acquired the lock
- data.writeByte(LockStatus_Locked);
- m_status = RequestGeneratorStatus_Holding;
- m_last_transition = g_eventQueue_ptr->getTime();
- DEBUG_MSG(TESTER_COMP, HighPrio, "Acquired");
- DEBUG_EXPR(TESTER_COMP, HighPrio, proc);
- DEBUG_EXPR(TESTER_COMP, HighPrio, g_eventQueue_ptr->getTime());
- g_eventQueue_ptr->scheduleEvent(this, holdTime());
- }
- } else if (m_status == RequestGeneratorStatus_Release_Pending) {
- m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
- // We're releasing the lock
- data.writeByte(LockStatus_Unlocked);
-
- m_counter++;
- if (m_counter < g_tester_length) {
- m_status = RequestGeneratorStatus_Thinking;
- m_last_transition = g_eventQueue_ptr->getTime();
- pickAddress();
- g_eventQueue_ptr->scheduleEvent(this, thinkTime());
- } else {
- m_driver.reportDone();
- m_status = RequestGeneratorStatus_Done;
- m_last_transition = g_eventQueue_ptr->getTime();
- }
- } else {
- WARN_EXPR(m_status);
- ERROR_MSG("Invalid status");
- }
-}
-
-int RequestGenerator::thinkTime() const
-{
- return g_think_time;
-}
-
-int RequestGenerator::waitTime() const
-{
- return g_wait_time;
-}
-
-int RequestGenerator::holdTime() const
-{
- return g_hold_time;
-}
-
-void RequestGenerator::pickAddress()
-{
- assert(m_status == RequestGeneratorStatus_Thinking);
- m_address = m_driver.pickAddress(m_node);
-}
-
-void RequestGenerator::initiateTest()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Test");
-
- Addr data_addr = m_address.getAddress();
- Request request(0, data_addr, 1, Flags<unsigned int>(), 1, 0, 0);
- MemCmd::Command command;
- command = MemCmd::ReadReq;
-
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
- sequencer()->makeRequest(&pkt);
-}
-
-void RequestGenerator::initiateSwap()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Swap");
-
- Addr data_addr = m_address.getAddress();
- Request request(0, data_addr, 1, Flags<unsigned int>(), 2, 0, 0);
- MemCmd::Command command;
- command = MemCmd::SwapReq;
-
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
- sequencer()->makeRequest(&pkt);
-}
-
-void RequestGenerator::initiateRelease()
-{
- DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Release");
-
- Addr data_addr = m_address.getAddress();
- Request request(0, data_addr, 1, Flags<unsigned int>(), 3, 0, 0);
- MemCmd::Command command;
- command = MemCmd::WriteReq;
-
- Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
- sequencer()->makeRequest(&pkt);
-}
-
-Sequencer* RequestGenerator::sequencer() const
-{
- return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
-}
-
-void RequestGenerator::print(ostream& out) const
-{
- out << "[RequestGenerator]" << endl;
-}
-
diff --git a/src/mem/ruby/tester/SpecifiedGenerator.cc b/src/mem/ruby/tester/SpecifiedGenerator.cc
index 1c273eac3..63e4a7ae8 100644
--- a/src/mem/ruby/tester/SpecifiedGenerator.cc
+++ b/src/mem/ruby/tester/SpecifiedGenerator.cc
@@ -33,10 +33,6 @@
*/
#include "mem/ruby/tester/SpecifiedGenerator.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/tester/SyntheticDriver.hh"
SpecifiedGenerator::SpecifiedGenerator()
{
diff --git a/src/mem/ruby/tester/SpecifiedGenerator.hh b/src/mem/ruby/tester/SpecifiedGenerator.hh
index 9aaaffba0..976947ce6 100644
--- a/src/mem/ruby/tester/SpecifiedGenerator.hh
+++ b/src/mem/ruby/tester/SpecifiedGenerator.hh
@@ -37,12 +37,10 @@
#ifndef SPECIFIEDGENERATOR_H
#define SPECIFIEDGENERATOR_H
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/system/NodeID.hh"
-
-class Sequencer;
-class SubBlock;
+#include "Address_Tester.hh"
class SpecifiedGenerator : public Consumer {
public:
@@ -54,7 +52,7 @@ public:
// Public Methods
virtual void wakeup() = 0;
- virtual void performCallback(NodeID proc, SubBlock& data) = 0;
+ virtual void performCallback(NodeID proc, Address address) = 0;
virtual void print(ostream& out) const = 0;
protected:
diff --git a/src/mem/ruby/tester/SyntheticDriver.cc b/src/mem/ruby/tester/SyntheticDriver.cc
deleted file mode 100644
index f19baa202..000000000
--- a/src/mem/ruby/tester/SyntheticDriver.cc
+++ /dev/null
@@ -1,286 +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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/tester/SyntheticDriver.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/tester/RequestGenerator.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/protocol/Chip.hh"
-
-SyntheticDriver::SyntheticDriver(RubySystem* sys_ptr)
-{
- m_finish_time = 0;
- m_done_counter = 0;
-
- m_last_progress_vector.setSize(RubyConfig::numberOfProcessors());
- for (int i=0; i<m_last_progress_vector.size(); i++) {
- m_last_progress_vector[i] = 0;
- }
-
- m_lock_vector.setSize(g_synthetic_locks);
- for (int i=0; i<m_lock_vector.size(); i++) {
- m_lock_vector[i] = -1; // No processor last held it
- }
-
- m_request_generator_vector.setSize(RubyConfig::numberOfProcessors());
- for (int i=0; i<m_request_generator_vector.size(); i++) {
- if(XACT_MEMORY){
- //m_request_generator_vector[i] = new XactRequestGenerator(i, *this);
- } else {
- m_request_generator_vector[i] = new RequestGenerator(i, *this);
- }
- }
-
- // add the tester consumer to the global event queue
- g_eventQueue_ptr->scheduleEvent(this, 1);
-}
-
-SyntheticDriver::~SyntheticDriver()
-{
- for (int i=0; i<m_last_progress_vector.size(); i++) {
- delete m_request_generator_vector[i];
- }
-}
-
-void
-SyntheticDriver::hitCallback(Packet * pkt)
-{
- NodeID proc = pkt->req->contextId();
- SubBlock data(Address(pkt->getAddr()), pkt->req->getSize());
- if (pkt->hasData()) {
- for (int i = 0; i < pkt->req->getSize(); i++) {
- data.setByte(i, *(pkt->getPtr<uint8>()+i));
- }
- }
- m_request_generator_vector[proc]->performCallback(proc, data);
- m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
-}
-
-void SyntheticDriver::abortCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread)
-{
- //cout << "SyntheticDriver::abortCallback" << endl;
- DEBUG_EXPR(TESTER_COMP, MedPrio, data);
-
- if(XACT_MEMORY){
- //XactRequestGenerator* reqGen = static_cast<XactRequestGenerator*>(m_request_generator_vector[proc]);
- //reqGen->abortTransaction();
- //reqGen->performCallback(proc, data);
- } else {
- m_request_generator_vector[proc]->performCallback(proc, data);
- }
-
- // Mark that we made progress
- m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
-}
-
-// For Transactional Memory
-/*
-// called whenever we send a nack
-void SyntheticDriver::notifySendNack( int proc, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id ){
- if(XACT_MEMORY){
- //XactRequestGenerator* reqGen = static_cast<XactRequestGenerator*>(m_request_generator_vector[proc]);
- //reqGen->notifySendNack(addr, remote_timestamp, remote_id);
- }
- else{
- cout << "notifySendNack NOT USING TM" << endl;
- ASSERT(0);
- }
-}
-
-// called whenever we receive a NACK
-// Either for a demand request or log store
-void SyntheticDriver::notifyReceiveNack( int proc, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id ){
- if(XACT_MEMORY){
- //XactRequestGenerator* reqGen = static_cast<XactRequestGenerator*>(m_request_generator_vector[proc]);
- //reqGen->notifyReceiveNack(addr, remote_timestamp, remote_id);
- }
- else{
- cout << "notifyReceiveNack NOT USING TM" << endl;
- ASSERT(0);
- }
-}
-
-// called whenever we received ALL the NACKs. Take abort or retry action here
-void SyntheticDriver::notifyReceiveNackFinal(int proc, const Address & addr){
- if(XACT_MEMORY){
- //XactRequestGenerator* reqGen = static_cast<XactRequestGenerator*>(m_request_generator_vector[proc]);
- //reqGen->notifyReceiveNackFinal(addr);
- }
- else{
- ASSERT(0);
- }
-}
-
-// called during abort handling
-// void SyntheticDriver::notifyAbortStart( const Address & handlerPC ){
-
-// }
-
-// void SyntheticDriver::notifyAbortComplete( const Address & newPC ){
-
-// }
-*/
-
-Address SyntheticDriver::pickAddress(NodeID node)
-{
- // This methods picks a random lock that we were NOT that last
- // processor to acquire. Why? Without this change 2 and 4
- // processor runs, the odds of having the lock in your cache in
- // read/write state is 50% or 25%, respectively. This effect can
- // make our 'throughput per processor' results look too strange.
-
- Address addr;
- // FIXME - make this a parameter of the workload
- int lock_number = 0;
- int counter = 0;
- while (1) {
- // Pick a random lock
- lock_number = random() % m_lock_vector.size();
-
- // Were we the last to acquire the lock?
- if (m_lock_vector[lock_number] != node) {
- break;
- }
-
- // Don't keep trying forever, since if there is only one lock, we're always the last to try to obtain the lock
- counter++;
- if (counter > 10) {
- break;
- }
- }
-
- // We're going to acquire it soon, so we can update the last
- // processor to hold the lock at this time
- m_lock_vector[lock_number] = node;
-
- // One lock per cache line
- addr.setAddress(lock_number * RubyConfig::dataBlockBytes());
- return addr;
-}
-
-void SyntheticDriver::reportDone()
-{
- m_done_counter++;
- if (m_done_counter == RubyConfig::numberOfProcessors()) {
- m_finish_time = g_eventQueue_ptr->getTime();
- }
-}
-
-void SyntheticDriver::recordTestLatency(Time time)
-{
- m_test_latency.add(time);
-}
-
-void SyntheticDriver::recordSwapLatency(Time time)
-{
- m_swap_latency.add(time);
-}
-
-void SyntheticDriver::recordReleaseLatency(Time time)
-{
- m_release_latency.add(time);
-}
-
-void SyntheticDriver::wakeup()
-{
- // checkForDeadlock();
- if (m_done_counter < RubyConfig::numberOfProcessors()) {
- g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
- }
-}
-
-void SyntheticDriver::checkForDeadlock()
-{
- int size = m_last_progress_vector.size();
- Time current_time = g_eventQueue_ptr->getTime();
- for (int processor=0; processor<size; processor++) {
- if ((current_time - m_last_progress_vector[processor]) > g_DEADLOCK_THRESHOLD) {
- WARN_EXPR(processor);
-#ifndef NDEBUG
- Sequencer* seq_ptr = g_system_ptr->getChip(processor/RubyConfig::numberOfProcsPerChip())->getSequencer(processor%RubyConfig::numberOfProcsPerChip());
-#endif
- assert(seq_ptr != NULL);
- // if (seq_ptr->isRequestPending()) {
- // WARN_EXPR(seq_ptr->pendingAddress());
- // }
- WARN_EXPR(current_time);
- WARN_EXPR(m_last_progress_vector[processor]);
- WARN_EXPR(current_time - m_last_progress_vector[processor]);
- ERROR_MSG("Deadlock detected.");
- }
- }
-}
-
-integer_t SyntheticDriver::readPhysicalMemory(int procID, physical_address_t address,
- int len ){
- char buffer[8];
- ASSERT(len <= 8);
- Sequencer* seq = g_system_ptr->getChip(procID/RubyConfig::numberOfProcsPerChip())->getSequencer(procID%RubyConfig::numberOfProcsPerChip());
- assert(seq != NULL);
- bool found = seq->getRubyMemoryValue(Address(address), buffer, len );
- ASSERT(found);
- return *((integer_t *) buffer);
-}
-
-void SyntheticDriver::writePhysicalMemory( int procID, physical_address_t address,
- integer_t value, int len ){
- char buffer[8];
- ASSERT(len <= 8);
-
- memcpy(buffer, (const void*) &value, len);
- DEBUG_EXPR(TESTER_COMP, MedPrio, "");
- Sequencer* seq = g_system_ptr->getChip(procID/RubyConfig::numberOfProcsPerChip())->getSequencer(procID%RubyConfig::numberOfProcsPerChip());
- assert(seq != NULL);
- bool found = seq->setRubyMemoryValue(Address(address), buffer, len );
- ASSERT(found);
- //return found;
-}
-
-void SyntheticDriver::printStats(ostream& out) const
-{
- out << endl;
- out << "SyntheticDriver Stats" << endl;
- out << "---------------------" << endl;
-
- out << "synthetic_finish_time: " << m_finish_time << endl;
- out << "test_latency: " << m_test_latency << endl;
- out << "swap_latency: " << m_swap_latency << endl;
- out << "release_latency: " << m_release_latency << endl;
-}
-
-void SyntheticDriver::print(ostream& out) const
-{
-}
diff --git a/src/mem/ruby/tester/SyntheticDriver.hh b/src/mem/ruby/tester/SyntheticDriver.hh
deleted file mode 100644
index 18c463e88..000000000
--- a/src/mem/ruby/tester/SyntheticDriver.hh
+++ /dev/null
@@ -1,118 +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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef SYNTHETICDRIVER_H
-#define SYNTHETICDRIVER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/ruby/common/Histogram.hh"
-#include "mem/protocol/CacheRequestType.hh"
-
-class RubySystem;
-class RequestGenerator;
-
-class SyntheticDriver : public Driver, public Consumer {
-public:
- // Constructors
- SyntheticDriver(RubySystem* sys_ptr);
-
- // Destructor
- ~SyntheticDriver();
-
- // Public Methods
- Address pickAddress(NodeID node);
- void reportDone();
- void recordTestLatency(Time time);
- void recordSwapLatency(Time time);
- void recordReleaseLatency(Time time);
-
- void hitCallback(Packet* pkt);
- void conflictCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) {assert(0);}
- void abortCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread);
- void wakeup();
- void printStats(ostream& out) const;
- void clearStats() {}
- void printConfig(ostream& out) const {}
-
- integer_t readPhysicalMemory(int procID, physical_address_t address,
- int len );
-
- void writePhysicalMemory( int procID, physical_address_t address,
- integer_t value, int len );
-
- void print(ostream& out) const;
-
- // For handling NACKs/retries
- //void notifySendNack( int procID, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id);
- //void notifyReceiveNack( int procID, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id);
- //void notifyReceiveNackFinal( int procID, const Address & addr);
-
-private:
- // Private Methods
- void checkForDeadlock();
-
- // Private copy constructor and assignment operator
- SyntheticDriver(const SyntheticDriver& obj);
- SyntheticDriver& operator=(const SyntheticDriver& obj);
-
- // Data Members (m_ prefix)
- Vector<Time> m_last_progress_vector;
- Vector<RequestGenerator*> m_request_generator_vector;
- Vector<NodeID> m_lock_vector; // Processor last to hold the lock
- int m_done_counter;
-
- Histogram m_test_latency;
- Histogram m_swap_latency;
- Histogram m_release_latency;
- Time m_finish_time;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const SyntheticDriver& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const SyntheticDriver& obj)
-{
- obj.print(out);
- out << flush;
- return out;
-}
-
-#endif //SYNTHETICDRIVER_H
diff --git a/src/mem/ruby/tester/Tester.cc b/src/mem/ruby/tester/Tester.cc
deleted file mode 100644
index eafc04a92..000000000
--- a/src/mem/ruby/tester/Tester.cc
+++ /dev/null
@@ -1,112 +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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/tester/Tester.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/tester/Check.hh"
-#include "mem/protocol/Chip.hh"
-
-Tester::Tester(RubySystem* sys_ptr)
-{
- g_callback_counter = 0;
-
- // add the tester consumer to the global event queue
- g_eventQueue_ptr->scheduleEvent(this, 1);
-
- m_last_progress_vector.setSize(RubyConfig::numberOfProcessors());
- for (int i=0; i<m_last_progress_vector.size(); i++) {
- m_last_progress_vector[i] = 0;
- }
-}
-
-Tester::~Tester()
-{
-}
-
-void Tester::hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread)
-{
- // Mark that we made progress
- m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
- g_callback_counter++;
-
- // This tells us our store has 'completed' or for a load gives us
- // back the data to make the check
- DEBUG_EXPR(TESTER_COMP, MedPrio, proc);
- DEBUG_EXPR(TESTER_COMP, MedPrio, data);
- Check* check_ptr = m_checkTable.getCheck(data.getAddress());
- assert(check_ptr != NULL);
- check_ptr->performCallback(proc, data);
-
-}
-
-void Tester::wakeup()
-{
- if (g_callback_counter < g_tester_length) {
- // Try to perform an action or check
- Check* check_ptr = m_checkTable.getRandomCheck();
- assert(check_ptr != NULL);
- check_ptr->initiate();
-
- checkForDeadlock();
-
- g_eventQueue_ptr->scheduleEvent(this, 2);
- }
-}
-
-void Tester::checkForDeadlock()
-{
- int size = m_last_progress_vector.size();
- Time current_time = g_eventQueue_ptr->getTime();
- for (int processor=0; processor<size; processor++) {
- if ((current_time - m_last_progress_vector[processor]) > g_DEADLOCK_THRESHOLD) {
- WARN_EXPR(current_time);
- WARN_EXPR(m_last_progress_vector[processor]);
- WARN_EXPR(current_time - m_last_progress_vector[processor]);
- WARN_EXPR(processor);
- Sequencer* seq_ptr = g_system_ptr->getChip(processor/RubyConfig::numberOfProcsPerChip())->getSequencer(processor%RubyConfig::numberOfProcsPerChip());
- assert(seq_ptr != NULL);
- WARN_EXPR(*seq_ptr);
- ERROR_MSG("Deadlock detected.");
- }
- }
-}
-
-void Tester::print(ostream& out) const
-{
- out << "[Tester]" << endl;
-}
-
diff --git a/src/mem/ruby/tester/main.cc b/src/mem/ruby/tester/main.cc
index ba835b488..849206de9 100644
--- a/src/mem/ruby/tester/main.cc
+++ b/src/mem/ruby/tester/main.cc
@@ -32,10 +32,8 @@
*
*/
-#include "mem/ruby/tester/main.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-//#include "mem/ruby/tester/test_framework.hh"
+#include "mem/slicc/main.hh"
+#include "mem/ruby/tester/test_framework.hh"
// *******************
// *** tester main ***
@@ -43,6 +41,5 @@
int main(int argc, char *argv[])
{
- //dsm: PRUNED
- //tester_main(argc, argv);
+ tester_main(argc, argv);
}
diff --git a/src/mem/ruby/tester/main.hh b/src/mem/ruby/tester/main.hh
index 3708d770d..ca036ddd7 100644
--- a/src/mem/ruby/tester/main.hh
+++ b/src/mem/ruby/tester/main.hh
@@ -27,9 +27,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*
+ * $Id$
+ *
+ * Description:
+ *
+ */
+
#ifndef MAIN_H
#define MAIN_H
-#include "mem/ruby/common/Global.hh"
+#include "Global_Tester.hh"
#endif //MAIN_H
diff --git a/src/mem/ruby/tester/test_framework.cc b/src/mem/ruby/tester/test_framework.cc
index 9886adc8d..6b7c7ddec 100644
--- a/src/mem/ruby/tester/test_framework.cc
+++ b/src/mem/ruby/tester/test_framework.cc
@@ -32,181 +32,233 @@
*
*/
-#include "mem/protocol/protocol_name.hh"
+using namespace std;
+
#include "mem/ruby/tester/test_framework.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/init.hh"
-#include "mem/ruby/tester/Tester.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
+#include "mem/protocol/protocol_name.hh"
#include "getopt.hh"
-#include "mem/ruby/network/Network.hh"
-#include "mem/ruby/recorder/CacheRecorder.hh"
-#include "mem/ruby/recorder/Tracer.hh"
+#include "mem/ruby/tester/DeterministicDriver.hh"
+#include "mem/ruby/tester/RaceyDriver.hh"
+#include "mem/ruby/tester/Driver_Tester.hh"
-using namespace std;
#include <string>
#include <map>
+#include <iostream>
+#include <assert.h>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <sys/wait.h>
-// Maurice
-// extern "C" {
-// #include "simics/api.hh"
-// };
+#include "mem/ruby/libruby.hh"
-#include "mem/gems_common/ioutil/confio.hh"
-#include "mem/gems_common/ioutil/initvar.hh"
+// FIXME: should really make this a class if can't figure out how to make a function to get the ruby parameter
-// A generated file containing the default tester parameters in string form
-// The defaults are stored in the variables
-// global_default_param and global_default_tester_param
-#include "mem/ruby/default_param.hh"
-#include "mem/ruby/tester_param.hh"
+static void set_defaults();
static void parseOptions(int argc, char **argv);
static void usageInstructions();
static void checkArg(char ch);
-static void tester_record_cache();
-static void tester_playback_trace();
static void tester_initialize(int argc, char **argv);
static void tester_destroy();
+static void hit_callback(int64_t request_id);
+
+// Tester variables
+string driver_type;
+string generator_type;
+Driver_Tester * m_driver_ptr;
+int g_tester_length;
+int num_completions;
+Time g_think_time;
+Time g_wait_time;
+int num_procs;
+
+// Debugger variables
+Debug * debug_ptr;
+string g_debug_verbosity_string;
+string g_debug_filter_string;
+string g_debug_output_filename;
+Time g_debug_start_time;
-static string trace_filename;
-char * my_default_param;
-initvar_t * my_initvar;
void tester_main(int argc, char **argv)
{
tester_initialize(argc, argv);
- if (trace_filename != "") {
- // playback a trace (for multicast-mask prediction)
- tester_playback_trace();
- } else {
- // test code to create a trace
- if (!(g_SYNTHETIC_DRIVER || g_DETERMINISTIC_DRIVER) && trace_filename == "") {
- g_system_ptr->getTracer()->startTrace("ruby.trace.gz");
- g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 10000);
- g_system_ptr->getTracer()->stopTrace();
- }
-
- g_eventQueue_ptr->triggerAllEvents();
-
- // This call is placed here to make sure the cache dump code doesn't fall victim to code rot
- if (!(g_SYNTHETIC_DRIVER || g_DETERMINISTIC_DRIVER)) {
- tester_record_cache();
- }
- }
tester_destroy();
}
-static void tester_allocate( void )
+vector<string> tokenizeMyString(string str, string delims)
{
- init_simulator();
+ vector<string> tokens;
+ char* pch;
+ char* tmp;
+ const char* c_delims = delims.c_str();
+ tmp = new char[str.length()+1];
+ strcpy(tmp, str.c_str());
+ pch = strtok(tmp, c_delims);
+ while (pch != NULL) {
+ tokens.push_back(string(pch));
+ pch = strtok(NULL, c_delims);
+ }
+ delete [] tmp;
+ return tokens;
}
-static void tester_generate_values( void )
+
+vector<string> getPorts(const char* cfg_script, int cfg_script_argc, char* cfg_script_argv[])
{
+ stringstream cfg_output;
+
+ // first we execute the Ruby-lang configuration script
+ int fd[2];
+ int pid;
+ if (pipe(fd) == -1) {
+ perror("Error Creating Pipe");
+ exit(EXIT_FAILURE);
+ }
+
+ pid = fork();
+ if (pid == -1){
+ perror("Error forking");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!pid) {
+ // child
+ close(fd[0]); // close the read end of the pipe
+ // replace stdout with the write pipe
+ if (dup2(fd[1], STDOUT_FILENO) == -1) {
+ perror("Error redirecting stdout");
+ exit(EXIT_FAILURE);
+ }
+#define QUOTE_MACRO(x, y) QUOTE_TXT(x,y)
+#define QUOTE_TXT(x, y) #x y
+ if (execlp("ruby", "ruby", "-I", QUOTE_MACRO(GEMS_ROOT, "/ruby/config"), QUOTE_MACRO(GEMS_ROOT, "/tests/list_ports.rb"), cfg_script, NULL)) {
+ perror("execlp");
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ close(fd[1]);
+
+ int child_status;
+ if (wait(&child_status) == -1) {
+ perror("wait");
+ exit(EXIT_FAILURE);
+ }
+ if (child_status != EXIT_SUCCESS) {
+ exit(EXIT_FAILURE);
+ }
+
+ char buf[100];
+ int bytes_read;
+ while( (bytes_read = read(fd[0], buf, 100)) > 0 ) {
+ for (int i=0;i<bytes_read;i++) {
+ cfg_output << buf[i];
+ }
+ }
+ assert(bytes_read == 0);
+ close(fd[0]);
+ }
+ string line;
+ getline(cfg_output, line);
+
+ return tokenizeMyString(line, " ");
}
+
+
void tester_initialize(int argc, char **argv)
{
- int param_len = strlen( global_default_param ) + strlen( global_default_tester_param ) + 1;
- char *default_param = (char *) malloc( sizeof(char) * param_len );
- my_default_param = default_param;
- strcpy( default_param, global_default_param );
- strcat( default_param, global_default_tester_param );
-
- // when the initvar object is created, it reads the configuration default
- // -for the tester, the configuration defaults in config/tester.defaults
-
- /** note: default_param is included twice in the tester:
- * -once in init.C
- * -again in this file
- */
- initvar_t *ruby_initvar = new initvar_t( "ruby", "../../../ruby/",
- default_param,
- &tester_allocate,
- &tester_generate_values,
- NULL,
- NULL );
- my_initvar = ruby_initvar;
- ruby_initvar->checkInitialization();
+ const char* cfg_file = argv[1];
+
+ set_defaults();
parseOptions(argc, argv);
- ruby_initvar->allocate();
+ libruby_init(cfg_file);
+ libruby_print_config(std::cout);
- g_system_ptr->printConfig(cout);
- cout << "Testing clear stats...";
- g_system_ptr->clearStats();
- cout << "Done." << endl;
- //free( default_param );
- //delete ruby_initvar;
-}
+ vector<string> port_names = getPorts(cfg_file, 0, NULL);
+ vector<RubyPortHandle> ports;
-void tester_destroy()
-{
- g_system_ptr->printStats(cout);
- g_debug_ptr->closeDebugOutputFile();
+ for (vector<string>::const_iterator it = port_names.begin(); it != port_names.end(); it++)
+ ports.push_back(libruby_get_port((*it).c_str(), hit_callback));
- free(my_default_param);
- delete my_initvar;
- // Clean up
- destroy_simulator();
- cerr << "Success: " << CURRENT_PROTOCOL << endl;
-}
+ debug_ptr = new Debug( g_debug_filter_string.c_str(),
+ g_debug_verbosity_string.c_str(),
+ g_debug_start_time,
+ g_debug_output_filename.c_str() );
-void tester_install_opal(mf_opal_api_t* opal_api, mf_ruby_api_t* ruby_api)
-{
- std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented" << std::endl;
+ if (driver_type == "Deterministic") {
+ m_driver_ptr = new DeterministicDriver(generator_type, num_completions, num_procs, g_think_time, g_wait_time, g_tester_length);
+ }
+ else if (driver_type == "Racey") {
+ m_driver_ptr = new RaceyDriver(num_procs, g_tester_length);
+ }
+ /* else if (driver_type == "Synthetic") {
+ m_driver_ptr = new SyntheticDriver();
+ }
+ }*/
+
+ m_driver_ptr->go();
}
-void tester_record_cache()
+void tester_destroy()
{
- cout << "Testing recording of cache contents" << endl;
- CacheRecorder recorder;
- g_system_ptr->recordCacheContents(recorder);
- int written = recorder.dumpRecords("ruby.caches.gz");
- int read = Tracer::playbackTrace("ruby.caches.gz");
- assert(read == written);
- cout << "Testing recording of cache contents completed" << endl;
+ m_driver_ptr->printStats(cout);
+ libruby_destroy();
+ cerr << "Success: " << CURRENT_PROTOCOL << endl;
}
-void tester_playback_trace()
+
+void hit_callback(int64_t request_id)
{
- assert(trace_filename != "");
- cout << "Reading trace from file '" << trace_filename << "'..." << endl;
- int read = Tracer::playbackTrace(trace_filename);
- cout << "(" << read << " requests read)" << endl;
- if (read == 0) {
- ERROR_MSG("Zero items read from tracefile.");
- }
+ m_driver_ptr->hitCallback(request_id);
}
// ************************************************************************
// *** Functions for parsing the command line parameters for the tester ***
// ************************************************************************
+
+
static struct option const long_options[] =
{
{"help", no_argument, NULL, 'h'},
- {"processors", required_argument, NULL, 'p'},
- {"length", required_argument, NULL, 'l'},
- {"random", required_argument, NULL, 'r'},
- {"trace_input", required_argument, NULL, 'z'},
- {"component", required_argument, NULL, 'c'},
- {"verbosity", required_argument, NULL, 'v'},
- {"debug_output_file", required_argument, NULL, 'o'},
- {"start", required_argument, NULL, 's'},
- {"bandwidth", required_argument, NULL, 'b'},
- {"threshold", required_argument, NULL, 't'},
- {"think_time", required_argument, NULL, 'k'},
- {"locks", required_argument, NULL, 'q'},
- {"network", required_argument, NULL, 'n'},
- {"procs_per_chip", required_argument, NULL, 'a'},
- {"l2_caches", required_argument, NULL, 'e'},
- {"memories", required_argument, NULL, 'm'},
+ {"number of processors", required_argument, NULL, 'p'},
+ {"test run length", required_argument, NULL, 'l'},
+ {"debugger verbosity", required_argument, NULL, 'v'},
+ {"debugger filter component", required_argument, NULL, 'c'},
+ {"debugger output file", required_argument, NULL, 'o'},
+ {"debugger start time", required_argument, NULL, 's'},
+ {"generator think time", required_argument, NULL, 'k'},
+ {"generator wait time", required_argument, NULL, 'w'},
+ {"driver type", required_argument, NULL, 'd'},
+ {"generator type", required_argument, NULL, 'g'},
+ {"num completions before pass", required_argument, NULL, 'n'},
{NULL, 0, NULL, 0}
};
+
+// This is awkward and temporary, need the defaults config, and also need functions to
+// just lookup a parameter in the configuration file
+// Ideally the default values are set by libruby_init and then a function is provided to
+// set values at run-time
+static void set_defaults() {
+ g_tester_length = 0;
+ g_think_time = 5;
+ g_wait_time = 20;
+
+ num_procs = 1;
+ num_completions = 1;
+ driver_type = "Deterministic";
+ generator_type = "DetermInvGenerator";
+ g_debug_verbosity_string = "none";
+ g_debug_filter_string = "none";
+ g_debug_output_filename = "none";
+ g_debug_start_time = 0;
+}
+
static void parseOptions(int argc, char **argv)
{
cout << "Parsing command line arguments:" << endl;
@@ -229,21 +281,14 @@ static void parseOptions(int argc, char **argv)
switch (c) {
case 0:
break;
-
- case 'c':
- checkArg(c);
- cout << " component filter string = " << optarg << endl;
- error = Debug::checkFilterString( optarg );
- if (error) {
- usageInstructions();
- }
- DEBUG_FILTER_STRING = strdup( optarg );
- break;
-
case 'h':
usageInstructions();
break;
-
+ case 'p':
+ checkArg(c);
+ cout << " number of processors = " << optarg << endl;
+ num_procs = atoi( optarg );
+ break;
case 'v':
checkArg(c);
cout << " verbosity string = " << optarg << endl;
@@ -251,22 +296,8 @@ static void parseOptions(int argc, char **argv)
if (error) {
usageInstructions();
}
- DEBUG_VERBOSITY_STRING = strdup( optarg );
- break;
-
- case 'r': {
- checkArg(c);
- if (string(optarg) == "random") {
- g_RANDOM_SEED = time(NULL);
- } else {
- g_RANDOM_SEED = atoi(optarg);
- if (g_RANDOM_SEED == 0) {
- usageInstructions();
- }
- }
+ g_debug_verbosity_string = strdup( optarg );
break;
- }
-
case 'l': {
checkArg(c);
g_tester_length = atoi(optarg);
@@ -276,44 +307,15 @@ static void parseOptions(int argc, char **argv)
}
break;
}
-
- case 'q': {
+ case 'c':
checkArg(c);
- g_synthetic_locks = atoi(optarg);
- cout << " locks in synthetic workload = " << g_synthetic_locks << endl;
- if (g_synthetic_locks == 0) {
+ cout << " component filter string = " << optarg << endl;
+ error = Debug::checkFilterString( optarg );
+ if (error) {
usageInstructions();
}
+ g_debug_filter_string = strdup( optarg );
break;
- }
-
- case 'p': {
- checkArg(c);
- g_NUM_PROCESSORS = atoi(optarg);
- break;
- }
-
- case 'a': {
- checkArg(c);
- g_PROCS_PER_CHIP = atoi(optarg);
- cout << " g_PROCS_PER_CHIP: " << g_PROCS_PER_CHIP << endl;
- break;
- }
-
- case 'e': {
- checkArg(c);
- g_NUM_L2_BANKS = atoi(optarg);
- cout << " g_NUM_L2_BANKS: " << g_NUM_L2_BANKS << endl;
- break;
- }
-
- case 'm': {
- checkArg(c);
- g_NUM_MEMORIES = atoi(optarg);
- cout << " g_NUM_MEMORIES: " << g_NUM_MEMORIES << endl;
- break;
- }
-
case 's': {
checkArg(c);
long long start_time = atoll(optarg);
@@ -321,71 +323,44 @@ static void parseOptions(int argc, char **argv)
if (start_time == 0) {
usageInstructions();
}
- DEBUG_START_TIME = start_time;
- break;
- }
-
- case 'b': {
- checkArg(c);
- int bandwidth = atoi(optarg);
- cout << " bandwidth per link (MB/sec) = " << bandwidth << endl;
- g_endpoint_bandwidth = bandwidth;
- if (bandwidth == 0) {
- usageInstructions();
- }
+ g_debug_start_time = start_time;
break;
}
-
- case 't': {
+ case 'k': {
checkArg(c);
- g_bash_bandwidth_adaptive_threshold = atof(optarg);
- if ((g_bash_bandwidth_adaptive_threshold > 1.1) || (g_bash_bandwidth_adaptive_threshold < -0.1)) {
- cerr << "Error: Bandwidth adaptive threshold must be between 0.0 and 1.0" << endl;
- usageInstructions();
- }
-
+ g_think_time = atoi(optarg);
break;
}
-
- case 'k': {
+ case 'w': {
checkArg(c);
- g_think_time = atoi(optarg);
+ g_wait_time = atoi(optarg);
break;
}
-
case 'o':
checkArg(c);
cout << " output file = " << optarg << endl;
- DEBUG_OUTPUT_FILENAME = strdup( optarg );
+ g_debug_output_filename = strdup( optarg );
break;
-
- case 'z':
+ case 'd':
checkArg(c);
- trace_filename = string(optarg);
- cout << " tracefile = " << trace_filename << endl;
+ cout << " driver type = " << optarg << endl;
+ driver_type = strdup( optarg );
+ break;
+ case 'g':
+ checkArg(c);
+ cout << " generator type = " << optarg << endl;
+ generator_type = strdup( optarg );
+ break;
+ case 'n':
+ checkArg(c);
+ cout << " num completions before pass = " << optarg << endl;
+ num_completions = atoi( optarg );
break;
-
- case 'n':
- checkArg(c);
- cout << " topology = " << string(optarg) << endl;
- g_NETWORK_TOPOLOGY = strdup(optarg);
- break;
-
default:
cerr << "parameter '" << c << "' unknown" << endl;
usageInstructions();
}
}
-
- if ((trace_filename != "") || (g_tester_length != 0)) {
- if ((trace_filename != "") && (g_tester_length != 0)) {
- cerr << "Error: both a run length (-l) and a trace file (-z) have been specified." << endl;
- usageInstructions();
- }
- } else {
- cerr << "Error: either run length (-l) must be > 0 or a trace file (-z) must be specified." << endl;
- usageInstructions();
- }
}
static void usageInstructions()
@@ -408,10 +383,8 @@ static void usageInstructions()
counter++;
}
- cerr << "Option --processors (-p) is required." << endl;
- cerr << "Either option --length (-l) or --trace_input (-z) must be specified." << endl;
cerr << endl;
- g_debug_ptr->usageInstructions();
+ debug_ptr->usageInstructions();
cerr << endl;
exit(1);
diff --git a/src/mem/ruby/tester/test_framework.hh b/src/mem/ruby/tester/test_framework.hh
index 5e9e9363b..ade27a78f 100644
--- a/src/mem/ruby/tester/test_framework.hh
+++ b/src/mem/ruby/tester/test_framework.hh
@@ -37,10 +37,8 @@
#ifndef TESTFRAMEWORK_H
#define TESTFRAMEWORK_H
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/interfaces/mf_api.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
void tester_main(int argc, char **argv);
-void tester_install_opal( mf_opal_api_t *opal_api, mf_ruby_api_t *ruby_api );
#endif //TESTFRAMEWORK_H