summaryrefslogtreecommitdiff
path: root/src/mem/ruby/tester
diff options
context:
space:
mode:
authorNathan Binkert <nate@binkert.org>2009-07-06 15:49:47 -0700
committerNathan Binkert <nate@binkert.org>2009-07-06 15:49:47 -0700
commit92de70b69aaf3f399a855057b556ed198139e5d8 (patch)
treef8e7d0d494df8810cc960be4c52d8b555471f157 /src/mem/ruby/tester
parent05f6a4a6b92370162da17ef5cccb5a7e3ba508e5 (diff)
downloadgem5-92de70b69aaf3f399a855057b556ed198139e5d8.tar.xz
ruby: Import the latest ruby changes from gems.
This was done with an automated process, so there could be things that were done in this tree in the past that didn't make it. One known regression is that atomic memory operations do not seem to work properly anymore.
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