From: Nathan Binkert Date: Mon, 6 Jul 2009 22:49:47 +0000 (-0700) Subject: ruby: Fix RubyMemory to work with the newer ruby. X-Git-Tag: Calvin_Submission~229 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=da704f52e55dd2649e53bf233f948c897727f13d;p=gem5.git ruby: Fix RubyMemory to work with the newer ruby. --- diff --git a/src/mem/RubyMemory.py b/src/mem/RubyMemory.py index 2daf82071..fbbbeebe4 100644 --- a/src/mem/RubyMemory.py +++ b/src/mem/RubyMemory.py @@ -35,12 +35,11 @@ class RubyMemory(PhysicalMemory): type = 'RubyMemory' clock = Param.Clock('1t', "ruby clock speed") phase = Param.Latency('0ns', "ruby clock phase") - config_file = Param.String("", "path to the Ruby config file") - config_options = Param.String("", "extra Ruby options (one per line)") + config_file = Param.String("path to the Ruby config file") stats_file = Param.String("ruby.stats", "file to which ruby dumps its stats") num_cpus = Param.Int(1, "Number of CPUs connected to the Ruby memory") debug = Param.Bool(False, "Use ruby debug") - debug_file = Param.String("", + debug_file = Param.String("ruby.debug", "path to the Ruby debug output file (stdout if blank)") diff --git a/src/mem/ruby/SConsopts b/src/mem/ruby/SConsopts index 848d0b972..2b325ff33 100644 --- a/src/mem/ruby/SConsopts +++ b/src/mem/ruby/SConsopts @@ -36,7 +36,10 @@ if not main['RUBY']: sticky_vars.AddVariables( BoolVariable('NO_VECTOR_BOUNDS_CHECKS', "Don't do bounds checks", True), BoolVariable('RUBY_DEBUG', "Add debugging stuff to Ruby", False), - ('GEMS_ROOT', "Add debugging stuff to Ruby", Dir('..').srcnode().abspath)) + ('GEMS_ROOT', "Add debugging stuff to Ruby", Dir('..').srcnode().abspath), + BoolVariable('RUBY_TSO_CHECKER', "Use the Ruby TSO Checker", False) + ) -export_vars += [ 'NO_VECTOR_BOUNDS_CHECKS', 'RUBY_DEBUG', 'GEMS_ROOT' ] +export_vars += [ 'NO_VECTOR_BOUNDS_CHECKS', 'RUBY_DEBUG', 'GEMS_ROOT', + 'RUBY_TSO_CHECKER' ] diff --git a/src/mem/ruby/storebuffer/storebuffer.cc b/src/mem/ruby/storebuffer/storebuffer.cc index 865a31820..ed97b216c 100644 --- a/src/mem/ruby/storebuffer/storebuffer.cc +++ b/src/mem/ruby/storebuffer/storebuffer.cc @@ -36,7 +36,7 @@ #include "mem/ruby/storebuffer/storebuffer.hh" #include "mem/ruby/common/Global.hh" -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER #include "TsoChecker.hh" #endif @@ -46,7 +46,7 @@ // global map of request id_s to map them back to storebuffer pointers map request_map; -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER Tso::TsoChecker * g_tsoChecker; #endif @@ -65,7 +65,7 @@ void hit(int64_t id) { //***************************************************************************************** StoreBuffer::StoreBuffer(uint32 id, uint32 block_bits, int storebuffer_size) { -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER if (id == 0) { g_tsoChecker = new Tso::TsoChecker(); g_tsoChecker->init(64); @@ -99,7 +99,7 @@ StoreBuffer::StoreBuffer(uint32 id, uint32 block_bits, int storebuffer_size) { //****************************************************************************************** StoreBuffer::~StoreBuffer(){ -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER if (m_id == 0) { delete g_tsoChecker; } @@ -272,7 +272,7 @@ void StoreBuffer::returnMatchedData(struct RubyRequest request) { ASSERT(checkForLoadHit(request) != NO_MATCH); physical_address_t lineaddr = physical_address & m_block_mask; bool found = false; -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER Tso::TsoCheckerCmd * cmd; #endif deque::iterator satisfying_store; @@ -280,7 +280,7 @@ void StoreBuffer::returnMatchedData(struct RubyRequest request) { if ((it->m_request.paddr & m_block_mask) == lineaddr) { if (!found) { found = true; -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER satisfying_store = it; cmd = new Tso::TsoCheckerCmd(m_id, // this thread id iseq, // instruction sequence @@ -313,7 +313,7 @@ void StoreBuffer::returnMatchedData(struct RubyRequest request) { } } -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER uint64_t tso_data = 0; memcpy(&tso_data, request.data, request.len); cmd->setData(tso_data); @@ -400,7 +400,7 @@ void StoreBuffer::complete(uint64_t id) { m_buffer_size--; ASSERT(m_buffer_size >= 0); -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER int len = outstanding_requests.find(id)->second.len; uint64_t data = 0; memcpy(&data, from_buffer.m_request.data, 4); @@ -462,7 +462,7 @@ void StoreBuffer::complete(uint64_t id) { #endif } // end if (type == ST) else if (type == RubyRequestType_LD) { -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER RubyRequest request = outstanding_requests.find(id)->second; uint64_t data = 0; memcpy(&data, request.data, request.len); @@ -511,7 +511,7 @@ void StoreBuffer::complete(uint64_t id) { } } -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER void StoreBuffer::insertTsoLL(Tso::TsoCheckerCmd * cmd) { uint64_t count = cmd->getIseq(); Tso::TsoCheckerCmd * current = NULL; diff --git a/src/mem/ruby/storebuffer/storebuffer.hh b/src/mem/ruby/storebuffer/storebuffer.hh index 4117a8f38..67555f48f 100644 --- a/src/mem/ruby/storebuffer/storebuffer.hh +++ b/src/mem/ruby/storebuffer/storebuffer.hh @@ -36,7 +36,7 @@ #include "mem/ruby/storebuffer/hfa.hh" #include "mem/ruby/libruby.hh" -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER #include "TsoCheckerCmd.hh" #endif @@ -53,13 +53,13 @@ enum load_match { NO_MATCH, PARTIAL_MATCH, FULL_MATCH }; struct SBEntry { struct RubyRequest m_request; -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER Tso::TsoCheckerCmd * m_next_ptr; #endif SBEntry(struct RubyRequest request, void * ptr) : m_request(request) { -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER m_next_ptr = (Tso::TsoCheckerCmd*) ptr; #endif } @@ -101,7 +101,7 @@ class StoreBuffer { /// prints out the contents of the Write Buffer void print(); -#ifdef RUBY_TSO_CHECKER +#if RUBY_TSO_CHECKER /// if load completes before store, insert correctly to be issued to TSOChecker void insertTsoLL(Tso::TsoCheckerCmd * cmd); #endif diff --git a/src/mem/rubymem.cc b/src/mem/rubymem.cc index 83bac2fd5..62685a71b 100644 --- a/src/mem/rubymem.cc +++ b/src/mem/rubymem.cc @@ -33,9 +33,11 @@ #include "arch/isa_traits.hh" #include "base/output.hh" +#include "base/str.hh" #include "base/types.hh" #include "mem/ruby/common/Debug.hh" -#include "mem/ruby/init.hh" +#include "mem/ruby/libruby.hh" +#include "mem/ruby/system/RubyPort.hh" #include "mem/ruby/system/Sequencer.hh" #include "mem/ruby/system/System.hh" #include "mem/rubymem.hh" @@ -45,33 +47,54 @@ using namespace std; using namespace TheISA; +map RubyMemory::pending_requests; + RubyMemory::RubyMemory(const Params *p) : PhysicalMemory(p) { - config_file = p->config_file; - config_options = p->config_options; - stats_file = p->stats_file; - num_cpus = p->num_cpus; ruby_clock = p->clock; ruby_phase = p->phase; - debug = p->debug; - debug_file = p->debug_file; + ifstream config(p->config_file.c_str()); + + vector sys_conf; + while (!config.eof()) { + char buffer[4096]; + config.getline(buffer, sizeof(buffer)); + string line = buffer; + if (line.empty()) + continue; + vector tokens; + tokenize(tokens, line, ' '); + assert(tokens.size() >= 2); + vector argv; + for (size_t i=2; inum_cpus; i++) { + RubyPort *p = RubySystem::getPort(csprintf("Sequencer_%d", i), + ruby_hit_callback); + ruby_ports.push_back(p); + } } void RubyMemory::init() { - init_variables(); - g_NUM_PROCESSORS = num_cpus; - - init_simulator(this); - - if (debug) { + if (params()->debug) { g_debug_ptr->setVerbosityString("high"); g_debug_ptr->setDebugTime(1); - if (debug_file != "") { - g_debug_ptr->setDebugOutputFile("ruby.debug"); + if (!params()->debug_file.empty()) { + g_debug_ptr->setDebugOutputFile(params()->debug_file.c_str()); } } @@ -104,23 +127,21 @@ RubyMemory::init() } //called by rubyTickEvent -void RubyMemory::tick() { - g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 1); - schedule(rubyTickEvent, curTick + ruby_clock); //dsm: clock_phase was added here. This is wrong, the phase is only added on the first tick +void +RubyMemory::tick() +{ + RubyEventQueue *eq = RubySystem::getEventQueue(); + eq->triggerEvents(eq->getTime() + 1); + schedule(rubyTickEvent, curTick + ruby_clock); } - -RubyMemory::~RubyMemory() { - delete g_system_ptr; +RubyMemory::~RubyMemory() +{ } void -RubyMemory::hitCallback(Packet* pkt) +RubyMemory::hitCallback(PacketPtr pkt, Port *port) { - RubyMemoryPort* port = m_packet_to_port_map[pkt]; - assert(port != NULL); - m_packet_to_port_map.erase(pkt); - DPRINTF(MemoryAccess, "Hit callback\n"); bool needsResponse = pkt->needsResponse(); @@ -146,7 +167,7 @@ RubyMemory::getPort(const std::string &if_name, int idx) // with places where this function is called from C++. I'd prefer // to move all these into Python someday. if (if_name == "functional") { - return new RubyMemoryPort(csprintf("%s-functional", name()), this); + return new Port(csprintf("%s-functional", name()), this); } if (if_name != "port") { @@ -161,22 +182,20 @@ RubyMemory::getPort(const std::string &if_name, int idx) panic("RubyMemory::getPort: port %d already assigned", idx); } - RubyMemoryPort *port = - new RubyMemoryPort(csprintf("%s-port%d", name(), idx), this); + Port *port = new Port(csprintf("%s-port%d", name(), idx), this); ports[idx] = port; return port; } -RubyMemory::RubyMemoryPort::RubyMemoryPort(const std::string &_name, - RubyMemory *_memory) +RubyMemory::Port::Port(const std::string &_name, RubyMemory *_memory) : PhysicalMemory::MemoryPort::MemoryPort(_name, _memory) { ruby_mem = _memory; } bool -RubyMemory::RubyMemoryPort::recvTiming(PacketPtr pkt) +RubyMemory::Port::recvTiming(PacketPtr pkt) { DPRINTF(MemoryAccess, "Timing access caught\n"); @@ -197,33 +216,83 @@ RubyMemory::RubyMemoryPort::recvTiming(PacketPtr pkt) return true; } - ruby_mem->m_packet_to_port_map[pkt] = this; - - Sequencer* sequencer = g_system_ptr->getSequencer(pkt->req->contextId()); + // Save the port in the sender state object + pkt->senderState = new SenderState(this, pkt->senderState); + + RubyRequestType type = RubyRequestType_NULL; + Addr pc = 0; + if (pkt->isRead()) { + if (pkt->req->isInstFetch()) { + type = RubyRequestType_IFETCH; + pc = pkt->req->getPC(); + } else { + type = RubyRequestType_LD; + } + } else if (pkt->isWrite()) { + type = RubyRequestType_ST; + } else if (pkt->isReadWrite()) { + type = RubyRequestType_RMW; + } - if ( ! sequencer->isReady(pkt) ) { - DPRINTF(MemoryAccess, "Sequencer isn't ready yet!!\n"); - return false; + RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr(), + pkt->getSize(), pc, type, + RubyAccessMode_Supervisor); + + // Submit the ruby request + RubyPort *ruby_port = ruby_mem->ruby_ports[pkt->req->contextId()]; + int64_t req_id = ruby_port->makeRequest(ruby_request); + if (req_id == -1) { + RubyMemory::SenderState *senderState = + safe_cast(pkt->senderState); + + // pop the sender state from the packet + pkt->senderState = senderState->saved; + delete senderState; + return false; } - DPRINTF(MemoryAccess, "Issuing makeRequest\n"); + // Save the request for the callback + RubyMemory::pending_requests[req_id] = pkt; - sequencer->makeRequest(pkt); return true; } void -RubyMemory::RubyMemoryPort::sendTiming(PacketPtr pkt) +ruby_hit_callback(int64_t req_id) +{ + typedef map map_t; + map_t &prm = RubyMemory::pending_requests; + + map_t::iterator i = prm.find(req_id); + if (i == prm.end()) + panic("could not find pending request %d\n", req_id); + + PacketPtr pkt = i->second; + prm.erase(i); + + RubyMemory::SenderState *senderState = + safe_cast(pkt->senderState); + RubyMemory::Port *port = senderState->port; + + // pop the sender state from the packet + pkt->senderState = senderState->saved; + delete senderState; + + port->ruby_mem->hitCallback(pkt, port); +} + +void +RubyMemory::Port::sendTiming(PacketPtr pkt) { schedSendTiming(pkt, curTick + 1); //minimum latency, must be > 0 } void RubyMemory::printConfigStats() { - std::ostream *os = simout.create(stats_file); - g_system_ptr->printConfig(*os); + std::ostream *os = simout.create(params()->stats_file); + RubySystem::printConfig(*os); *os << endl; - g_system_ptr->printStats(*os); + RubySystem::printStats(*os); } diff --git a/src/mem/rubymem.hh b/src/mem/rubymem.hh index feb87ca6c..e33418a42 100644 --- a/src/mem/rubymem.hh +++ b/src/mem/rubymem.hh @@ -32,20 +32,26 @@ #define __RUBY_MEMORY_HH__ #include +#include +#include "base/callback.hh" +#include "mem/packet.hh" #include "mem/physical.hh" +#include "mem/ruby/system/RubyPort.hh" #include "params/RubyMemory.hh" -#include "base/callback.hh" -#include "mem/ruby/common/Driver.hh" -class RubyMemory : public PhysicalMemory, public Driver +class RubyMemory : public PhysicalMemory { - class RubyMemoryPort : public MemoryPort + public: + std::vector ruby_ports; + class Port : public MemoryPort { - RubyMemory* ruby_mem; + friend void ruby_hit_callback(int64_t req_id); + + RubyMemory *ruby_mem; public: - RubyMemoryPort(const std::string &_name, RubyMemory *_memory); + Port(const std::string &_name, RubyMemory *_memory); void sendTiming(PacketPtr pkt); protected: @@ -64,6 +70,15 @@ class RubyMemory : public PhysicalMemory, public Driver virtual const char *description() const { return "ruby tick"; } }; + struct SenderState : public Packet::SenderState + { + Port *port; + Packet::SenderState *saved; + + SenderState(Port *p, Packet::SenderState *s = NULL) + : port(p), saved(s) + {} + }; private: // prevent copying of a RubyMemory object @@ -77,14 +92,23 @@ class RubyMemory : public PhysicalMemory, public Driver RubyMemory(const Params *p); virtual ~RubyMemory(); + const Params * + params() const + { + return safe_cast(_params); + } + public: - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual ::Port *getPort(const std::string &if_name, int idx = -1); void virtual init(); //Ruby-related specifics - void printConfigStats(); //dsm: Maybe this function should disappear once the configuration options change & M5 determines the stats file to use + void printConfigStats(); //dsm: Maybe this function should + //disappear once the configuration + //options change & M5 determines the + //stats file to use - void hitCallback(Packet* pkt); // called by the Ruby sequencer + void hitCallback(PacketPtr pkt, Port *port); void printStats(std::ostream & out) const; void clearStats(); @@ -93,15 +117,15 @@ class RubyMemory : public PhysicalMemory, public Driver void tick(); private: - //Parameters passed - std::string config_file, config_options, stats_file, debug_file; - bool debug; - int num_cpus; - Tick ruby_clock, ruby_phase; + Tick ruby_clock; + Tick ruby_phase; - std::map m_packet_to_port_map; + public: + static std::map pending_requests; }; +void ruby_hit_callback(int64_t); + class RubyExitCallback : public Callback { private: diff --git a/tests/configs/memtest-ruby.py b/tests/configs/memtest-ruby.py index 004424af5..00a668a7b 100644 --- a/tests/configs/memtest-ruby.py +++ b/tests/configs/memtest-ruby.py @@ -34,9 +34,12 @@ from m5.objects import * nb_cores = 8 cpus = [ MemTest() for i in xrange(nb_cores) ] +import ruby_config +ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", nb_cores) + # system simulated system = System(cpu = cpus, funcmem = PhysicalMemory(), - physmem = RubyMemory(num_cpus=nb_cores), + physmem = ruby_memory, membus = Bus(clock="500GHz", width=16)) for cpu in cpus: diff --git a/tests/configs/o3-timing-mp-ruby.py b/tests/configs/o3-timing-mp-ruby.py index b9aade84e..eab9bfaf2 100644 --- a/tests/configs/o3-timing-mp-ruby.py +++ b/tests/configs/o3-timing-mp-ruby.py @@ -33,9 +33,11 @@ m5.AddToPath('../configs/common') nb_cores = 4 cpus = [ DerivO3CPU(cpu_id=i) for i in xrange(nb_cores) ] +import ruby_config +ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", nb_cores) + # system simulated -system = System(cpu = cpus, physmem = RubyMemory(num_cpus=nb_cores), - membus = Bus()) +system = System(cpu = cpus, physmem = ruby_memory, membus = Bus()) for cpu in cpus: cpu.connectMemPorts(system.membus) diff --git a/tests/configs/o3-timing-ruby.py b/tests/configs/o3-timing-ruby.py index 394550987..a91a9cf39 100644 --- a/tests/configs/o3-timing-ruby.py +++ b/tests/configs/o3-timing-ruby.py @@ -31,11 +31,14 @@ from m5.objects import * m5.AddToPath('../configs/common') +import ruby_config +ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", 1) + cpu = DerivO3CPU(cpu_id=0) cpu.clock = '2GHz' system = System(cpu = cpu, - physmem = RubyMemory(), + physmem = ruby_memory, membus = Bus()) system.physmem.port = system.membus.port cpu.connectMemPorts(system.membus) diff --git a/tests/configs/ruby_config.py b/tests/configs/ruby_config.py new file mode 100644 index 000000000..7b8e27613 --- /dev/null +++ b/tests/configs/ruby_config.py @@ -0,0 +1,20 @@ +import os +import subprocess + +from os.path import dirname, join as joinpath + +import m5 + +def generate(config_file, cores=1, memories=1, memory_size=1024): + default = joinpath(dirname(__file__), '../../src/mem/ruby/config') + ruby_config = os.environ.get('RUBY_CONFIG', default) + args = [ "ruby", "-I", ruby_config, joinpath(ruby_config, "print_cfg.rb"), + "-r", joinpath(ruby_config, config_file), "-p", str(cores), + "-m", str(memories), "-s", str(memory_size)] + + temp_config = joinpath(m5.options.outdir, "ruby.config") + ret = subprocess.call(args, stdout=file(temp_config, "w")) + if ret != 0: + raise RuntimeError, "subprocess failed!" + + return m5.objects.RubyMemory(config_file=temp_config, num_cpus=cores) diff --git a/tests/configs/simple-atomic-mp-ruby.py b/tests/configs/simple-atomic-mp-ruby.py index c03ede9b1..1b60418d0 100644 --- a/tests/configs/simple-atomic-mp-ruby.py +++ b/tests/configs/simple-atomic-mp-ruby.py @@ -33,9 +33,11 @@ from m5.objects import * nb_cores = 4 cpus = [ AtomicSimpleCPU(cpu_id=i) for i in xrange(nb_cores) ] +import ruby_config +ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", nb_cores) + # system simulated -system = System(cpu = cpus, physmem = RubyMemory(num_cpus=nb_cores), - membus = Bus()) +system = System(cpu = cpus, physmem = ruby_memory, membus = Bus()) # add L1 caches for cpu in cpus: diff --git a/tests/configs/simple-atomic-ruby.py b/tests/configs/simple-atomic-ruby.py index 95f922ddc..c9c61788c 100644 --- a/tests/configs/simple-atomic-ruby.py +++ b/tests/configs/simple-atomic-ruby.py @@ -29,8 +29,11 @@ import m5 from m5.objects import * +import ruby_config +ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", 1) + system = System(cpu = AtomicSimpleCPU(cpu_id=0), - physmem = RubyMemory(), + physmem = ruby_memory, membus = Bus()) system.physmem.port = system.membus.port system.cpu.connectMemPorts(system.membus) diff --git a/tests/configs/simple-timing-mp-ruby.py b/tests/configs/simple-timing-mp-ruby.py index df019c321..ed4b5b4c6 100644 --- a/tests/configs/simple-timing-mp-ruby.py +++ b/tests/configs/simple-timing-mp-ruby.py @@ -32,9 +32,11 @@ from m5.objects import * nb_cores = 4 cpus = [ TimingSimpleCPU(cpu_id=i) for i in xrange(nb_cores) ] +import ruby_config +ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", nb_cores) + # system simulated -system = System(cpu = cpus, physmem = RubyMemory(num_cpus=nb_cores), - membus = Bus()) +system = System(cpu = cpus, physmem = ruby_memory, membus = Bus()) # add L1 caches for cpu in cpus: diff --git a/tests/configs/simple-timing-ruby.py b/tests/configs/simple-timing-ruby.py index b921e4812..d3cd7273f 100644 --- a/tests/configs/simple-timing-ruby.py +++ b/tests/configs/simple-timing-ruby.py @@ -29,9 +29,12 @@ import m5 from m5.objects import * +import ruby_config +ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", 1) + cpu = TimingSimpleCPU(cpu_id=0) system = System(cpu = cpu, - physmem = RubyMemory(), + physmem = ruby_memory, membus = Bus()) system.physmem.port = system.membus.port cpu.connectMemPorts(system.membus) diff --git a/tests/run.py b/tests/run.py index df26c88c5..7f70ac507 100644 --- a/tests/run.py +++ b/tests/run.py @@ -28,6 +28,9 @@ import os import sys + +from os.path import join as joinpath + import m5 # Since we're in batch mode, dont allow tcp socket connections @@ -41,32 +44,33 @@ tests_root = os.path.dirname(__file__) if os.path.isdir('/dist/m5/regression/test-progs'): test_progs = '/dist/m5/regression/test-progs' else: - test_progs = os.path.join(tests_root, 'test-progs') + test_progs = joinpath(tests_root, 'test-progs') # generate path to binary file def binpath(app, file=None): # executable has same name as app unless specified otherwise if not file: file = app - return os.path.join(test_progs, app, 'bin', isa, opsys, file) + return joinpath(test_progs, app, 'bin', isa, opsys, file) # generate path to input file def inputpath(app, file=None): # input file has same name as app unless specified otherwise if not file: file = app - return os.path.join(test_progs, app, 'input', file) + return joinpath(test_progs, app, 'input', file) # build configuration -execfile(os.path.join(tests_root, 'configs', config + '.py')) +sys.path.append(joinpath(tests_root, 'configs')) +execfile(joinpath(tests_root, 'configs', config + '.py')) # set default maxtick... script can override # -1 means run forever maxtick = m5.MaxTick # tweak configuration for specific test - -execfile(os.path.join(tests_root, category, name, 'test.py')) +sys.path.append(joinpath(tests_root, category, name)) +execfile(joinpath(tests_root, category, name, 'test.py')) # instantiate configuration m5.instantiate(root)