diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mem/RubyMemory.py | 5 | ||||
-rw-r--r-- | src/mem/ruby/SConsopts | 7 | ||||
-rw-r--r-- | src/mem/ruby/storebuffer/storebuffer.cc | 20 | ||||
-rw-r--r-- | src/mem/ruby/storebuffer/storebuffer.hh | 8 | ||||
-rw-r--r-- | src/mem/rubymem.cc | 157 | ||||
-rw-r--r-- | src/mem/rubymem.hh | 54 |
6 files changed, 173 insertions, 78 deletions
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 <uint64_t, StoreBuffer *> 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<struct SBEntry>::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<int64_t, PacketPtr> 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<RubyObjConf> sys_conf; + while (!config.eof()) { + char buffer[4096]; + config.getline(buffer, sizeof(buffer)); + string line = buffer; + if (line.empty()) + continue; + vector<string> tokens; + tokenize(tokens, line, ' '); + assert(tokens.size() >= 2); + vector<string> argv; + for (size_t i=2; i<tokens.size(); i++) { + std::replace(tokens[i].begin(), tokens[i].end(), '%', ' '); + std::replace(tokens[i].begin(), tokens[i].end(), '#', '\n'); + argv.push_back(tokens[i]); + } + sys_conf.push_back(RubyObjConf(tokens[0], tokens[1], argv)); + tokens.clear(); + argv.clear(); + } + + RubySystem::create(sys_conf); + + for (int i = 0; i < params()->num_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<uint8_t>(), + 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<RubyMemory::SenderState *>(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<int64_t, PacketPtr> 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<RubyMemory::SenderState *>(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 <map> +#include <vector> +#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<RubyPort *> 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<const Params *>(_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<Packet*, RubyMemoryPort*> m_packet_to_port_map; + public: + static std::map<int64_t, PacketPtr> pending_requests; }; +void ruby_hit_callback(int64_t); + class RubyExitCallback : public Callback { private: |