# Node ID 663554ecf21e984d0e4a2569f98e71c7b463260c # Parent 0684c3a6cee6ba44f22280e3defd3aca35bd3c18 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 @@ -125,10 +125,15 @@ # # Tie the ruby tester ports to the ruby cpu read and write ports # - if ruby_port.support_data_reqs: - tester.cpuDataPort = ruby_port.slave - if ruby_port.support_inst_reqs: - tester.cpuInstPort = ruby_port.slave + if ruby_port.support_data_reqs and ruby_port.support_inst_reqs: + tester.cpuInstDataPort = ruby_port.slave + elif ruby_port.support_data_reqs: + tester.cpuDataPort = ruby_port.slave + elif ruby_port.support_inst_reqs: + tester.cpuInstPort = ruby_port.slave + + # Do not automatically retry stalled Ruby requests + ruby_port.no_retry_on_stall = True # # Tell each sequencer this is the ruby tester so that it diff --git a/configs/ruby/MESI_Three_Level.py b/configs/ruby/MESI_Three_Level.py --- a/configs/ruby/MESI_Three_Level.py +++ b/configs/ruby/MESI_Three_Level.py @@ -100,15 +100,33 @@ l0d_cache = L0Cache(size = '4096B', assoc = 1, is_icache = False, start_index_bit = block_size_bits, replacement_policy="LRU") - l0_cntrl = L0Cache_Controller(version = i*num_cpus_per_cluster + j, - Icache = l0i_cache, Dcache = l0d_cache, - send_evictions = send_evicts(options), - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + # the ruby random tester reuses num_cpus to specify the + # number of cpu ports connected to the tester object, which + # is stored in system.cpu. because there is only ever one + # tester object, num_cpus is not necessarily equal to the + # size of system.cpu; therefore if len(system.cpu) == 1 + # we use system.cpu[0] to set the clk_domain, thereby ensuring + # we don't index off the end of the cpu list. + if len(system.cpu) == 1: + l0_cntrl = L0Cache_Controller(version = i*num_cpus_per_cluster + j, + Icache = l0i_cache, Dcache = l0d_cache, + send_evictions = send_evicts(options), + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) - cpu_seq = RubySequencer(version = i, icache = l0i_cache, - clk_domain=system.cpu[i].clk_domain, - dcache = l0d_cache, ruby_system = ruby_system) + cpu_seq = RubySequencer(version = i, icache = l0i_cache, + clk_domain=system.cpu[0].clk_domain, + dcache = l0d_cache, ruby_system = ruby_system) + else: + l0_cntrl = L0Cache_Controller(version = i*num_cpus_per_cluster + j, + Icache = l0i_cache, Dcache = l0d_cache, + send_evictions = send_evicts(options), + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, icache = l0i_cache, + clk_domain=system.cpu[i].clk_domain, + dcache = l0d_cache, ruby_system = ruby_system) l0_cntrl.sequencer = cpu_seq diff --git a/configs/ruby/MESI_Two_Level.py b/configs/ruby/MESI_Two_Level.py --- a/configs/ruby/MESI_Two_Level.py +++ b/configs/ruby/MESI_Two_Level.py @@ -88,22 +88,47 @@ prefetcher = RubyPrefetcher.Prefetcher() - l1_cntrl = L1Cache_Controller(version = i, - L1Icache = l1i_cache, - L1Dcache = l1d_cache, - l2_select_num_bits = l2_bits, - send_evictions = send_evicts(options), - prefetcher = prefetcher, - ruby_system = ruby_system, - clk_domain=system.cpu[i].clk_domain, - transitions_per_cycle=options.ports, - enable_prefetch = False) + # the ruby random tester reuses num_cpus to specify the + # number of cpu ports connected to the tester object, which + # is stored in system.cpu. because there is only ever one + # tester object, num_cpus is not necessarily equal to the + # size of system.cpu; therefore if len(system.cpu) == 1 + # we use system.cpu[0] to set the clk_domain, thereby ensuring + # we don't index off the end of the cpu list. + if len(system.cpu) == 1: + l1_cntrl = L1Cache_Controller(version = i, + L1Icache = l1i_cache, + L1Dcache = l1d_cache, + l2_select_num_bits = l2_bits, + send_evictions = send_evicts(options), + prefetcher = prefetcher, + ruby_system = ruby_system, + clk_domain=system.cpu[0].clk_domain, + transitions_per_cycle=options.ports, + enable_prefetch = False) - cpu_seq = RubySequencer(version = i, - icache = l1i_cache, - dcache = l1d_cache, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) + else: + l1_cntrl = L1Cache_Controller(version = i, + L1Icache = l1i_cache, + L1Dcache = l1d_cache, + l2_select_num_bits = l2_bits, + send_evictions = send_evicts(options), + prefetcher = prefetcher, + ruby_system = ruby_system, + clk_domain=system.cpu[i].clk_domain, + transitions_per_cycle=options.ports, + enable_prefetch = False) + + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) l1_cntrl.sequencer = cpu_seq exec("ruby_system.l1_cntrl%d = l1_cntrl" % i) diff --git a/configs/ruby/MI_example.py b/configs/ruby/MI_example.py --- a/configs/ruby/MI_example.py +++ b/configs/ruby/MI_example.py @@ -75,21 +75,41 @@ assoc = options.l1d_assoc, start_index_bit = block_size_bits) - # - # Only one unified L1 cache exists. Can cache instructions and data. - # - l1_cntrl = L1Cache_Controller(version = i, - cacheMemory = cache, - send_evictions = send_evicts(options), - transitions_per_cycle = options.ports, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) - cpu_seq = RubySequencer(version = i, - icache = cache, - dcache = cache, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + # the ruby random tester reuses num_cpus to specify the + # number of cpu ports connected to the tester object, which + # is stored in system.cpu. because there is only ever one + # tester object, num_cpus is not necessarily equal to the + # size of system.cpu; therefore if len(system.cpu) == 1 + # we use system.cpu[0] to set the clk_domain, thereby ensuring + # we don't index off the end of the cpu list. + if len(system.cpu) == 1: + # Only one unified L1 cache exists. Can cache instructions and data. + l1_cntrl = L1Cache_Controller(version = i, + cacheMemory = cache, + send_evictions = send_evicts(options), + transitions_per_cycle = options.ports, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = cache, + dcache = cache, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) + else: + l1_cntrl = L1Cache_Controller(version = i, + cacheMemory = cache, + send_evictions = send_evicts(options), + transitions_per_cycle = options.ports, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = cache, + dcache = cache, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) l1_cntrl.sequencer = cpu_seq exec("ruby_system.l1_cntrl%d = l1_cntrl" % i) diff --git a/configs/ruby/MOESI_CMP_directory.py b/configs/ruby/MOESI_CMP_directory.py --- a/configs/ruby/MOESI_CMP_directory.py +++ b/configs/ruby/MOESI_CMP_directory.py @@ -86,20 +86,43 @@ start_index_bit = block_size_bits, is_icache = False) - l1_cntrl = L1Cache_Controller(version = i, - L1Icache = l1i_cache, - L1Dcache = l1d_cache, - l2_select_num_bits = l2_bits, - send_evictions = send_evicts(options), - transitions_per_cycle = options.ports, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + # the ruby random tester reuses num_cpus to specify the + # number of cpu ports connected to the tester object, which + # is stored in system.cpu. because there is only ever one + # tester object, num_cpus is not necessarily equal to the + # size of system.cpu; therefore if len(system.cpu) == 1 + # we use system.cpu[0] to set the clk_domain, thereby ensuring + # we don't index off the end of the cpu list. + if len(system.cpu): + l1_cntrl = L1Cache_Controller(version = i, + L1Icache = l1i_cache, + L1Dcache = l1d_cache, + l2_select_num_bits = l2_bits, + send_evictions = send_evicts(options), + transitions_per_cycle = options.ports, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) - cpu_seq = RubySequencer(version = i, - icache = l1i_cache, - dcache = l1d_cache, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) + else: + l1_cntrl = L1Cache_Controller(version = i, + L1Icache = l1i_cache, + L1Dcache = l1d_cache, + l2_select_num_bits = l2_bits, + send_evictions = send_evicts(options), + transitions_per_cycle = options.ports, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) l1_cntrl.sequencer = cpu_seq exec("ruby_system.l1_cntrl%d = l1_cntrl" % i) diff --git a/configs/ruby/MOESI_CMP_token.py b/configs/ruby/MOESI_CMP_token.py --- a/configs/ruby/MOESI_CMP_token.py +++ b/configs/ruby/MOESI_CMP_token.py @@ -97,29 +97,61 @@ assoc = options.l1d_assoc, start_index_bit = block_size_bits) - l1_cntrl = L1Cache_Controller(version = i, - L1Icache = l1i_cache, - L1Dcache = l1d_cache, - l2_select_num_bits = l2_bits, - N_tokens = n_tokens, - retry_threshold = \ - options.l1_retries, - fixed_timeout_latency = \ - options.timeout_latency, - dynamic_timeout_enabled = \ - not options.disable_dyn_timeouts, - no_mig_atomic = not \ - options.allow_atomic_migration, - send_evictions = send_evicts(options), - transitions_per_cycle = options.ports, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + # the ruby random tester reuses num_cpus to specify the + # number of cpu ports connected to the tester object, which + # is stored in system.cpu. because there is only ever one + # tester object, num_cpus is not necessarily equal to the + # size of system.cpu; therefore if len(system.cpu) == 1 + # we use system.cpu[0] to set the clk_domain, thereby ensuring + # we don't index off the end of the cpu list. + if len(system.cpu) == 1: + l1_cntrl = L1Cache_Controller(version = i, + L1Icache = l1i_cache, + L1Dcache = l1d_cache, + l2_select_num_bits = l2_bits, + N_tokens = n_tokens, + retry_threshold = \ + options.l1_retries, + fixed_timeout_latency = \ + options.timeout_latency, + dynamic_timeout_enabled = \ + not options.disable_dyn_timeouts, + no_mig_atomic = not \ + options.allow_atomic_migration, + send_evictions = send_evicts(options), + transitions_per_cycle = options.ports, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) - cpu_seq = RubySequencer(version = i, - icache = l1i_cache, - dcache = l1d_cache, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) + else: + l1_cntrl = L1Cache_Controller(version = i, + L1Icache = l1i_cache, + L1Dcache = l1d_cache, + l2_select_num_bits = l2_bits, + N_tokens = n_tokens, + retry_threshold = \ + options.l1_retries, + fixed_timeout_latency = \ + options.timeout_latency, + dynamic_timeout_enabled = \ + not options.disable_dyn_timeouts, + no_mig_atomic = not \ + options.allow_atomic_migration, + send_evictions = send_evicts(options), + transitions_per_cycle = options.ports, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) l1_cntrl.sequencer = cpu_seq exec("ruby_system.l1_cntrl%d = l1_cntrl" % i) diff --git a/configs/ruby/MOESI_hammer.py b/configs/ruby/MOESI_hammer.py --- a/configs/ruby/MOESI_hammer.py +++ b/configs/ruby/MOESI_hammer.py @@ -97,22 +97,47 @@ assoc = options.l2_assoc, start_index_bit = block_size_bits) - l1_cntrl = L1Cache_Controller(version = i, - L1Icache = l1i_cache, - L1Dcache = l1d_cache, - L2cache = l2_cache, - no_mig_atomic = not \ - options.allow_atomic_migration, - send_evictions = send_evicts(options), - transitions_per_cycle = options.ports, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + # the ruby random tester reuses num_cpus to specify the + # number of cpu ports connected to the tester object, which + # is stored in system.cpu. because there is only ever one + # tester object, num_cpus is not necessarily equal to the + # size of system.cpu; therefore if len(system.cpu) == 1 + # we use system.cpu[0] to set the clk_domain, thereby ensuring + # we don't index off the end of the cpu list. + if len(system.cpu) == 1: + l1_cntrl = L1Cache_Controller(version = i, + L1Icache = l1i_cache, + L1Dcache = l1d_cache, + L2cache = l2_cache, + no_mig_atomic = not \ + options.allow_atomic_migration, + send_evictions = send_evicts(options), + transitions_per_cycle = options.ports, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) - cpu_seq = RubySequencer(version = i, - icache = l1i_cache, - dcache = l1d_cache, - clk_domain=system.cpu[i].clk_domain, - ruby_system = ruby_system) + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + clk_domain=system.cpu[0].clk_domain, + ruby_system = ruby_system) + else: + l1_cntrl = L1Cache_Controller(version = i, + L1Icache = l1i_cache, + L1Dcache = l1d_cache, + L2cache = l2_cache, + no_mig_atomic = not \ + options.allow_atomic_migration, + send_evictions = send_evicts(options), + transitions_per_cycle = options.ports, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) + + cpu_seq = RubySequencer(version = i, + icache = l1i_cache, + dcache = l1d_cache, + clk_domain=system.cpu[i].clk_domain, + ruby_system = ruby_system) l1_cntrl.sequencer = cpu_seq if options.recycle_latency: 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 @@ -96,7 +96,9 @@ cmd = MemCmd::ReadReq; // if necessary, make the request an instruction fetch - if (m_tester_ptr->isInstReadableCpuPort(index)) { + if (m_tester_ptr->isInstOnlyCpuPort(index) || + (m_tester_ptr->isInstDataCpuPort(index) && + (random_mt.random(0, 0x1)))) { flags.set(Request::INST_FETCH); } } else { @@ -178,7 +180,7 @@ // Stores are assumed to be 1 byte-sized Request *req = new Request(writeAddr.getAddress(), 1, flags, - m_tester_ptr->masterId(), curTick(), + m_tester_ptr->masterId(), curTick(), m_pc.getAddress()); req->setThreadContext(index, 0); @@ -208,6 +210,7 @@ DPRINTF(RubyTest, "status before action update: %s\n", (TesterStatus_to_string(m_status)).c_str()); m_status = TesterStatus_Action_Pending; + DPRINTF(RubyTest, "Check %s, State=Action_Pending\n", m_address); } else { // If the packet did not issue, must delete // Note: No need to delete the data, the packet destructor @@ -235,13 +238,16 @@ Request::Flags flags; // If necessary, make the request an instruction fetch - if (m_tester_ptr->isInstReadableCpuPort(index)) { + if (m_tester_ptr->isInstOnlyCpuPort(index) || + (m_tester_ptr->isInstDataCpuPort(index) && + (random_mt.random(0, 0x1)))) { flags.set(Request::INST_FETCH); } // Checks are sized depending on the number of bytes written Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags, - m_tester_ptr->masterId(), curTick(), m_pc.getAddress()); + m_tester_ptr->masterId(), curTick(), + m_pc.getAddress()); req->setThreadContext(index, 0); PacketPtr pkt = new Packet(req, MemCmd::ReadReq); @@ -257,6 +263,7 @@ DPRINTF(RubyTest, "status before check update: %s\n", TesterStatus_to_string(m_status).c_str()); m_status = TesterStatus_Check_Pending; + DPRINTF(RubyTest, "Check %s, State=Check_Pending\n", m_address); } else { // If the packet did not issue, must delete // Note: No need to delete the data, the packet destructor @@ -294,8 +301,11 @@ m_store_count++; if (m_store_count == CHECK_SIZE) { m_status = TesterStatus_Ready; + DPRINTF(RubyTest, "Check %s, State=Ready\n", m_address); } else { m_status = TesterStatus_Idle; + DPRINTF(RubyTest, "Check %s, State=Idle store_count: %d\n", + m_address, m_store_count); } DPRINTF(RubyTest, "Action callback return data now %d\n", data->getByte(0)); @@ -319,6 +329,7 @@ m_tester_ptr->incrementCheckCompletions(); m_status = TesterStatus_Idle; + DPRINTF(RubyTest, "Check %s, State=Idle\n", m_address); pickValue(); } else { @@ -338,6 +349,7 @@ assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready); m_status = TesterStatus_Idle; m_address = address; + DPRINTF(RubyTest, "Check %s, State=Idle\n", m_address); m_store_count = 0; } @@ -345,7 +357,6 @@ Check::pickValue() { assert(m_status == TesterStatus_Idle); - m_status = TesterStatus_Idle; m_value = random_mt.random(0, 0xff); // One byte m_store_count = 0; } @@ -356,7 +367,8 @@ assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready); m_status = TesterStatus_Idle; m_initiatingNode = (random_mt.random(0, m_num_writers - 1)); - DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode); + DPRINTF(RubyTest, "Check %s, State=Idle, picked initiating node %d\n", + m_address, m_initiatingNode); m_store_count = 0; } 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 @@ -43,6 +43,7 @@ const int size1 = 32; const int size2 = 100; + DPRINTF(RubyTest, "Adding false sharing checks\n"); // The first set is to get some false sharing physical = 1000; for (int i = 0; i < size1; i++) { @@ -52,6 +53,7 @@ physical += CHECK_SIZE; } + DPRINTF(RubyTest, "Adding cache conflict checks\n"); // The next two sets are to get some limited false sharing and // cache conflicts physical = 1000; @@ -62,6 +64,7 @@ physical += 256; } + DPRINTF(RubyTest, "Adding cache conflict checks2\n"); physical = 1000 + CHECK_SIZE; for (int i = 0; i < size2; i++) { // Setup linear addresses @@ -95,6 +98,8 @@ } } + DPRINTF(RubyTest, "Adding check for address: %s\n", address); + Check* check_ptr = new Check(address, Address(100 + m_check_vector.size()), m_num_writers, m_num_readers, m_tester_ptr); for (int i = 0; i < CHECK_SIZE; i++) { @@ -114,7 +119,7 @@ Check* CheckTable::getCheck(const Address& address) { - DPRINTF(RubyTest, "Looking for check by address: %s", address); + DPRINTF(RubyTest, "Looking for check by address: %s\n", address); m5::hash_map
::iterator i = m_lookup_map.find(address); 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 @@ -94,7 +94,8 @@ virtual BaseMasterPort &getMasterPort(const std::string &if_name, PortID idx = InvalidPortID); - bool isInstReadableCpuPort(int idx); + bool isInstOnlyCpuPort(int idx); + bool isInstDataCpuPort(int idx); MasterPort* getReadableCpuPort(int idx); MasterPort* getWritableCpuPort(int idx); @@ -153,7 +154,8 @@ int m_num_readers; int m_wakeup_frequency; bool m_check_flush; - int m_num_inst_ports; + int m_num_inst_only_ports; + int m_num_inst_data_ports; }; inline std::ostream& diff --git a/src/cpu/testers/rubytest/RubyTester.cc b/src/cpu/testers/rubytest/RubyTester.cc --- a/src/cpu/testers/rubytest/RubyTester.cc +++ b/src/cpu/testers/rubytest/RubyTester.cc @@ -60,7 +60,8 @@ m_num_readers(0), m_wakeup_frequency(p->wakeup_frequency), m_check_flush(p->check_flush), - m_num_inst_ports(p->port_cpuInstPort_connection_count) + m_num_inst_only_ports(p->port_cpuInstPort_connection_count), + m_num_inst_data_ports(p->port_cpuInstDataPort_connection_count) { m_checks_completed = 0; @@ -75,15 +76,25 @@ // Note: the inst ports are the lowest elements of the readPort vector, // then the data ports are added to the readPort vector // + int idx = 0; for (int i = 0; i < p->port_cpuInstPort_connection_count; ++i) { readPorts.push_back(new CpuPort(csprintf("%s-instPort%d", name(), i), - this, i)); + this, idx)); + idx++; + } + for (int i = 0; i < p->port_cpuInstDataPort_connection_count; ++i) { + CpuPort *port = new CpuPort(csprintf("%s-instDataPort%d", name(), i), + this, idx); + readPorts.push_back(port); + writePorts.push_back(port); + idx++; } for (int i = 0; i < p->port_cpuDataPort_connection_count; ++i) { CpuPort *port = new CpuPort(csprintf("%s-dataPort%d", name(), i), - this, i); + this, idx); readPorts.push_back(port); writePorts.push_back(port); + idx++; } // add the check start event to the event queue @@ -117,32 +128,45 @@ BaseMasterPort & RubyTester::getMasterPort(const std::string &if_name, PortID idx) { - if (if_name != "cpuInstPort" && if_name != "cpuDataPort") { + if (if_name != "cpuInstPort" && if_name != "cpuInstDataPort" && + if_name != "cpuDataPort") { // pass it along to our super class return MemObject::getMasterPort(if_name, idx); } else { if (if_name == "cpuInstPort") { - if (idx > m_num_inst_ports) { - panic("RubyTester::getMasterPort: unknown inst port idx %d\n", + if (idx > m_num_inst_only_ports) { + panic("RubyTester::getMasterPort: unknown inst port %d\n", idx); } // - // inst ports directly map to the lowest readPort elements + // inst ports map to the lowest readPort elements // return *readPorts[idx]; + } else if (if_name == "cpuInstDataPort") { + if (idx > m_num_inst_data_ports) { + panic("RubyTester::getMasterPort: unknown inst+data port %d\n", + idx); + } + int read_idx = idx + m_num_inst_only_ports; + // + // inst+data ports map to the next readPort elements + // + return *readPorts[read_idx]; } else { assert(if_name == "cpuDataPort"); // - // add the inst port offset to translate to the correct read port - // index + // data only ports map to the final readPort elements // - int read_idx = idx + m_num_inst_ports; - if (read_idx >= static_cast