Ruby: use ClockedObject in Consumer class
Many Ruby structures inherit from the Consumer, which is used for scheduling events. The Consumer used to relay on an Event Manager for scheduling events and on g_system_ptr for time. With this patch, the Consumer will now use a ClockedObject to schedule events and to query for current time. This resulted in several structures being converted from SimObjects to ClockedObjects. Also, the MessageBuffer class now requires a pointer to a ClockedObject so as to query for time.
This commit is contained in:
@@ -47,4 +47,4 @@ void profile_outstanding_persistent_request(int outstanding);
|
||||
void profile_average_latency_estimate(int latency);
|
||||
|
||||
// profile the total message delay of a message across a virtual network
|
||||
void profileMsgDelay(int virtualNetwork, int delayCycles);
|
||||
void profileMsgDelay(int virtualNetwork, Time delayCycles);
|
||||
|
||||
@@ -36,13 +36,12 @@
|
||||
//
|
||||
|
||||
external_type(MessageBuffer, buffer="yes", inport="yes", outport="yes");
|
||||
|
||||
external_type(OutPort, primitive="yes");
|
||||
|
||||
structure(InPort, external = "yes", primitive="yes") {
|
||||
bool isReady();
|
||||
void dequeue();
|
||||
int dequeue_getDelayCycles();
|
||||
Time dequeue_getDelayCycles();
|
||||
void recycle();
|
||||
bool isEmpty();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ MessageBuffer::MessageBuffer(const string &name)
|
||||
{
|
||||
m_msg_counter = 0;
|
||||
m_consumer_ptr = NULL;
|
||||
m_clockobj_ptr = NULL;
|
||||
|
||||
m_ordering_set = false;
|
||||
m_strict_fifo = true;
|
||||
m_size = 0;
|
||||
@@ -66,10 +68,10 @@ MessageBuffer::MessageBuffer(const string &name)
|
||||
int
|
||||
MessageBuffer::getSize()
|
||||
{
|
||||
if (m_time_last_time_size_checked == g_system_ptr->getTime()) {
|
||||
if (m_time_last_time_size_checked == m_clockobj_ptr->curCycle()) {
|
||||
return m_size_last_time_size_checked;
|
||||
} else {
|
||||
m_time_last_time_size_checked = g_system_ptr->getTime();
|
||||
m_time_last_time_size_checked = m_clockobj_ptr->curCycle();
|
||||
m_size_last_time_size_checked = m_size;
|
||||
return m_size;
|
||||
}
|
||||
@@ -89,11 +91,11 @@ MessageBuffer::areNSlotsAvailable(int n)
|
||||
// until next cycle, but enqueue operations effect the visible
|
||||
// size immediately
|
||||
int current_size = max(m_size_at_cycle_start, m_size);
|
||||
if (m_time_last_time_pop < g_system_ptr->getTime()) {
|
||||
if (m_time_last_time_pop < m_clockobj_ptr->curCycle()) {
|
||||
// no pops this cycle - m_size is correct
|
||||
current_size = m_size;
|
||||
} else {
|
||||
if (m_time_last_time_enqueue < g_system_ptr->getTime()) {
|
||||
if (m_time_last_time_enqueue < m_clockobj_ptr->curCycle()) {
|
||||
// no enqueues this cycle - m_size_at_cycle_start is correct
|
||||
current_size = m_size_at_cycle_start;
|
||||
} else {
|
||||
@@ -155,9 +157,9 @@ MessageBuffer::enqueue(MsgPtr message, Time delta)
|
||||
m_size++;
|
||||
|
||||
// record current time incase we have a pop that also adjusts my size
|
||||
if (m_time_last_time_enqueue < g_system_ptr->getTime()) {
|
||||
if (m_time_last_time_enqueue < m_clockobj_ptr->curCycle()) {
|
||||
m_msgs_this_cycle = 0; // first msg this cycle
|
||||
m_time_last_time_enqueue = g_system_ptr->getTime();
|
||||
m_time_last_time_enqueue = m_clockobj_ptr->curCycle();
|
||||
}
|
||||
m_msgs_this_cycle++;
|
||||
|
||||
@@ -168,7 +170,7 @@ MessageBuffer::enqueue(MsgPtr message, Time delta)
|
||||
// Calculate the arrival time of the message, that is, the first
|
||||
// cycle the message can be dequeued.
|
||||
assert(delta>0);
|
||||
Time current_time = g_system_ptr->getTime();
|
||||
Time current_time = m_clockobj_ptr->curCycle();
|
||||
Time arrival_time = 0;
|
||||
if (!RubySystem::getRandomization() || (m_randomization == false)) {
|
||||
// No randomization
|
||||
@@ -191,11 +193,10 @@ MessageBuffer::enqueue(MsgPtr message, Time delta)
|
||||
if (arrival_time < m_last_arrival_time) {
|
||||
panic("FIFO ordering violated: %s name: %s current time: %d "
|
||||
"delta: %d arrival_time: %d last arrival_time: %d\n",
|
||||
*this, m_name,
|
||||
current_time * g_system_ptr->clockPeriod(),
|
||||
delta * g_system_ptr->clockPeriod(),
|
||||
arrival_time * g_system_ptr->clockPeriod(),
|
||||
m_last_arrival_time * g_system_ptr->clockPeriod());
|
||||
*this, m_name, current_time * m_clockobj_ptr->clockPeriod(),
|
||||
delta * m_clockobj_ptr->clockPeriod(),
|
||||
arrival_time * m_clockobj_ptr->clockPeriod(),
|
||||
m_last_arrival_time * m_clockobj_ptr->clockPeriod());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,10 +209,10 @@ MessageBuffer::enqueue(MsgPtr message, Time delta)
|
||||
Message* msg_ptr = message.get();
|
||||
assert(msg_ptr != NULL);
|
||||
|
||||
assert(g_system_ptr->getTime() >= msg_ptr->getLastEnqueueTime() &&
|
||||
assert(m_clockobj_ptr->curCycle() >= msg_ptr->getLastEnqueueTime() &&
|
||||
"ensure we aren't dequeued early");
|
||||
|
||||
msg_ptr->setDelayedCycles(g_system_ptr->getTime() -
|
||||
msg_ptr->setDelayedCycles(m_clockobj_ptr->curCycle() -
|
||||
msg_ptr->getLastEnqueueTime() +
|
||||
msg_ptr->getDelayedCycles());
|
||||
msg_ptr->setLastEnqueueTime(arrival_time);
|
||||
@@ -222,9 +223,8 @@ MessageBuffer::enqueue(MsgPtr message, Time delta)
|
||||
push_heap(m_prio_heap.begin(), m_prio_heap.end(),
|
||||
greater<MessageBufferNode>());
|
||||
|
||||
DPRINTF(RubyQueue, "Enqueue with arrival_time %lld.\n",
|
||||
arrival_time * g_system_ptr->clockPeriod());
|
||||
DPRINTF(RubyQueue, "Enqueue Message: %s.\n", (*(message.get())));
|
||||
DPRINTF(RubyQueue, "Enqueue arrival_time: %lld, Message: %s\n",
|
||||
arrival_time * m_clockobj_ptr->clockPeriod(), *(message.get()));
|
||||
|
||||
// Schedule the wakeup
|
||||
if (m_consumer_ptr != NULL) {
|
||||
@@ -235,18 +235,11 @@ MessageBuffer::enqueue(MsgPtr message, Time delta)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Time
|
||||
MessageBuffer::dequeue_getDelayCycles(MsgPtr& message)
|
||||
{
|
||||
int delay_cycles = -1; // null value
|
||||
|
||||
dequeue(message);
|
||||
|
||||
// get the delay cycles
|
||||
delay_cycles = setAndReturnDelayCycles(message);
|
||||
|
||||
assert(delay_cycles >= 0);
|
||||
return delay_cycles;
|
||||
return setAndReturnDelayCycles(message);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -259,21 +252,17 @@ MessageBuffer::dequeue(MsgPtr& message)
|
||||
DPRINTF(RubyQueue, "Enqueue message is %s\n", (*(message.get())));
|
||||
}
|
||||
|
||||
int
|
||||
Time
|
||||
MessageBuffer::dequeue_getDelayCycles()
|
||||
{
|
||||
int delay_cycles = -1; // null value
|
||||
|
||||
// get MsgPtr of the message about to be dequeued
|
||||
MsgPtr message = m_prio_heap.front().m_msgptr;
|
||||
|
||||
// get the delay cycles
|
||||
delay_cycles = setAndReturnDelayCycles(message);
|
||||
|
||||
Time delayCycles = setAndReturnDelayCycles(message);
|
||||
dequeue();
|
||||
|
||||
assert(delay_cycles >= 0);
|
||||
return delay_cycles;
|
||||
return delayCycles;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -287,9 +276,9 @@ MessageBuffer::pop()
|
||||
|
||||
// record previous size and time so the current buffer size isn't
|
||||
// adjusted until next cycle
|
||||
if (m_time_last_time_pop < g_system_ptr->getTime()) {
|
||||
if (m_time_last_time_pop < m_clockobj_ptr->curCycle()) {
|
||||
m_size_at_cycle_start = m_size;
|
||||
m_time_last_time_pop = g_system_ptr->getTime();
|
||||
m_time_last_time_pop = m_clockobj_ptr->curCycle();
|
||||
}
|
||||
m_size--;
|
||||
}
|
||||
@@ -315,11 +304,11 @@ MessageBuffer::recycle()
|
||||
MessageBufferNode node = m_prio_heap.front();
|
||||
pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
|
||||
greater<MessageBufferNode>());
|
||||
node.m_time = g_system_ptr->getTime() + m_recycle_latency;
|
||||
node.m_time = m_clockobj_ptr->curCycle() + m_recycle_latency;
|
||||
m_prio_heap.back() = node;
|
||||
push_heap(m_prio_heap.begin(), m_prio_heap.end(),
|
||||
greater<MessageBufferNode>());
|
||||
m_consumer_ptr->scheduleEventAbsolute(g_system_ptr->getTime() +
|
||||
m_consumer_ptr->scheduleEventAbsolute(m_clockobj_ptr->curCycle() +
|
||||
m_recycle_latency);
|
||||
}
|
||||
|
||||
@@ -335,7 +324,7 @@ MessageBuffer::reanalyzeMessages(const Address& addr)
|
||||
//
|
||||
while(!m_stall_msg_map[addr].empty()) {
|
||||
m_msg_counter++;
|
||||
MessageBufferNode msgNode(g_system_ptr->getTime() + 1,
|
||||
MessageBufferNode msgNode(m_clockobj_ptr->curCycle() + 1,
|
||||
m_msg_counter,
|
||||
m_stall_msg_map[addr].front());
|
||||
|
||||
@@ -364,7 +353,7 @@ MessageBuffer::reanalyzeAllMessages()
|
||||
|
||||
while(!(map_iter->second).empty()) {
|
||||
m_msg_counter++;
|
||||
MessageBufferNode msgNode(g_system_ptr->getTime() + 1,
|
||||
MessageBufferNode msgNode(m_clockobj_ptr->curCycle() + 1,
|
||||
m_msg_counter,
|
||||
(map_iter->second).front());
|
||||
|
||||
@@ -397,23 +386,19 @@ MessageBuffer::stallMessage(const Address& addr)
|
||||
(m_stall_msg_map[addr]).push_back(message);
|
||||
}
|
||||
|
||||
int
|
||||
Time
|
||||
MessageBuffer::setAndReturnDelayCycles(MsgPtr msg_ptr)
|
||||
{
|
||||
int delay_cycles = -1; // null value
|
||||
|
||||
// get the delay cycles of the message at the top of the queue
|
||||
|
||||
// this function should only be called on dequeue
|
||||
// ensure the msg hasn't been enqueued
|
||||
assert(msg_ptr->getLastEnqueueTime() <= g_system_ptr->getTime());
|
||||
msg_ptr->setDelayedCycles(g_system_ptr->getTime() -
|
||||
msg_ptr->getLastEnqueueTime() +
|
||||
msg_ptr->getDelayedCycles());
|
||||
delay_cycles = msg_ptr->getDelayedCycles();
|
||||
assert(msg_ptr->getLastEnqueueTime() <= m_clockobj_ptr->curCycle());
|
||||
msg_ptr->setDelayedCycles(m_clockobj_ptr->curCycle() -
|
||||
msg_ptr->getLastEnqueueTime() +
|
||||
msg_ptr->getDelayedCycles());
|
||||
|
||||
assert(delay_cycles >= 0);
|
||||
return delay_cycles;
|
||||
return msg_ptr->getDelayedCycles();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -440,7 +425,7 @@ bool
|
||||
MessageBuffer::isReady() const
|
||||
{
|
||||
return ((m_prio_heap.size() > 0) &&
|
||||
(m_prio_heap.front().m_time <= g_system_ptr->getTime()));
|
||||
(m_prio_heap.front().m_time <= m_clockobj_ptr->curCycle()));
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -86,6 +86,12 @@ class MessageBuffer
|
||||
m_consumer_ptr = consumer_ptr;
|
||||
}
|
||||
|
||||
void setClockObj(ClockedObject* obj)
|
||||
{
|
||||
assert(m_clockobj_ptr == NULL);
|
||||
m_clockobj_ptr = obj;
|
||||
}
|
||||
|
||||
void setDescription(const std::string& name) { m_name = name; }
|
||||
std::string getDescription() { return m_name;}
|
||||
|
||||
@@ -110,12 +116,13 @@ class MessageBuffer
|
||||
|
||||
void enqueue(MsgPtr message) { enqueue(message, 1); }
|
||||
void enqueue(MsgPtr message, Time delta);
|
||||
// void enqueueAbsolute(const MsgPtr& message, Time absolute_time);
|
||||
int dequeue_getDelayCycles(MsgPtr& message); // returns delay
|
||||
// cycles of the
|
||||
// message
|
||||
|
||||
//! returns delay ticks of the message.
|
||||
Time dequeue_getDelayCycles(MsgPtr& message);
|
||||
void dequeue(MsgPtr& message);
|
||||
int dequeue_getDelayCycles(); // returns delay cycles of the message
|
||||
|
||||
//! returns delay cycles of the message
|
||||
Time dequeue_getDelayCycles();
|
||||
void dequeue() { pop(); }
|
||||
void pop();
|
||||
void recycle();
|
||||
@@ -156,16 +163,19 @@ class MessageBuffer
|
||||
int m_recycle_latency;
|
||||
|
||||
// Private Methods
|
||||
int setAndReturnDelayCycles(MsgPtr message);
|
||||
Time setAndReturnDelayCycles(MsgPtr message);
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
MessageBuffer(const MessageBuffer& obj);
|
||||
MessageBuffer& operator=(const MessageBuffer& obj);
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
Consumer* m_consumer_ptr; // Consumer to signal a wakeup(), can be NULL
|
||||
//! Object used for querying time.
|
||||
ClockedObject* m_clockobj_ptr;
|
||||
//! Consumer to signal a wakeup(), can be NULL
|
||||
Consumer* m_consumer_ptr;
|
||||
std::vector<MessageBufferNode> m_prio_heap;
|
||||
|
||||
|
||||
// use a std::map for the stalled messages as this container is
|
||||
// sorted and ensures a well-defined iteration order
|
||||
typedef std::map< Address, std::list<MsgPtr> > StallMsgMapType;
|
||||
|
||||
@@ -27,23 +27,21 @@
|
||||
*/
|
||||
|
||||
#include "mem/ruby/common/Consumer.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/system/System.hh"
|
||||
|
||||
void
|
||||
Consumer::scheduleEvent(Time timeDelta)
|
||||
{
|
||||
scheduleEventAbsolute(timeDelta + g_system_ptr->getTime());
|
||||
scheduleEventAbsolute(timeDelta + em->curCycle());
|
||||
}
|
||||
|
||||
void
|
||||
Consumer::scheduleEventAbsolute(Time timeAbs)
|
||||
{
|
||||
Tick evt_time = g_system_ptr->clockPeriod() * timeAbs;
|
||||
Tick evt_time = em->clockPeriod() * timeAbs;
|
||||
if (!alreadyScheduled(evt_time)) {
|
||||
// This wakeup is not redundant
|
||||
ConsumerEvent *evt = new ConsumerEvent(this);
|
||||
assert(timeAbs > g_system_ptr->getTime());
|
||||
assert(timeAbs > em->curCycle());
|
||||
|
||||
em->schedule(evt, evt_time);
|
||||
insertScheduledWakeupTime(evt_time);
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
#include <set>
|
||||
|
||||
#include "mem/ruby/common/TypeDefines.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/clocked_object.hh"
|
||||
|
||||
class Consumer
|
||||
{
|
||||
public:
|
||||
Consumer(EventManager *_em)
|
||||
Consumer(ClockedObject *_em)
|
||||
: m_last_scheduled_wakeup(0), m_last_wakeup(0), em(_em)
|
||||
{
|
||||
}
|
||||
@@ -95,7 +95,7 @@ class Consumer
|
||||
Tick m_last_scheduled_wakeup;
|
||||
std::set<Tick> m_scheduled_wakeups;
|
||||
Tick m_last_wakeup;
|
||||
EventManager *em;
|
||||
ClockedObject *em;
|
||||
|
||||
class ConsumerEvent : public Event
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "mem/ruby/network/BasicRouter.hh"
|
||||
|
||||
BasicRouter::BasicRouter(const Params *p)
|
||||
: SimObject(p)
|
||||
: ClockedObject(p)
|
||||
{
|
||||
m_id = p->router_id;
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include "params/BasicRouter.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/clocked_object.hh"
|
||||
|
||||
class BasicRouter : public SimObject
|
||||
class BasicRouter : public ClockedObject
|
||||
{
|
||||
public:
|
||||
typedef BasicRouterParams Params;
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
# Brad Beckmann
|
||||
|
||||
from m5.params import *
|
||||
from m5.SimObject import SimObject
|
||||
from ClockedObject import ClockedObject
|
||||
|
||||
class BasicRouter(SimObject):
|
||||
class BasicRouter(ClockedObject):
|
||||
type = 'BasicRouter'
|
||||
cxx_header = "mem/ruby/network/BasicRouter.hh"
|
||||
router_id = Param.Int("ID in relation to other routers")
|
||||
|
||||
@@ -37,7 +37,7 @@ uint32_t Network::m_control_msg_size;
|
||||
uint32_t Network::m_data_msg_size;
|
||||
|
||||
Network::Network(const Params *p)
|
||||
: SimObject(p)
|
||||
: ClockedObject(p)
|
||||
{
|
||||
m_virtual_networks = p->number_of_virtual_networks;
|
||||
m_topology_ptr = p->topology;
|
||||
|
||||
@@ -49,14 +49,14 @@
|
||||
#include "mem/protocol/MessageSizeType.hh"
|
||||
#include "mem/ruby/common/TypeDefines.hh"
|
||||
#include "params/RubyNetwork.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/clocked_object.hh"
|
||||
|
||||
class NetDest;
|
||||
class MessageBuffer;
|
||||
class Throttle;
|
||||
class Topology;
|
||||
|
||||
class Network : public SimObject
|
||||
class Network : public ClockedObject
|
||||
{
|
||||
public:
|
||||
typedef RubyNetworkParams Params;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
from m5.params import *
|
||||
from m5.SimObject import SimObject
|
||||
from ClockedObject import ClockedObject
|
||||
from BasicLink import BasicLink
|
||||
|
||||
class Topology(SimObject):
|
||||
@@ -42,7 +43,7 @@ class Topology(SimObject):
|
||||
print_config = Param.Bool(False,
|
||||
"display topology config in the stats file")
|
||||
|
||||
class RubyNetwork(SimObject):
|
||||
class RubyNetwork(ClockedObject):
|
||||
type = 'RubyNetwork'
|
||||
cxx_class = 'Network'
|
||||
cxx_header = "mem/ruby/network/Network.hh"
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from m5.SimObject import SimObject
|
||||
from ClockedObject import ClockedObject
|
||||
from BasicLink import BasicIntLink, BasicExtLink
|
||||
|
||||
class NetworkLink_d(SimObject):
|
||||
class NetworkLink_d(ClockedObject):
|
||||
type = 'NetworkLink_d'
|
||||
cxx_header = "mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh"
|
||||
link_id = Param.Int(Parent.link_id, "link id")
|
||||
|
||||
@@ -116,6 +116,7 @@ NetworkInterface_d::addNode(vector<MessageBuffer *>& in,
|
||||
|
||||
// the protocol injects messages into the NI
|
||||
inNode_ptr[j]->setConsumer(this);
|
||||
inNode_ptr[j]->setClockObj(m_net_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh"
|
||||
|
||||
NetworkLink_d::NetworkLink_d(const Params *p)
|
||||
: SimObject(p), Consumer(this)
|
||||
: ClockedObject(p), Consumer(this)
|
||||
{
|
||||
m_latency = p->link_latency;
|
||||
channel_width = p->channel_width;
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
#include "mem/ruby/network/garnet/NetworkHeader.hh"
|
||||
#include "mem/ruby/network/orion/NetworkPower.hh"
|
||||
#include "params/NetworkLink_d.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/clocked_object.hh"
|
||||
|
||||
class GarnetNetwork_d;
|
||||
|
||||
class NetworkLink_d : public SimObject, public Consumer
|
||||
class NetworkLink_d : public ClockedObject, public Consumer
|
||||
{
|
||||
public:
|
||||
typedef NetworkLink_dParams Params;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
class FlexibleConsumer : public Consumer
|
||||
{
|
||||
public:
|
||||
FlexibleConsumer(EventManager *em) : Consumer(em) {}
|
||||
FlexibleConsumer(ClockedObject *em) : Consumer(em) {}
|
||||
virtual bool isBufferNotFull(int vc, int inport) { return true; }
|
||||
virtual void grant_vc(int out_port, int vc, Time grant_time) {}
|
||||
virtual void release_vc(int out_port, int vc, Time release_time) {}
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
|
||||
from m5.params import *
|
||||
from m5.proxy import *
|
||||
from m5.SimObject import SimObject
|
||||
from ClockedObject import ClockedObject
|
||||
from BasicLink import BasicIntLink, BasicExtLink
|
||||
|
||||
class NetworkLink(SimObject):
|
||||
class NetworkLink(ClockedObject):
|
||||
type = 'NetworkLink'
|
||||
cxx_header = "mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh"
|
||||
link_id = Param.Int(Parent.link_id, "link id")
|
||||
|
||||
@@ -106,6 +106,7 @@ NetworkInterface::addNode(vector<MessageBuffer*>& in,
|
||||
// protocol injects messages into the NI
|
||||
for (int j = 0; j < m_virtual_networks; j++) {
|
||||
inNode_ptr[j]->setConsumer(this);
|
||||
inNode_ptr[j]->setClockObj(m_net_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh"
|
||||
|
||||
NetworkLink::NetworkLink(const Params *p)
|
||||
: SimObject(p), FlexibleConsumer(this)
|
||||
: ClockedObject(p), FlexibleConsumer(this)
|
||||
{
|
||||
linkBuffer = new flitBuffer();
|
||||
m_in_port = 0;
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
#include "mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh"
|
||||
#include "mem/ruby/network/garnet/NetworkHeader.hh"
|
||||
#include "params/NetworkLink.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/clocked_object.hh"
|
||||
|
||||
class GarnetNetwork;
|
||||
|
||||
class NetworkLink : public SimObject, public FlexibleConsumer
|
||||
class NetworkLink : public ClockedObject, public FlexibleConsumer
|
||||
{
|
||||
public:
|
||||
typedef NetworkLinkParams Params;
|
||||
|
||||
@@ -68,7 +68,7 @@ PerfectSwitch::init(SimpleNetwork *network_ptr)
|
||||
}
|
||||
|
||||
void
|
||||
PerfectSwitch::addInPort(const vector<MessageBuffer*>& in)
|
||||
PerfectSwitch::addInPort(const vector<MessageBuffer*>& in, Switch *sw)
|
||||
{
|
||||
assert(in.size() == m_virtual_networks);
|
||||
NodeID port = m_in.size();
|
||||
@@ -76,6 +76,8 @@ PerfectSwitch::addInPort(const vector<MessageBuffer*>& in)
|
||||
|
||||
for (int j = 0; j < m_virtual_networks; j++) {
|
||||
m_in[port][j]->setConsumer(this);
|
||||
m_in[port][j]->setClockObj(sw);
|
||||
|
||||
string desc = csprintf("[Queue from port %s %s %s to PerfectSwitch]",
|
||||
to_string(m_switch_id), to_string(port), to_string(j));
|
||||
m_in[port][j]->setDescription(desc);
|
||||
|
||||
@@ -63,7 +63,7 @@ class PerfectSwitch : public Consumer
|
||||
{ return csprintf("PerfectSwitch-%i", m_switch_id); }
|
||||
|
||||
void init(SimpleNetwork *);
|
||||
void addInPort(const std::vector<MessageBuffer*>& in);
|
||||
void addInPort(const std::vector<MessageBuffer*>& in, Switch *);
|
||||
void addOutPort(const std::vector<MessageBuffer*>& out,
|
||||
const NetDest& routing_table_entry);
|
||||
void clearRoutingTables();
|
||||
|
||||
@@ -67,7 +67,7 @@ Switch::init()
|
||||
void
|
||||
Switch::addInPort(const vector<MessageBuffer*>& in)
|
||||
{
|
||||
m_perfect_switch_ptr->addInPort(in);
|
||||
m_perfect_switch_ptr->addInPort(in, this);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -97,7 +97,7 @@ Switch::addOutPort(const vector<MessageBuffer*>& out,
|
||||
m_perfect_switch_ptr->addOutPort(intermediateBuffers, routing_table_entry);
|
||||
|
||||
// Hook the queues to the Throttle
|
||||
throttle_ptr->addLinks(intermediateBuffers, out);
|
||||
throttle_ptr->addLinks(intermediateBuffers, out, this);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -50,7 +50,7 @@ static int network_message_to_size(NetworkMessage* net_msg_ptr);
|
||||
|
||||
Throttle::Throttle(int sID, NodeID node, int link_latency,
|
||||
int link_bandwidth_multiplier, int endpoint_bandwidth,
|
||||
EventManager *em)
|
||||
ClockedObject *em)
|
||||
: Consumer(em)
|
||||
{
|
||||
init(node, link_latency, link_bandwidth_multiplier, endpoint_bandwidth);
|
||||
@@ -59,7 +59,7 @@ Throttle::Throttle(int sID, NodeID node, int link_latency,
|
||||
|
||||
Throttle::Throttle(NodeID node, int link_latency,
|
||||
int link_bandwidth_multiplier, int endpoint_bandwidth,
|
||||
EventManager *em)
|
||||
ClockedObject *em)
|
||||
: Consumer(em)
|
||||
{
|
||||
init(node, link_latency, link_bandwidth_multiplier, endpoint_bandwidth);
|
||||
@@ -93,11 +93,11 @@ Throttle::clear()
|
||||
|
||||
void
|
||||
Throttle::addLinks(const std::vector<MessageBuffer*>& in_vec,
|
||||
const std::vector<MessageBuffer*>& out_vec)
|
||||
const std::vector<MessageBuffer*>& out_vec, ClockedObject *em)
|
||||
{
|
||||
assert(in_vec.size() == out_vec.size());
|
||||
for (int i=0; i<in_vec.size(); i++) {
|
||||
addVirtualNetwork(in_vec[i], out_vec[i]);
|
||||
addVirtualNetwork(in_vec[i], out_vec[i], em);
|
||||
}
|
||||
|
||||
m_message_counters.resize(MessageSizeType_NUM);
|
||||
@@ -110,7 +110,8 @@ Throttle::addLinks(const std::vector<MessageBuffer*>& in_vec,
|
||||
}
|
||||
|
||||
void
|
||||
Throttle::addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr)
|
||||
Throttle::addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr,
|
||||
ClockedObject *em)
|
||||
{
|
||||
m_units_remaining.push_back(0);
|
||||
m_in.push_back(in_ptr);
|
||||
@@ -118,6 +119,8 @@ Throttle::addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr)
|
||||
|
||||
// Set consumer and description
|
||||
m_in[m_vnets]->setConsumer(this);
|
||||
m_in[m_vnets]->setClockObj(em);
|
||||
|
||||
string desc = "[Queue to Throttle " + to_string(m_sID) + " " +
|
||||
to_string(m_node) + "]";
|
||||
m_in[m_vnets]->setDescription(desc);
|
||||
|
||||
@@ -54,16 +54,16 @@ class Throttle : public Consumer
|
||||
public:
|
||||
Throttle(int sID, NodeID node, int link_latency,
|
||||
int link_bandwidth_multiplier, int endpoint_bandwidth,
|
||||
EventManager *em);
|
||||
ClockedObject *em);
|
||||
Throttle(NodeID node, int link_latency, int link_bandwidth_multiplier,
|
||||
int endpoint_bandwidth, EventManager *em);
|
||||
int endpoint_bandwidth, ClockedObject *em);
|
||||
~Throttle() {}
|
||||
|
||||
std::string name()
|
||||
{ return csprintf("Throttle-%i", m_sID); }
|
||||
|
||||
void addLinks(const std::vector<MessageBuffer*>& in_vec,
|
||||
const std::vector<MessageBuffer*>& out_vec);
|
||||
const std::vector<MessageBuffer*>& out_vec, ClockedObject *em);
|
||||
void wakeup();
|
||||
|
||||
void printStats(std::ostream& out) const;
|
||||
@@ -90,7 +90,8 @@ class Throttle : public Consumer
|
||||
private:
|
||||
void init(NodeID node, int link_latency, int link_bandwidth_multiplier,
|
||||
int endpoint_bandwidth);
|
||||
void addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr);
|
||||
void addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr,
|
||||
ClockedObject *em);
|
||||
void linkUtilized(double ratio) { m_links_utilized += ratio; }
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
|
||||
@@ -137,7 +137,7 @@ Profiler::wakeup()
|
||||
}
|
||||
|
||||
//g_system_ptr->getNetwork()->printStats(out);
|
||||
schedule(m_event, g_system_ptr->clockEdge(Cycles(m_stats_period )));
|
||||
schedule(m_event, g_system_ptr->clockEdge(Cycles(m_stats_period)));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -571,7 +571,7 @@ Profiler::profileSharing(const Address& addr, AccessType type,
|
||||
}
|
||||
|
||||
void
|
||||
Profiler::profileMsgDelay(int virtualNetwork, int delayCycles)
|
||||
Profiler::profileMsgDelay(uint32_t virtualNetwork, Time delayCycles)
|
||||
{
|
||||
assert(virtualNetwork < m_delayedCyclesVCHistograms.size());
|
||||
m_delayedCyclesHistogram.add(delayCycles);
|
||||
|
||||
@@ -152,7 +152,7 @@ class Profiler : public SimObject
|
||||
|
||||
void sequencerRequests(int num) { m_sequencer_requests.add(num); }
|
||||
|
||||
void profileMsgDelay(int virtualNetwork, int delayCycles);
|
||||
void profileMsgDelay(uint32_t virtualNetwork, Time delayCycles);
|
||||
|
||||
void print(std::ostream& out) const;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "mem/ruby/system/System.hh"
|
||||
|
||||
AbstractController::AbstractController(const Params *p)
|
||||
: SimObject(p), Consumer(this)
|
||||
: ClockedObject(p), Consumer(this)
|
||||
{
|
||||
m_version = p->version;
|
||||
m_transitions_per_cycle = p->transitions_per_cycle;
|
||||
|
||||
@@ -41,12 +41,12 @@
|
||||
#include "mem/ruby/system/MachineID.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "params/RubyController.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/clocked_object.hh"
|
||||
|
||||
class MessageBuffer;
|
||||
class Network;
|
||||
|
||||
class AbstractController : public SimObject, public Consumer
|
||||
class AbstractController : public ClockedObject, public Consumer
|
||||
{
|
||||
public:
|
||||
typedef RubyControllerParams Params;
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
# Brad Beckmann
|
||||
|
||||
from m5.params import *
|
||||
from m5.SimObject import SimObject
|
||||
from ClockedObject import ClockedObject
|
||||
|
||||
class RubyController(SimObject):
|
||||
class RubyController(ClockedObject):
|
||||
type = 'RubyController'
|
||||
cxx_class = 'AbstractController'
|
||||
cxx_header = "mem/ruby/slicc_interface/AbstractController.hh"
|
||||
|
||||
@@ -73,12 +73,11 @@ class Message : public RefCounted
|
||||
virtual bool functionalWrite(Packet *pkt) = 0;
|
||||
//{ fatal("Write functional access not implemented!"); }
|
||||
|
||||
void setDelayedCycles(const int& cycles) { m_DelayedCycles = cycles; }
|
||||
const int& getDelayedCycles() const {return m_DelayedCycles;}
|
||||
int& getDelayedCycles() {return m_DelayedCycles;}
|
||||
void setDelayedCycles(const Time cycles) { m_DelayedCycles = cycles; }
|
||||
const Time getDelayedCycles() const {return m_DelayedCycles;}
|
||||
|
||||
void setLastEnqueueTime(const Time& time) { m_LastEnqueueTime = time; }
|
||||
const Time& getLastEnqueueTime() const {return m_LastEnqueueTime;}
|
||||
Time& getLastEnqueueTime() {return m_LastEnqueueTime;}
|
||||
const Time getLastEnqueueTime() const {return m_LastEnqueueTime;}
|
||||
|
||||
const Time& getTime() const { return m_time; }
|
||||
void setTime(const Time& new_time) { m_time = new_time; }
|
||||
|
||||
@@ -66,7 +66,7 @@ profile_sharing(const Address& addr, AccessType type, NodeID requestor,
|
||||
}
|
||||
|
||||
void
|
||||
profileMsgDelay(int virtualNetwork, int delayCycles)
|
||||
profileMsgDelay(uint32_t virtualNetwork, Time delayCycles)
|
||||
{
|
||||
g_system_ptr->getProfiler()->profileMsgDelay(virtualNetwork, delayCycles);
|
||||
}
|
||||
@@ -86,6 +86,3 @@ profileGetS(const Address& datablock, const Address& PC, const Set& owner,
|
||||
g_system_ptr->getProfiler()->getAddressProfiler()->
|
||||
profileGetS(datablock, PC, owner, sharers, requestor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ void profile_token_retry(const Address& addr, AccessType type, int count);
|
||||
void profile_filter_action(int action);
|
||||
void profile_persistent_prediction(const Address& addr, AccessType type);
|
||||
void profile_average_latency_estimate(int latency);
|
||||
void profileMsgDelay(int virtualNetwork, int delayCycles);
|
||||
void profileMsgDelay(uint32_t virtualNetwork, Time delayCycles);
|
||||
|
||||
void profile_multicast_retry(const Address& addr, int count);
|
||||
void profileGetX(const Address& datablock, const Address& PC, const Set& owner,
|
||||
|
||||
@@ -60,6 +60,8 @@ class MemoryControl : public ClockedObject, public Consumer
|
||||
|
||||
virtual void setConsumer(Consumer* consumer_ptr) = 0;
|
||||
virtual Consumer* getConsumer() = 0;
|
||||
virtual void setClockObj(ClockedObject* consumer_ptr) {}
|
||||
|
||||
virtual void setDescription(const std::string& name) = 0;
|
||||
virtual std::string getDescription() = 0;
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ Sequencer::wakeup()
|
||||
assert(getDrainState() != Drainable::Draining);
|
||||
|
||||
// Check for deadlock of any of the requests
|
||||
Time current_time = g_system_ptr->getTime();
|
||||
Time current_time = curCycle();
|
||||
|
||||
// Check across all outstanding requests
|
||||
int total_outstanding = 0;
|
||||
@@ -130,8 +130,7 @@ Sequencer::wakeup()
|
||||
|
||||
if (m_outstanding_count > 0) {
|
||||
// If there are still outstanding requests, keep checking
|
||||
schedule(deadlockCheckEvent,
|
||||
g_system_ptr->clockPeriod() * m_deadlock_threshold + curTick());
|
||||
schedule(deadlockCheckEvent, clockEdge(m_deadlock_threshold));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,8 +210,7 @@ Sequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type)
|
||||
// See if we should schedule a deadlock check
|
||||
if (!deadlockCheckEvent.scheduled() &&
|
||||
getDrainState() != Drainable::Draining) {
|
||||
schedule(deadlockCheckEvent,
|
||||
g_system_ptr->clockPeriod() * m_deadlock_threshold + curTick());
|
||||
schedule(deadlockCheckEvent, clockEdge(m_deadlock_threshold));
|
||||
}
|
||||
|
||||
Address line_addr(pkt->getAddr());
|
||||
@@ -242,8 +240,7 @@ Sequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type)
|
||||
m_writeRequestTable.insert(default_entry);
|
||||
if (r.second) {
|
||||
RequestTable::iterator i = r.first;
|
||||
i->second = new SequencerRequest(pkt, request_type,
|
||||
g_system_ptr->getTime());
|
||||
i->second = new SequencerRequest(pkt, request_type, curCycle());
|
||||
m_outstanding_count++;
|
||||
} else {
|
||||
// There is an outstanding write request for the cache line
|
||||
@@ -263,8 +260,7 @@ Sequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type)
|
||||
|
||||
if (r.second) {
|
||||
RequestTable::iterator i = r.first;
|
||||
i->second = new SequencerRequest(pkt, request_type,
|
||||
g_system_ptr->getTime());
|
||||
i->second = new SequencerRequest(pkt, request_type, curCycle());
|
||||
m_outstanding_count++;
|
||||
} else {
|
||||
// There is an outstanding read request for the cache line
|
||||
@@ -480,8 +476,8 @@ Sequencer::hitCallback(SequencerRequest* srequest,
|
||||
m_dataCache_ptr->setMRU(request_line_address);
|
||||
}
|
||||
|
||||
assert(g_system_ptr->getTime() >= issued_time);
|
||||
Time miss_latency = g_system_ptr->getTime() - issued_time;
|
||||
assert(curCycle() >= issued_time);
|
||||
Time miss_latency = curCycle() - issued_time;
|
||||
|
||||
// Profile the miss latency for all non-zero demand misses
|
||||
if (miss_latency != 0) {
|
||||
@@ -489,18 +485,14 @@ Sequencer::hitCallback(SequencerRequest* srequest,
|
||||
|
||||
if (mach == GenericMachineType_L1Cache_wCC) {
|
||||
g_system_ptr->getProfiler()->missLatencyWcc(issued_time,
|
||||
initialRequestTime,
|
||||
forwardRequestTime,
|
||||
firstResponseTime,
|
||||
g_system_ptr->getTime());
|
||||
initialRequestTime, forwardRequestTime,
|
||||
firstResponseTime, curCycle());
|
||||
}
|
||||
|
||||
if (mach == GenericMachineType_Directory) {
|
||||
g_system_ptr->getProfiler()->missLatencyDir(issued_time,
|
||||
initialRequestTime,
|
||||
forwardRequestTime,
|
||||
firstResponseTime,
|
||||
g_system_ptr->getTime());
|
||||
initialRequestTime, forwardRequestTime,
|
||||
firstResponseTime, curCycle());
|
||||
}
|
||||
|
||||
DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %d cycles\n",
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
TimerTable::TimerTable()
|
||||
{
|
||||
m_consumer_ptr = NULL;
|
||||
m_clockobj_ptr = NULL;
|
||||
|
||||
m_next_valid = false;
|
||||
m_next_address = Address(0);
|
||||
m_next_time = 0;
|
||||
@@ -48,7 +50,7 @@ TimerTable::isReady() const
|
||||
updateNext();
|
||||
}
|
||||
assert(m_next_valid);
|
||||
return (g_system_ptr->getTime() >= m_next_time);
|
||||
return (m_clockobj_ptr->curCycle() >= m_next_time);
|
||||
}
|
||||
|
||||
const Address&
|
||||
@@ -69,7 +71,7 @@ TimerTable::set(const Address& address, Time relative_latency)
|
||||
assert(address == line_address(address));
|
||||
assert(relative_latency > 0);
|
||||
assert(!m_map.count(address));
|
||||
Time ready_time = g_system_ptr->getTime() + relative_latency;
|
||||
Time ready_time = m_clockobj_ptr->curCycle() + relative_latency;
|
||||
m_map[address] = ready_time;
|
||||
assert(m_consumer_ptr != NULL);
|
||||
m_consumer_ptr->scheduleEventAbsolute(ready_time);
|
||||
|
||||
@@ -49,6 +49,12 @@ class TimerTable
|
||||
m_consumer_ptr = consumer_ptr;
|
||||
}
|
||||
|
||||
void setClockObj(ClockedObject* obj)
|
||||
{
|
||||
assert(m_clockobj_ptr == NULL);
|
||||
m_clockobj_ptr = obj;
|
||||
}
|
||||
|
||||
void
|
||||
setDescription(const std::string& name)
|
||||
{
|
||||
@@ -78,7 +84,12 @@ class TimerTable
|
||||
mutable bool m_next_valid;
|
||||
mutable Time m_next_time; // Only valid if m_next_valid is true
|
||||
mutable Address m_next_address; // Only valid if m_next_valid is true
|
||||
Consumer* m_consumer_ptr; // Consumer to signal a wakeup()
|
||||
|
||||
//! Object used for querying time.
|
||||
ClockedObject* m_clockobj_ptr;
|
||||
//! Consumer to signal a wakeup()
|
||||
Consumer* m_consumer_ptr;
|
||||
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
|
||||
@@ -55,6 +55,6 @@ class AST(PairContainer):
|
||||
code = self.slicc.codeFormatter()
|
||||
code('''
|
||||
panic("Runtime Error at ${{self.location}}, Ruby Time: %d, %s.\\n",
|
||||
g_system_ptr->getTime(), $message);
|
||||
curCycle(), $message);
|
||||
''')
|
||||
return code
|
||||
|
||||
@@ -527,6 +527,8 @@ $c_ident::init()
|
||||
{
|
||||
MachineType machine_type;
|
||||
int base;
|
||||
machine_type = string_to_MachineType("${{var.machine.ident}}");
|
||||
base = MachineType_base_number(machine_type);
|
||||
|
||||
m_machineID.type = MachineType_${ident};
|
||||
m_machineID.num = m_version;
|
||||
@@ -592,8 +594,6 @@ $c_ident::init()
|
||||
|
||||
assert var.machine is not None
|
||||
code('''
|
||||
machine_type = string_to_MachineType("${{var.machine.ident}}");
|
||||
base = MachineType_base_number(machine_type);
|
||||
$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type");
|
||||
''')
|
||||
|
||||
@@ -638,15 +638,14 @@ $vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{v
|
||||
for prefetcher in self.prefetchers:
|
||||
code('${{prefetcher.code}}.setController(this);')
|
||||
|
||||
# Set the queue consumers
|
||||
code()
|
||||
for port in self.in_ports:
|
||||
# Set the queue consumers
|
||||
code('${{port.code}}.setConsumer(this);')
|
||||
|
||||
# Set the queue descriptions
|
||||
code()
|
||||
for port in self.in_ports:
|
||||
# Set the queue descriptions
|
||||
code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");')
|
||||
# Set the clock object
|
||||
code('${{port.code}}.setClockObj(this);')
|
||||
|
||||
# Initialize the transition profiling
|
||||
code()
|
||||
@@ -1139,7 +1138,7 @@ ${ident}_Controller::doTransition(${ident}_Event event,
|
||||
${ident}_State next_state = state;
|
||||
|
||||
DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n",
|
||||
*this, g_system_ptr->getTime(), ${ident}_State_to_string(state),
|
||||
*this, curCycle(), ${ident}_State_to_string(state),
|
||||
${ident}_Event_to_string(event), addr);
|
||||
|
||||
TransitionResult result =
|
||||
@@ -1312,7 +1311,7 @@ if (!checkResourceAvailable(%s_RequestType_%s, addr)) {
|
||||
default:
|
||||
fatal("Invalid transition\\n"
|
||||
"%s time: %d addr: %s event: %s state: %s\\n",
|
||||
name(), g_system_ptr->getTime(), addr, event, state);
|
||||
name(), curCycle(), addr, event, state);
|
||||
}
|
||||
return TransitionResult_Valid;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user