diff --git a/configs/example/ruby_random_test.py b/configs/example/ruby_random_test.py --- a/configs/example/ruby_random_test.py +++ b/configs/example/ruby_random_test.py @@ -87,7 +87,8 @@ tester = RubyTester(check_flush = check_flush, checks_to_complete = options.checks, - wakeup_frequency = options.wakeup_freq) + wakeup_frequency = options.wakeup_freq, + num_cpus = options.num_cpus) # # Create the M5 system. Note that the PhysicalMemory Object isn't @@ -108,9 +109,12 @@ for ruby_port in system.ruby._cpu_ruby_ports: # - # Tie the ruby tester ports to the ruby cpu ports + # Tie the ruby tester ports to the ruby cpu read and write ports # - tester.cpuPort = ruby_port.slave + if ruby_port.support_data_reqs: + tester.cpuDataPort = ruby_port.slave + if ruby_port.support_inst_reqs: + tester.cpuInstPort = ruby_port.slave # # Tell each sequencer this is the ruby tester so that it diff --git a/src/cpu/testers/rubytest/Check.hh b/src/cpu/testers/rubytest/Check.hh --- a/src/cpu/testers/rubytest/Check.hh +++ b/src/cpu/testers/rubytest/Check.hh @@ -46,8 +46,8 @@ class Check { public: - Check(const Address& address, const Address& pc, int _num_cpu_sequencer, - RubyTester* _tester); + Check(const Address& address, const Address& pc, int _num_writers, + int _num_readers, RubyTester* _tester); void initiate(); // Does Action or Check or nether void performCallback(NodeID proc, SubBlock* data); @@ -74,7 +74,8 @@ Address m_address; Address m_pc; RubyAccessMode m_access_mode; - int m_num_cpu_sequencers; + int m_num_writers; + int m_num_readers; RubyTester* m_tester_ptr; }; diff --git a/src/cpu/testers/rubytest/Check.cc b/src/cpu/testers/rubytest/Check.cc --- a/src/cpu/testers/rubytest/Check.cc +++ b/src/cpu/testers/rubytest/Check.cc @@ -36,8 +36,9 @@ typedef RubyTester::SenderState SenderState; Check::Check(const Address& address, const Address& pc, - int _num_cpu_sequencers, RubyTester* _tester) - : m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester) + int _num_writers, int _num_readers, RubyTester* _tester) + : m_num_writers(_num_writers), m_num_readers(_num_readers), + m_tester_ptr(_tester) { m_status = TesterStatus_Idle; @@ -80,9 +81,9 @@ { DPRINTF(RubyTest, "initiating prefetch\n"); - int index = random() % m_num_cpu_sequencers; + int index = random() % m_num_readers; RubyTester::CpuPort* port = - safe_cast(m_tester_ptr->getCpuPort(index)); + safe_cast(m_tester_ptr->getCpuReadPort(index)); Request::Flags flags; flags.set(Request::PREFETCH); @@ -93,8 +94,8 @@ if ((random() & 0x7) != 0) { cmd = MemCmd::ReadReq; - // 50% chance that the request will be an instruction fetch - if ((random() & 0x1) == 0) { + // if necessary, make the request an instruction fetch + if (port->type == RubyTester::CpuPort::InstOnly) { flags.set(Request::INST_FETCH); } } else { @@ -135,9 +136,9 @@ DPRINTF(RubyTest, "initiating Flush\n"); - int index = random() % m_num_cpu_sequencers; + int index = random() % m_num_writers; RubyTester::CpuPort* port = - safe_cast(m_tester_ptr->getCpuPort(index)); + safe_cast(m_tester_ptr->getCpuWritePort(index)); Request::Flags flags; @@ -166,9 +167,9 @@ DPRINTF(RubyTest, "initiating Action\n"); assert(m_status == TesterStatus_Idle); - int index = random() % m_num_cpu_sequencers; + int index = random() % m_num_writers; RubyTester::CpuPort* port = - safe_cast(m_tester_ptr->getCpuPort(index)); + safe_cast(m_tester_ptr->getCpuWritePort(index)); Request::Flags flags; @@ -231,14 +232,14 @@ DPRINTF(RubyTest, "Initiating Check\n"); assert(m_status == TesterStatus_Ready); - int index = random() % m_num_cpu_sequencers; + int index = random() % m_num_readers; RubyTester::CpuPort* port = - safe_cast(m_tester_ptr->getCpuPort(index)); + safe_cast(m_tester_ptr->getCpuReadPort(index)); Request::Flags flags; - // 50% chance that the request will be an instruction fetch - if ((random() & 0x1) == 0) { + // If necessary, make the request an instruction fetch + if (port->type == RubyTester::CpuPort::InstOnly) { flags.set(Request::INST_FETCH); } @@ -363,7 +364,7 @@ { assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready); m_status = TesterStatus_Idle; - m_initiatingNode = (random() % m_num_cpu_sequencers); + m_initiatingNode = (random() % m_num_writers); DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode); m_store_count = 0; } diff --git a/src/cpu/testers/rubytest/CheckTable.hh b/src/cpu/testers/rubytest/CheckTable.hh --- a/src/cpu/testers/rubytest/CheckTable.hh +++ b/src/cpu/testers/rubytest/CheckTable.hh @@ -43,7 +43,7 @@ class CheckTable { public: - CheckTable(int _num_cpu_sequencers, RubyTester* _tester); + CheckTable(int _num_writers, int _num_readers, RubyTester* _tester); ~CheckTable(); Check* getRandomCheck(); @@ -66,7 +66,8 @@ std::vector m_check_vector; m5::hash_map m_lookup_map; - int m_num_cpu_sequencers; + int m_num_writers; + int m_num_readers; RubyTester* m_tester_ptr; }; diff --git a/src/cpu/testers/rubytest/CheckTable.cc b/src/cpu/testers/rubytest/CheckTable.cc --- a/src/cpu/testers/rubytest/CheckTable.cc +++ b/src/cpu/testers/rubytest/CheckTable.cc @@ -32,8 +32,9 @@ #include "cpu/testers/rubytest/CheckTable.hh" #include "debug/RubyTest.hh" -CheckTable::CheckTable(int _num_cpu_sequencers, RubyTester* _tester) - : m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester) +CheckTable::CheckTable(int _num_writers, int _num_readers, RubyTester* _tester) + : m_num_writers(_num_writers), m_num_readers(_num_readers), + m_tester_ptr(_tester) { physical_address_t physical = 0; Address address; @@ -94,7 +95,7 @@ } Check* check_ptr = new Check(address, Address(100 + m_check_vector.size()), - m_num_cpu_sequencers, m_tester_ptr); + m_num_writers, m_num_readers, m_tester_ptr); for (int i = 0; i < CHECK_SIZE; i++) { // Insert it once per byte m_lookup_map[Address(address.getAddress() + i)] = check_ptr; diff --git a/src/cpu/testers/rubytest/RubyTester.hh b/src/cpu/testers/rubytest/RubyTester.hh --- a/src/cpu/testers/rubytest/RubyTester.hh +++ b/src/cpu/testers/rubytest/RubyTester.hh @@ -51,11 +51,28 @@ RubyTester *tester; public: - CpuPort(const std::string &_name, RubyTester *_tester, int _idx) - : MasterPort(_name, _tester), tester(_tester), idx(_idx) + // + // Currently, each instatiation of the RubyTester::CpuPort supports + // only instruction or data requests, not both. However, for those + // RubyPorts that support both types of requests, separate InstOnly + // and DataOnly CpuPorts will map to that RubyPort + // + enum Type + { + // Port supports only instruction requests + InstOnly, + // Port supports only data requests + DataOnly + }; + + CpuPort(const std::string &_name, RubyTester *_tester, int _idx, + Type _type) + : MasterPort(_name, _tester), tester(_tester), idx(_idx), + type(_type) {} int idx; + Type type; protected: virtual bool recvTiming(PacketPtr pkt); @@ -90,7 +107,8 @@ virtual MasterPort &getMasterPort(const std::string &if_name, int idx = -1); - MasterPort* getCpuPort(int idx); + MasterPort* getCpuReadPort(int idx); + MasterPort* getCpuWritePort(int idx); virtual void init(); @@ -136,13 +154,17 @@ CheckTable* m_checkTable_ptr; std::vector