ruby: Fix RubyMemory to work with the newer ruby.
This commit is contained in:
parent
a7904e2cf3
commit
da704f52e5
15 changed files with 232 additions and 95 deletions
|
@ -35,12 +35,11 @@ class RubyMemory(PhysicalMemory):
|
||||||
type = 'RubyMemory'
|
type = 'RubyMemory'
|
||||||
clock = Param.Clock('1t', "ruby clock speed")
|
clock = Param.Clock('1t', "ruby clock speed")
|
||||||
phase = Param.Latency('0ns', "ruby clock phase")
|
phase = Param.Latency('0ns', "ruby clock phase")
|
||||||
config_file = Param.String("", "path to the Ruby config file")
|
config_file = Param.String("path to the Ruby config file")
|
||||||
config_options = Param.String("", "extra Ruby options (one per line)")
|
|
||||||
stats_file = Param.String("ruby.stats",
|
stats_file = Param.String("ruby.stats",
|
||||||
"file to which ruby dumps its stats")
|
"file to which ruby dumps its stats")
|
||||||
num_cpus = Param.Int(1, "Number of CPUs connected to the Ruby memory")
|
num_cpus = Param.Int(1, "Number of CPUs connected to the Ruby memory")
|
||||||
debug = Param.Bool(False, "Use ruby debug")
|
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)")
|
"path to the Ruby debug output file (stdout if blank)")
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,10 @@ if not main['RUBY']:
|
||||||
sticky_vars.AddVariables(
|
sticky_vars.AddVariables(
|
||||||
BoolVariable('NO_VECTOR_BOUNDS_CHECKS', "Don't do bounds checks", True),
|
BoolVariable('NO_VECTOR_BOUNDS_CHECKS', "Don't do bounds checks", True),
|
||||||
BoolVariable('RUBY_DEBUG', "Add debugging stuff to Ruby", False),
|
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' ]
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "mem/ruby/storebuffer/storebuffer.hh"
|
#include "mem/ruby/storebuffer/storebuffer.hh"
|
||||||
#include "mem/ruby/common/Global.hh"
|
#include "mem/ruby/common/Global.hh"
|
||||||
|
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
#include "TsoChecker.hh"
|
#include "TsoChecker.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
// global map of request id_s to map them back to storebuffer pointers
|
// global map of request id_s to map them back to storebuffer pointers
|
||||||
map <uint64_t, StoreBuffer *> request_map;
|
map <uint64_t, StoreBuffer *> request_map;
|
||||||
|
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
Tso::TsoChecker * g_tsoChecker;
|
Tso::TsoChecker * g_tsoChecker;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ void hit(int64_t id) {
|
||||||
|
|
||||||
//*****************************************************************************************
|
//*****************************************************************************************
|
||||||
StoreBuffer::StoreBuffer(uint32 id, uint32 block_bits, int storebuffer_size) {
|
StoreBuffer::StoreBuffer(uint32 id, uint32 block_bits, int storebuffer_size) {
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
g_tsoChecker = new Tso::TsoChecker();
|
g_tsoChecker = new Tso::TsoChecker();
|
||||||
g_tsoChecker->init(64);
|
g_tsoChecker->init(64);
|
||||||
|
@ -99,7 +99,7 @@ StoreBuffer::StoreBuffer(uint32 id, uint32 block_bits, int storebuffer_size) {
|
||||||
|
|
||||||
//******************************************************************************************
|
//******************************************************************************************
|
||||||
StoreBuffer::~StoreBuffer(){
|
StoreBuffer::~StoreBuffer(){
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
if (m_id == 0) {
|
if (m_id == 0) {
|
||||||
delete g_tsoChecker;
|
delete g_tsoChecker;
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ void StoreBuffer::returnMatchedData(struct RubyRequest request) {
|
||||||
ASSERT(checkForLoadHit(request) != NO_MATCH);
|
ASSERT(checkForLoadHit(request) != NO_MATCH);
|
||||||
physical_address_t lineaddr = physical_address & m_block_mask;
|
physical_address_t lineaddr = physical_address & m_block_mask;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
Tso::TsoCheckerCmd * cmd;
|
Tso::TsoCheckerCmd * cmd;
|
||||||
#endif
|
#endif
|
||||||
deque<struct SBEntry>::iterator satisfying_store;
|
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 ((it->m_request.paddr & m_block_mask) == lineaddr) {
|
||||||
if (!found) {
|
if (!found) {
|
||||||
found = true;
|
found = true;
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
satisfying_store = it;
|
satisfying_store = it;
|
||||||
cmd = new Tso::TsoCheckerCmd(m_id, // this thread id
|
cmd = new Tso::TsoCheckerCmd(m_id, // this thread id
|
||||||
iseq, // instruction sequence
|
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;
|
uint64_t tso_data = 0;
|
||||||
memcpy(&tso_data, request.data, request.len);
|
memcpy(&tso_data, request.data, request.len);
|
||||||
cmd->setData(tso_data);
|
cmd->setData(tso_data);
|
||||||
|
@ -400,7 +400,7 @@ void StoreBuffer::complete(uint64_t id) {
|
||||||
m_buffer_size--;
|
m_buffer_size--;
|
||||||
ASSERT(m_buffer_size >= 0);
|
ASSERT(m_buffer_size >= 0);
|
||||||
|
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
int len = outstanding_requests.find(id)->second.len;
|
int len = outstanding_requests.find(id)->second.len;
|
||||||
uint64_t data = 0;
|
uint64_t data = 0;
|
||||||
memcpy(&data, from_buffer.m_request.data, 4);
|
memcpy(&data, from_buffer.m_request.data, 4);
|
||||||
|
@ -462,7 +462,7 @@ void StoreBuffer::complete(uint64_t id) {
|
||||||
#endif
|
#endif
|
||||||
} // end if (type == ST)
|
} // end if (type == ST)
|
||||||
else if (type == RubyRequestType_LD) {
|
else if (type == RubyRequestType_LD) {
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
RubyRequest request = outstanding_requests.find(id)->second;
|
RubyRequest request = outstanding_requests.find(id)->second;
|
||||||
uint64_t data = 0;
|
uint64_t data = 0;
|
||||||
memcpy(&data, request.data, request.len);
|
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) {
|
void StoreBuffer::insertTsoLL(Tso::TsoCheckerCmd * cmd) {
|
||||||
uint64_t count = cmd->getIseq();
|
uint64_t count = cmd->getIseq();
|
||||||
Tso::TsoCheckerCmd * current = NULL;
|
Tso::TsoCheckerCmd * current = NULL;
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "mem/ruby/storebuffer/hfa.hh"
|
#include "mem/ruby/storebuffer/hfa.hh"
|
||||||
#include "mem/ruby/libruby.hh"
|
#include "mem/ruby/libruby.hh"
|
||||||
|
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
#include "TsoCheckerCmd.hh"
|
#include "TsoCheckerCmd.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -53,13 +53,13 @@ enum load_match { NO_MATCH, PARTIAL_MATCH, FULL_MATCH };
|
||||||
|
|
||||||
struct SBEntry {
|
struct SBEntry {
|
||||||
struct RubyRequest m_request;
|
struct RubyRequest m_request;
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
Tso::TsoCheckerCmd * m_next_ptr;
|
Tso::TsoCheckerCmd * m_next_ptr;
|
||||||
#endif
|
#endif
|
||||||
SBEntry(struct RubyRequest request, void * ptr)
|
SBEntry(struct RubyRequest request, void * ptr)
|
||||||
: m_request(request)
|
: m_request(request)
|
||||||
{
|
{
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
m_next_ptr = (Tso::TsoCheckerCmd*) ptr;
|
m_next_ptr = (Tso::TsoCheckerCmd*) ptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ class StoreBuffer {
|
||||||
/// prints out the contents of the Write Buffer
|
/// prints out the contents of the Write Buffer
|
||||||
void print();
|
void print();
|
||||||
|
|
||||||
#ifdef RUBY_TSO_CHECKER
|
#if RUBY_TSO_CHECKER
|
||||||
/// if load completes before store, insert correctly to be issued to TSOChecker
|
/// if load completes before store, insert correctly to be issued to TSOChecker
|
||||||
void insertTsoLL(Tso::TsoCheckerCmd * cmd);
|
void insertTsoLL(Tso::TsoCheckerCmd * cmd);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,9 +33,11 @@
|
||||||
|
|
||||||
#include "arch/isa_traits.hh"
|
#include "arch/isa_traits.hh"
|
||||||
#include "base/output.hh"
|
#include "base/output.hh"
|
||||||
|
#include "base/str.hh"
|
||||||
#include "base/types.hh"
|
#include "base/types.hh"
|
||||||
#include "mem/ruby/common/Debug.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/Sequencer.hh"
|
||||||
#include "mem/ruby/system/System.hh"
|
#include "mem/ruby/system/System.hh"
|
||||||
#include "mem/rubymem.hh"
|
#include "mem/rubymem.hh"
|
||||||
|
@ -45,33 +47,54 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
|
map<int64_t, PacketPtr> RubyMemory::pending_requests;
|
||||||
|
|
||||||
RubyMemory::RubyMemory(const Params *p)
|
RubyMemory::RubyMemory(const Params *p)
|
||||||
: PhysicalMemory(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_clock = p->clock;
|
||||||
ruby_phase = p->phase;
|
ruby_phase = p->phase;
|
||||||
|
|
||||||
debug = p->debug;
|
ifstream config(p->config_file.c_str());
|
||||||
debug_file = p->debug_file;
|
|
||||||
|
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
|
void
|
||||||
RubyMemory::init()
|
RubyMemory::init()
|
||||||
{
|
{
|
||||||
init_variables();
|
if (params()->debug) {
|
||||||
g_NUM_PROCESSORS = num_cpus;
|
|
||||||
|
|
||||||
init_simulator(this);
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
g_debug_ptr->setVerbosityString("high");
|
g_debug_ptr->setVerbosityString("high");
|
||||||
g_debug_ptr->setDebugTime(1);
|
g_debug_ptr->setDebugTime(1);
|
||||||
if (debug_file != "") {
|
if (!params()->debug_file.empty()) {
|
||||||
g_debug_ptr->setDebugOutputFile("ruby.debug");
|
g_debug_ptr->setDebugOutputFile(params()->debug_file.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,23 +127,21 @@ RubyMemory::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
//called by rubyTickEvent
|
//called by rubyTickEvent
|
||||||
void RubyMemory::tick() {
|
void
|
||||||
g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 1);
|
RubyMemory::tick()
|
||||||
schedule(rubyTickEvent, curTick + ruby_clock); //dsm: clock_phase was added here. This is wrong, the phase is only added on the first tick
|
{
|
||||||
|
RubyEventQueue *eq = RubySystem::getEventQueue();
|
||||||
|
eq->triggerEvents(eq->getTime() + 1);
|
||||||
|
schedule(rubyTickEvent, curTick + ruby_clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RubyMemory::~RubyMemory()
|
||||||
RubyMemory::~RubyMemory() {
|
{
|
||||||
delete g_system_ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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");
|
DPRINTF(MemoryAccess, "Hit callback\n");
|
||||||
|
|
||||||
bool needsResponse = pkt->needsResponse();
|
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
|
// with places where this function is called from C++. I'd prefer
|
||||||
// to move all these into Python someday.
|
// to move all these into Python someday.
|
||||||
if (if_name == "functional") {
|
if (if_name == "functional") {
|
||||||
return new RubyMemoryPort(csprintf("%s-functional", name()), this);
|
return new Port(csprintf("%s-functional", name()), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (if_name != "port") {
|
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);
|
panic("RubyMemory::getPort: port %d already assigned", idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
RubyMemoryPort *port =
|
Port *port = new Port(csprintf("%s-port%d", name(), idx), this);
|
||||||
new RubyMemoryPort(csprintf("%s-port%d", name(), idx), this);
|
|
||||||
|
|
||||||
ports[idx] = port;
|
ports[idx] = port;
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
RubyMemory::RubyMemoryPort::RubyMemoryPort(const std::string &_name,
|
RubyMemory::Port::Port(const std::string &_name, RubyMemory *_memory)
|
||||||
RubyMemory *_memory)
|
|
||||||
: PhysicalMemory::MemoryPort::MemoryPort(_name, _memory)
|
: PhysicalMemory::MemoryPort::MemoryPort(_name, _memory)
|
||||||
{
|
{
|
||||||
ruby_mem = _memory;
|
ruby_mem = _memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RubyMemory::RubyMemoryPort::recvTiming(PacketPtr pkt)
|
RubyMemory::Port::recvTiming(PacketPtr pkt)
|
||||||
{
|
{
|
||||||
DPRINTF(MemoryAccess, "Timing access caught\n");
|
DPRINTF(MemoryAccess, "Timing access caught\n");
|
||||||
|
|
||||||
|
@ -197,33 +216,83 @@ RubyMemory::RubyMemoryPort::recvTiming(PacketPtr pkt)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ruby_mem->m_packet_to_port_map[pkt] = this;
|
// Save the port in the sender state object
|
||||||
|
pkt->senderState = new SenderState(this, pkt->senderState);
|
||||||
|
|
||||||
Sequencer* sequencer = g_system_ptr->getSequencer(pkt->req->contextId());
|
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) ) {
|
RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr<uint8_t>(),
|
||||||
DPRINTF(MemoryAccess, "Sequencer isn't ready yet!!\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(MemoryAccess, "Issuing makeRequest\n");
|
// Save the request for the callback
|
||||||
|
RubyMemory::pending_requests[req_id] = pkt;
|
||||||
|
|
||||||
sequencer->makeRequest(pkt);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
schedSendTiming(pkt, curTick + 1); //minimum latency, must be > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
void RubyMemory::printConfigStats()
|
void RubyMemory::printConfigStats()
|
||||||
{
|
{
|
||||||
std::ostream *os = simout.create(stats_file);
|
std::ostream *os = simout.create(params()->stats_file);
|
||||||
g_system_ptr->printConfig(*os);
|
RubySystem::printConfig(*os);
|
||||||
*os << endl;
|
*os << endl;
|
||||||
g_system_ptr->printStats(*os);
|
RubySystem::printStats(*os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,20 +32,26 @@
|
||||||
#define __RUBY_MEMORY_HH__
|
#define __RUBY_MEMORY_HH__
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "mem/physical.hh"
|
|
||||||
#include "params/RubyMemory.hh"
|
|
||||||
#include "base/callback.hh"
|
#include "base/callback.hh"
|
||||||
#include "mem/ruby/common/Driver.hh"
|
#include "mem/packet.hh"
|
||||||
|
#include "mem/physical.hh"
|
||||||
|
#include "mem/ruby/system/RubyPort.hh"
|
||||||
|
#include "params/RubyMemory.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:
|
public:
|
||||||
RubyMemoryPort(const std::string &_name, RubyMemory *_memory);
|
Port(const std::string &_name, RubyMemory *_memory);
|
||||||
void sendTiming(PacketPtr pkt);
|
void sendTiming(PacketPtr pkt);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -64,6 +70,15 @@ class RubyMemory : public PhysicalMemory, public Driver
|
||||||
virtual const char *description() const { return "ruby tick"; }
|
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:
|
private:
|
||||||
// prevent copying of a RubyMemory object
|
// prevent copying of a RubyMemory object
|
||||||
|
@ -77,14 +92,23 @@ class RubyMemory : public PhysicalMemory, public Driver
|
||||||
RubyMemory(const Params *p);
|
RubyMemory(const Params *p);
|
||||||
virtual ~RubyMemory();
|
virtual ~RubyMemory();
|
||||||
|
|
||||||
|
const Params *
|
||||||
|
params() const
|
||||||
|
{
|
||||||
|
return safe_cast<const Params *>(_params);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
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();
|
void virtual init();
|
||||||
|
|
||||||
//Ruby-related specifics
|
//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 printStats(std::ostream & out) const;
|
||||||
void clearStats();
|
void clearStats();
|
||||||
|
@ -93,15 +117,15 @@ class RubyMemory : public PhysicalMemory, public Driver
|
||||||
void tick();
|
void tick();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//Parameters passed
|
Tick ruby_clock;
|
||||||
std::string config_file, config_options, stats_file, debug_file;
|
Tick ruby_phase;
|
||||||
bool debug;
|
|
||||||
int num_cpus;
|
|
||||||
Tick ruby_clock, 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
|
class RubyExitCallback : public Callback
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -34,9 +34,12 @@ from m5.objects import *
|
||||||
nb_cores = 8
|
nb_cores = 8
|
||||||
cpus = [ MemTest() for i in xrange(nb_cores) ]
|
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 simulated
|
||||||
system = System(cpu = cpus, funcmem = PhysicalMemory(),
|
system = System(cpu = cpus, funcmem = PhysicalMemory(),
|
||||||
physmem = RubyMemory(num_cpus=nb_cores),
|
physmem = ruby_memory,
|
||||||
membus = Bus(clock="500GHz", width=16))
|
membus = Bus(clock="500GHz", width=16))
|
||||||
|
|
||||||
for cpu in cpus:
|
for cpu in cpus:
|
||||||
|
|
|
@ -33,9 +33,11 @@ m5.AddToPath('../configs/common')
|
||||||
nb_cores = 4
|
nb_cores = 4
|
||||||
cpus = [ DerivO3CPU(cpu_id=i) for i in xrange(nb_cores) ]
|
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 simulated
|
||||||
system = System(cpu = cpus, physmem = RubyMemory(num_cpus=nb_cores),
|
system = System(cpu = cpus, physmem = ruby_memory, membus = Bus())
|
||||||
membus = Bus())
|
|
||||||
|
|
||||||
for cpu in cpus:
|
for cpu in cpus:
|
||||||
cpu.connectMemPorts(system.membus)
|
cpu.connectMemPorts(system.membus)
|
||||||
|
|
|
@ -31,11 +31,14 @@ from m5.objects import *
|
||||||
m5.AddToPath('../configs/common')
|
m5.AddToPath('../configs/common')
|
||||||
|
|
||||||
|
|
||||||
|
import ruby_config
|
||||||
|
ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", 1)
|
||||||
|
|
||||||
cpu = DerivO3CPU(cpu_id=0)
|
cpu = DerivO3CPU(cpu_id=0)
|
||||||
cpu.clock = '2GHz'
|
cpu.clock = '2GHz'
|
||||||
|
|
||||||
system = System(cpu = cpu,
|
system = System(cpu = cpu,
|
||||||
physmem = RubyMemory(),
|
physmem = ruby_memory,
|
||||||
membus = Bus())
|
membus = Bus())
|
||||||
system.physmem.port = system.membus.port
|
system.physmem.port = system.membus.port
|
||||||
cpu.connectMemPorts(system.membus)
|
cpu.connectMemPorts(system.membus)
|
||||||
|
|
20
tests/configs/ruby_config.py
Normal file
20
tests/configs/ruby_config.py
Normal file
|
@ -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)
|
|
@ -33,9 +33,11 @@ from m5.objects import *
|
||||||
nb_cores = 4
|
nb_cores = 4
|
||||||
cpus = [ AtomicSimpleCPU(cpu_id=i) for i in xrange(nb_cores) ]
|
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 simulated
|
||||||
system = System(cpu = cpus, physmem = RubyMemory(num_cpus=nb_cores),
|
system = System(cpu = cpus, physmem = ruby_memory, membus = Bus())
|
||||||
membus = Bus())
|
|
||||||
|
|
||||||
# add L1 caches
|
# add L1 caches
|
||||||
for cpu in cpus:
|
for cpu in cpus:
|
||||||
|
|
|
@ -29,8 +29,11 @@
|
||||||
import m5
|
import m5
|
||||||
from m5.objects import *
|
from m5.objects import *
|
||||||
|
|
||||||
|
import ruby_config
|
||||||
|
ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", 1)
|
||||||
|
|
||||||
system = System(cpu = AtomicSimpleCPU(cpu_id=0),
|
system = System(cpu = AtomicSimpleCPU(cpu_id=0),
|
||||||
physmem = RubyMemory(),
|
physmem = ruby_memory,
|
||||||
membus = Bus())
|
membus = Bus())
|
||||||
system.physmem.port = system.membus.port
|
system.physmem.port = system.membus.port
|
||||||
system.cpu.connectMemPorts(system.membus)
|
system.cpu.connectMemPorts(system.membus)
|
||||||
|
|
|
@ -32,9 +32,11 @@ from m5.objects import *
|
||||||
nb_cores = 4
|
nb_cores = 4
|
||||||
cpus = [ TimingSimpleCPU(cpu_id=i) for i in xrange(nb_cores) ]
|
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 simulated
|
||||||
system = System(cpu = cpus, physmem = RubyMemory(num_cpus=nb_cores),
|
system = System(cpu = cpus, physmem = ruby_memory, membus = Bus())
|
||||||
membus = Bus())
|
|
||||||
|
|
||||||
# add L1 caches
|
# add L1 caches
|
||||||
for cpu in cpus:
|
for cpu in cpus:
|
||||||
|
|
|
@ -29,9 +29,12 @@
|
||||||
import m5
|
import m5
|
||||||
from m5.objects import *
|
from m5.objects import *
|
||||||
|
|
||||||
|
import ruby_config
|
||||||
|
ruby_memory = ruby_config.generate("MI_example-homogeneous.rb", 1)
|
||||||
|
|
||||||
cpu = TimingSimpleCPU(cpu_id=0)
|
cpu = TimingSimpleCPU(cpu_id=0)
|
||||||
system = System(cpu = cpu,
|
system = System(cpu = cpu,
|
||||||
physmem = RubyMemory(),
|
physmem = ruby_memory,
|
||||||
membus = Bus())
|
membus = Bus())
|
||||||
system.physmem.port = system.membus.port
|
system.physmem.port = system.membus.port
|
||||||
cpu.connectMemPorts(system.membus)
|
cpu.connectMemPorts(system.membus)
|
||||||
|
|
16
tests/run.py
16
tests/run.py
|
@ -28,6 +28,9 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from os.path import join as joinpath
|
||||||
|
|
||||||
import m5
|
import m5
|
||||||
|
|
||||||
# Since we're in batch mode, dont allow tcp socket connections
|
# 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'):
|
if os.path.isdir('/dist/m5/regression/test-progs'):
|
||||||
test_progs = '/dist/m5/regression/test-progs'
|
test_progs = '/dist/m5/regression/test-progs'
|
||||||
else:
|
else:
|
||||||
test_progs = os.path.join(tests_root, 'test-progs')
|
test_progs = joinpath(tests_root, 'test-progs')
|
||||||
|
|
||||||
# generate path to binary file
|
# generate path to binary file
|
||||||
def binpath(app, file=None):
|
def binpath(app, file=None):
|
||||||
# executable has same name as app unless specified otherwise
|
# executable has same name as app unless specified otherwise
|
||||||
if not file:
|
if not file:
|
||||||
file = app
|
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
|
# generate path to input file
|
||||||
def inputpath(app, file=None):
|
def inputpath(app, file=None):
|
||||||
# input file has same name as app unless specified otherwise
|
# input file has same name as app unless specified otherwise
|
||||||
if not file:
|
if not file:
|
||||||
file = app
|
file = app
|
||||||
return os.path.join(test_progs, app, 'input', file)
|
return joinpath(test_progs, app, 'input', file)
|
||||||
|
|
||||||
# build configuration
|
# 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
|
# set default maxtick... script can override
|
||||||
# -1 means run forever
|
# -1 means run forever
|
||||||
maxtick = m5.MaxTick
|
maxtick = m5.MaxTick
|
||||||
|
|
||||||
# tweak configuration for specific test
|
# tweak configuration for specific test
|
||||||
|
sys.path.append(joinpath(tests_root, category, name))
|
||||||
execfile(os.path.join(tests_root, category, name, 'test.py'))
|
execfile(joinpath(tests_root, category, name, 'test.py'))
|
||||||
|
|
||||||
# instantiate configuration
|
# instantiate configuration
|
||||||
m5.instantiate(root)
|
m5.instantiate(root)
|
||||||
|
|
Loading…
Reference in a new issue