ruby: get rid of RefCnt and Allocator stuff use base/refcnt.hh
This was somewhat tricky because the RefCnt API was somewhat odd. The biggest confusion was that the the RefCnt object's constructor that took a TYPE& cloned the object. I created an explicit virtual clone() function for things that took advantage of this version of the constructor. I was conservative and used clone() when I was in doubt of whether or not it was necessary. I still think that there are probably too many instances of clone(), but hopefully not too many. I converted several instances of const MsgPtr & to a simple MsgPtr. If the function wants to avoid the overhead of creating another reference, then it should just use a regular pointer instead of a ref counting ptr. There were a couple of instances where refcounted objects were created on the stack. This seems pretty dangerous since if you ever accidentally make a reference to that object with a ref counting pointer, bad things are bound to happen.
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Mark D. Hill and David A. Wood
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ALLOCATOR_H
|
||||
#define ALLOCATOR_H
|
||||
|
||||
#include "mem/gems_common/Vector.hh"
|
||||
|
||||
template <class TYPE>
|
||||
class Allocator {
|
||||
public:
|
||||
// Constructors
|
||||
Allocator() { m_counter = 0; }
|
||||
|
||||
// Destructor
|
||||
~Allocator() { for(int i=0; i<m_pool_vec.size(); i++) { delete m_pool_vec[i]; }}
|
||||
|
||||
// Public Methods
|
||||
TYPE* allocate(const TYPE& obj);
|
||||
void deallocate(TYPE* obj_ptr);
|
||||
private:
|
||||
// Private copy constructor and assignment operator
|
||||
Allocator(const Allocator& obj);
|
||||
Allocator& operator=(const Allocator& obj);
|
||||
|
||||
// Private Methods
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
Vector<TYPE*> m_pool_vec;
|
||||
int m_counter;
|
||||
};
|
||||
|
||||
template <class TYPE>
|
||||
inline
|
||||
TYPE* Allocator<TYPE>::allocate(const TYPE& obj)
|
||||
{
|
||||
m_counter++;
|
||||
DPRINTF(GemsCommon, "couter %d", m_counter);
|
||||
TYPE* new_obj_ptr;
|
||||
|
||||
// See if we need to allocate any new objects
|
||||
if (m_pool_vec.size() == 0) {
|
||||
// Allocate a new item
|
||||
m_pool_vec.insertAtBottom(new TYPE);
|
||||
}
|
||||
|
||||
// Pop the pointer from the stack/pool
|
||||
int size = m_pool_vec.size();
|
||||
new_obj_ptr = m_pool_vec[size-1];
|
||||
m_pool_vec.setSize(size-1);
|
||||
|
||||
// Copy the object
|
||||
*new_obj_ptr = obj;
|
||||
return new_obj_ptr;
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
inline
|
||||
void Allocator<TYPE>::deallocate(TYPE* obj)
|
||||
{
|
||||
m_pool_vec.insertAtBottom(obj);
|
||||
}
|
||||
|
||||
#endif //ALLOCATOR_H
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef REFCNT_H
|
||||
#define REFCNT_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class TYPE>
|
||||
class RefCnt {
|
||||
public:
|
||||
// Constructors
|
||||
RefCnt();
|
||||
RefCnt(const TYPE& data);
|
||||
|
||||
// Destructor
|
||||
~RefCnt();
|
||||
|
||||
// Public Methods
|
||||
const TYPE* ref() const { return m_data_ptr; }
|
||||
TYPE* ref() { return m_data_ptr; }
|
||||
TYPE* mod_ref() const { return m_data_ptr; }
|
||||
void freeRef();
|
||||
void print(std::ostream& out) const;
|
||||
|
||||
// Public copy constructor and assignment operator
|
||||
RefCnt(const RefCnt& obj);
|
||||
RefCnt& operator=(const RefCnt& obj);
|
||||
|
||||
private:
|
||||
// Private Methods
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
TYPE* m_data_ptr;
|
||||
// int* m_count_ptr; // Not used yet
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
template <class TYPE>
|
||||
inline
|
||||
std::ostream& operator<<(std::ostream& out, const RefCnt<TYPE>& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Constructors
|
||||
template <class TYPE>
|
||||
inline
|
||||
RefCnt<TYPE>::RefCnt()
|
||||
{
|
||||
m_data_ptr = NULL;
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
inline
|
||||
RefCnt<TYPE>::RefCnt(const TYPE& data)
|
||||
{
|
||||
m_data_ptr = data.clone();
|
||||
m_data_ptr->setRefCnt(1);
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
inline
|
||||
RefCnt<TYPE>::~RefCnt()
|
||||
{
|
||||
freeRef();
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
inline
|
||||
void RefCnt<TYPE>::freeRef()
|
||||
{
|
||||
if (m_data_ptr != NULL) {
|
||||
m_data_ptr->decRefCnt();
|
||||
if (m_data_ptr->getRefCnt() == 0) {
|
||||
m_data_ptr->destroy();
|
||||
}
|
||||
m_data_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
inline
|
||||
void RefCnt<TYPE>::print(std::ostream& out) const
|
||||
{
|
||||
if (m_data_ptr == NULL) {
|
||||
out << "[RefCnt: Null]";
|
||||
} else {
|
||||
out << "[RefCnt: ";
|
||||
m_data_ptr->print(out);
|
||||
out << "]";
|
||||
}
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
template <class TYPE>
|
||||
inline
|
||||
RefCnt<TYPE>::RefCnt(const RefCnt<TYPE>& obj)
|
||||
{
|
||||
// m_data_ptr = obj.m_data_ptr->clone();
|
||||
m_data_ptr = obj.m_data_ptr;
|
||||
|
||||
// Increment the reference count
|
||||
if (m_data_ptr != NULL) {
|
||||
m_data_ptr->incRefCnt();
|
||||
}
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
template <class TYPE>
|
||||
inline
|
||||
RefCnt<TYPE>& RefCnt<TYPE>::operator=(const RefCnt<TYPE>& obj)
|
||||
{
|
||||
if (this == &obj) {
|
||||
// If this is the case, do nothing
|
||||
// assert(false);
|
||||
} else {
|
||||
freeRef();
|
||||
m_data_ptr = obj.m_data_ptr;
|
||||
if (m_data_ptr != NULL) {
|
||||
m_data_ptr->incRefCnt();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Output operator definition
|
||||
template <class TYPE>
|
||||
inline
|
||||
std::ostream& operator<<(std::ostream& out, const RefCnt<TYPE>& obj)
|
||||
{
|
||||
obj.print(out);
|
||||
out << std::flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //REFCNT_H
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Code used to test the RefCnt class
|
||||
*/
|
||||
|
||||
#include "mem/gems_common/RefCnt.hh"
|
||||
#include "mem/gems_common/RefCountable.hh"
|
||||
|
||||
class Foo : public RefCountable {
|
||||
public:
|
||||
int m_data;
|
||||
Foo* clone() const;
|
||||
private:
|
||||
};
|
||||
|
||||
Foo* Foo::clone() const
|
||||
{
|
||||
Foo* temp_ptr;
|
||||
temp_ptr = new Foo;
|
||||
*temp_ptr = *this;
|
||||
cout << "Cloned!" << endl;
|
||||
return temp_ptr;
|
||||
}
|
||||
|
||||
void bar(RefCnt<Foo> f)
|
||||
{
|
||||
cout << f.ref()->m_data << endl;
|
||||
}
|
||||
|
||||
Foo f2;
|
||||
|
||||
int main()
|
||||
{
|
||||
Foo f;
|
||||
f.m_data = 2;
|
||||
|
||||
{
|
||||
RefCnt<Foo> a(f);
|
||||
|
||||
f.m_data = 3;
|
||||
cout << a.ref()->m_data << endl;
|
||||
cout << f.m_data << endl;
|
||||
f2 = f;
|
||||
}
|
||||
|
||||
bar(f2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Virtual base class for things that can be reference counted
|
||||
*/
|
||||
|
||||
#ifndef REFCOUNTABLE_H
|
||||
#define REFCOUNTABLE_H
|
||||
|
||||
#include "mem/gems_common/RefCnt.hh"
|
||||
|
||||
class RefCountable {
|
||||
public:
|
||||
// Public Methods
|
||||
|
||||
RefCountable() { m_refcnt = 0; }
|
||||
|
||||
// These are used by the RefCnt class to hold the reference count
|
||||
// for the object. These really should be private and accessed by a
|
||||
// friend class, but I can't figure out how to make a template class
|
||||
// a friend.
|
||||
void incRefCnt() { m_refcnt++; }
|
||||
void decRefCnt() { m_refcnt--; }
|
||||
int getRefCnt() const { return m_refcnt; }
|
||||
void setRefCnt(int cnt) { m_refcnt = cnt; }
|
||||
private:
|
||||
// Private Methods
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
int m_refcnt;
|
||||
};
|
||||
|
||||
#endif //REFCOUNTABLE_H
|
||||
@@ -1,36 +0,0 @@
|
||||
# -*- mode:python -*-
|
||||
|
||||
# Copyright (c) 2009 The Hewlett-Packard Development Company
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Authors: Nathan Binkert
|
||||
|
||||
Import('*')
|
||||
|
||||
if not env['RUBY']:
|
||||
Return()
|
||||
|
||||
TraceFlag('GemsCommon')
|
||||
@@ -111,16 +111,12 @@ MessageBuffer::getMsgPtrCopy() const
|
||||
{
|
||||
assert(isReady());
|
||||
|
||||
MsgPtr temp_msg;
|
||||
temp_msg = *(m_prio_heap.peekMin().m_msgptr.ref());
|
||||
assert(temp_msg.ref() != NULL);
|
||||
return temp_msg;
|
||||
return m_prio_heap.peekMin().m_msgptr->clone();
|
||||
}
|
||||
|
||||
const Message*
|
||||
MessageBuffer::peekAtHeadOfQueue() const
|
||||
{
|
||||
const Message* msg_ptr;
|
||||
DEBUG_NEWLINE(QUEUE_COMP, MedPrio);
|
||||
|
||||
DEBUG_MSG(QUEUE_COMP, MedPrio,
|
||||
@@ -128,8 +124,8 @@ MessageBuffer::peekAtHeadOfQueue() const
|
||||
m_name, g_eventQueue_ptr->getTime()));
|
||||
assert(isReady());
|
||||
|
||||
msg_ptr = m_prio_heap.peekMin().m_msgptr.ref();
|
||||
assert(msg_ptr != NULL);
|
||||
const Message* msg_ptr = m_prio_heap.peekMin().m_msgptr.get();
|
||||
assert(msg_ptr);
|
||||
|
||||
DEBUG_EXPR(QUEUE_COMP, MedPrio, *msg_ptr);
|
||||
DEBUG_NEWLINE(QUEUE_COMP, MedPrio);
|
||||
@@ -149,7 +145,7 @@ random_time()
|
||||
}
|
||||
|
||||
void
|
||||
MessageBuffer::enqueue(const MsgPtr& message, Time delta)
|
||||
MessageBuffer::enqueue(MsgPtr message, Time delta)
|
||||
{
|
||||
DEBUG_NEWLINE(QUEUE_COMP, HighPrio);
|
||||
DEBUG_MSG(QUEUE_COMP, HighPrio,
|
||||
@@ -214,7 +210,7 @@ MessageBuffer::enqueue(const MsgPtr& message, Time delta)
|
||||
m_last_arrival_time = arrival_time;
|
||||
|
||||
// compute the delay cycles and set enqueue time
|
||||
Message* msg_ptr = message.mod_ref();
|
||||
Message* msg_ptr = message.get();
|
||||
assert(msg_ptr != NULL);
|
||||
|
||||
assert(g_eventQueue_ptr->getTime() >= msg_ptr->getLastEnqueueTime() &&
|
||||
@@ -332,12 +328,11 @@ MessageBuffer::recycle()
|
||||
}
|
||||
|
||||
int
|
||||
MessageBuffer::setAndReturnDelayCycles(MsgPtr& message)
|
||||
MessageBuffer::setAndReturnDelayCycles(MsgPtr msg_ptr)
|
||||
{
|
||||
int delay_cycles = -1; // null value
|
||||
|
||||
// get the delay cycles of the message at the top of the queue
|
||||
Message* msg_ptr = message.ref();
|
||||
|
||||
// this function should only be called on dequeue
|
||||
// ensure the msg hasn't been enqueued
|
||||
|
||||
@@ -102,8 +102,8 @@ class MessageBuffer
|
||||
return m_prio_heap.peekMin().m_msgptr;
|
||||
}
|
||||
|
||||
void enqueue(const MsgPtr& message) { enqueue(message, 1); }
|
||||
void enqueue(const MsgPtr& message, Time delta);
|
||||
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
|
||||
@@ -136,7 +136,7 @@ class MessageBuffer
|
||||
int m_recycle_latency;
|
||||
|
||||
// Private Methods
|
||||
int setAndReturnDelayCycles(MsgPtr& message);
|
||||
int setAndReturnDelayCycles(MsgPtr message);
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
MessageBuffer(const MessageBuffer& obj);
|
||||
|
||||
@@ -65,7 +65,6 @@ DebugComponentData debugComponents[] =
|
||||
{"Store Buffer", 'b' },
|
||||
{"Cache", 'c' },
|
||||
{"Predictor", 'p' },
|
||||
{"Allocator", 'a' },
|
||||
{"Memory", 'M' },
|
||||
};
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ enum DebugComponents
|
||||
STOREBUFFER_COMP,
|
||||
CACHE_COMP,
|
||||
PREDICTOR_COMP,
|
||||
ALLOCATOR_COMP,
|
||||
MEMORY_COMP,
|
||||
NUMBER_OF_COMPS
|
||||
};
|
||||
|
||||
@@ -107,7 +107,8 @@ void NetworkInterface_d::addNode(Vector<MessageBuffer*>& in, Vector<MessageBuff
|
||||
|
||||
bool NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet)
|
||||
{
|
||||
NetworkMessage *net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref());
|
||||
NetworkMessage *net_msg_ptr =
|
||||
safe_cast<NetworkMessage *>(msg_ptr.get());
|
||||
NetDest net_msg_dest = net_msg_ptr->getInternalDestination();
|
||||
Vector<NodeID> dest_nodes = net_msg_dest.getAllDest(); // gets all the destinations associated with this message.
|
||||
|
||||
@@ -120,10 +121,11 @@ bool NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet)
|
||||
{
|
||||
return false ;
|
||||
}
|
||||
MsgPtr new_msg_ptr = *(msg_ptr.ref());
|
||||
MsgPtr new_msg_ptr = msg_ptr->clone();
|
||||
NodeID destID = dest_nodes[ctr];
|
||||
|
||||
NetworkMessage *new_net_msg_ptr = dynamic_cast<NetworkMessage*>(new_msg_ptr.ref());
|
||||
NetworkMessage *new_net_msg_ptr =
|
||||
safe_cast<NetworkMessage *>(new_msg_ptr.get());
|
||||
if(dest_nodes.size() > 1)
|
||||
{
|
||||
NetDest personal_dest;
|
||||
@@ -145,7 +147,7 @@ bool NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet)
|
||||
{
|
||||
m_net_ptr->increment_injected_flits();
|
||||
flit_d *fl = new flit_d(i, vc, vnet, num_flits, new_msg_ptr);
|
||||
fl->set_delay(g_eventQueue_ptr->getTime() - (msg_ptr.ref())->getTime());
|
||||
fl->set_delay(g_eventQueue_ptr->getTime() - msg_ptr->getTime());
|
||||
m_ni_buffers[vc]->insert(fl);
|
||||
}
|
||||
m_ni_enqueue_time[vc] = g_eventQueue_ptr->getTime();
|
||||
|
||||
@@ -61,8 +61,8 @@ void RoutingUnit_d::RC_stage(flit_d *t_flit, InputUnit_d *in_unit, int invc)
|
||||
int RoutingUnit_d::routeCompute(flit_d *t_flit)
|
||||
{
|
||||
MsgPtr msg_ptr = t_flit->get_msg_ptr();
|
||||
NetworkMessage* net_msg_ptr = NULL;
|
||||
net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref());
|
||||
NetworkMessage* net_msg_ptr =
|
||||
safe_cast<NetworkMessage*>(msg_ptr.get());
|
||||
NetDest msg_destination = net_msg_ptr->getInternalDestination();
|
||||
|
||||
int output_link = -1;
|
||||
|
||||
@@ -103,7 +103,8 @@ void NetworkInterface::request_vc(int in_vc, int in_port, NetDest destination, T
|
||||
|
||||
bool NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
|
||||
{
|
||||
NetworkMessage *net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref());
|
||||
NetworkMessage *net_msg_ptr =
|
||||
safe_cast<NetworkMessage*>(msg_ptr.get());
|
||||
NetDest net_msg_dest = net_msg_ptr->getInternalDestination();
|
||||
Vector<NodeID> dest_nodes = net_msg_dest.getAllDest(); // gets all the destinations associated with this message.
|
||||
int num_flits = (int) ceil((double) m_net_ptr->MessageSizeType_to_int(net_msg_ptr->getMessageSize())/m_net_ptr->getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size
|
||||
@@ -117,10 +118,11 @@ bool NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
|
||||
// did not find a free output vc
|
||||
return false ;
|
||||
}
|
||||
MsgPtr new_msg_ptr = *(msg_ptr.ref());
|
||||
MsgPtr new_msg_ptr = msg_ptr->clone();
|
||||
NodeID destID = dest_nodes[ctr];
|
||||
|
||||
NetworkMessage *new_net_msg_ptr = dynamic_cast<NetworkMessage*>(new_msg_ptr.ref());
|
||||
NetworkMessage *new_net_msg_ptr =
|
||||
safe_cast<NetworkMessage*>(new_msg_ptr.get());
|
||||
if(dest_nodes.size() > 1)
|
||||
{
|
||||
NetDest personal_dest;
|
||||
|
||||
@@ -252,7 +252,9 @@ void Router::routeCompute(flit *m_flit, int inport)
|
||||
g_eventQueue_ptr->scheduleEvent(this, m_net_ptr->getNumPipeStages() -1 );
|
||||
if((m_flit->get_type() == HEAD_) || (m_flit->get_type() == HEAD_TAIL_))
|
||||
{
|
||||
NetDest destination = dynamic_cast<NetworkMessage*>(m_flit->get_msg_ptr().ref())->getInternalDestination();
|
||||
NetworkMessage *nm =
|
||||
safe_cast<NetworkMessage*>(m_flit->get_msg_ptr().get());
|
||||
NetDest destination = nm->getInternalDestination();
|
||||
if(m_net_ptr->getNumPipeStages() > 1)
|
||||
{
|
||||
m_out_vc_state[outport][outvc]->setState(VC_AB_, g_eventQueue_ptr->getTime() + 1);
|
||||
|
||||
@@ -170,7 +170,7 @@ PerfectSwitch::wakeup()
|
||||
|
||||
// Peek at message
|
||||
msg_ptr = m_in[incoming][vnet]->peekMsgPtr();
|
||||
net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref());
|
||||
net_msg_ptr = safe_cast<NetworkMessage*>(msg_ptr.get());
|
||||
DEBUG_EXPR(NETWORK_COMP, MedPrio, *net_msg_ptr);
|
||||
|
||||
output_links.clear();
|
||||
@@ -272,7 +272,7 @@ PerfectSwitch::wakeup()
|
||||
|
||||
// This magic line creates a private copy of the
|
||||
// message
|
||||
unmodified_msg_ptr = *(msg_ptr.ref());
|
||||
unmodified_msg_ptr = msg_ptr->clone();
|
||||
}
|
||||
|
||||
// Enqueue it - for all outgoing queues
|
||||
@@ -282,13 +282,13 @@ PerfectSwitch::wakeup()
|
||||
if (i > 0) {
|
||||
// create a private copy of the unmodified
|
||||
// message
|
||||
msg_ptr = *(unmodified_msg_ptr.ref());
|
||||
msg_ptr = unmodified_msg_ptr->clone();
|
||||
}
|
||||
|
||||
// Change the internal destination set of the
|
||||
// message so it knows which destinations this
|
||||
// link is responsible for.
|
||||
net_msg_ptr = safe_cast<NetworkMessage*>(msg_ptr.ref());
|
||||
net_msg_ptr = safe_cast<NetworkMessage*>(msg_ptr.get());
|
||||
net_msg_ptr->getInternalDestination() =
|
||||
output_link_destinations[i];
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ Throttle::wakeup()
|
||||
// Find the size of the message we are moving
|
||||
MsgPtr msg_ptr = m_in[vnet]->peekMsgPtr();
|
||||
NetworkMessage* net_msg_ptr =
|
||||
safe_cast<NetworkMessage*>(msg_ptr.ref());
|
||||
safe_cast<NetworkMessage*>(msg_ptr.get());
|
||||
m_units_remaining[vnet] +=
|
||||
network_message_to_size(net_msg_ptr);
|
||||
|
||||
|
||||
@@ -31,29 +31,31 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "mem/gems_common/RefCnt.hh"
|
||||
#include "mem/gems_common/RefCountable.hh"
|
||||
#include "base/refcnt.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
|
||||
|
||||
class Message;
|
||||
typedef RefCnt<Message> MsgPtr;
|
||||
typedef RefCountingPtr<Message> MsgPtr;
|
||||
|
||||
class Message : public RefCountable
|
||||
class Message : public RefCounted
|
||||
{
|
||||
public:
|
||||
Message()
|
||||
: RefCountable()
|
||||
{
|
||||
m_time = g_eventQueue_ptr->getTime();
|
||||
m_LastEnqueueTime = g_eventQueue_ptr->getTime();
|
||||
m_DelayedCycles = 0;
|
||||
}
|
||||
: m_time(g_eventQueue_ptr->getTime()),
|
||||
m_LastEnqueueTime(g_eventQueue_ptr->getTime()),
|
||||
m_DelayedCycles(0)
|
||||
{ }
|
||||
|
||||
Message(const Message &other)
|
||||
: m_time(other.m_time),
|
||||
m_LastEnqueueTime(other.m_LastEnqueueTime),
|
||||
m_DelayedCycles(other.m_DelayedCycles)
|
||||
{ }
|
||||
|
||||
virtual ~Message() { }
|
||||
|
||||
virtual Message* clone() const = 0;
|
||||
virtual void destroy() = 0;
|
||||
virtual void print(std::ostream& out) const = 0;
|
||||
|
||||
void setDelayedCycles(const int& cycles) { m_DelayedCycles = cycles; }
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "mem/gems_common/RefCnt.hh"
|
||||
#include "mem/gems_common/RefCountable.hh"
|
||||
#include "base/refcnt.hh"
|
||||
#include "mem/protocol/MessageSizeType.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/common/NetDest.hh"
|
||||
@@ -41,16 +40,18 @@
|
||||
class Address;
|
||||
|
||||
class NetworkMessage;
|
||||
typedef RefCnt<NetworkMessage> NetMsgPtr;
|
||||
typedef RefCountingPtr<NetworkMessage> NetMsgPtr;
|
||||
|
||||
class NetworkMessage : public Message
|
||||
{
|
||||
public:
|
||||
NetworkMessage()
|
||||
: Message()
|
||||
{
|
||||
m_internal_dest_valid = false;
|
||||
}
|
||||
: m_internal_dest_valid(false)
|
||||
{ }
|
||||
|
||||
NetworkMessage(const NetworkMessage &other)
|
||||
: Message(other), m_internal_dest_valid(other.m_internal_dest_valid)
|
||||
{ }
|
||||
|
||||
virtual ~NetworkMessage() { }
|
||||
|
||||
|
||||
@@ -82,22 +82,22 @@ DMASequencer::makeRequest(const RubyRequest &request)
|
||||
active_request.bytes_issued = 0;
|
||||
active_request.pkt = request.pkt;
|
||||
|
||||
SequencerMsg msg;
|
||||
msg.getPhysicalAddress() = Address(paddr);
|
||||
msg.getLineAddress() = line_address(msg.getPhysicalAddress());
|
||||
msg.getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD;
|
||||
SequencerMsg *msg = new SequencerMsg;
|
||||
msg->getPhysicalAddress() = Address(paddr);
|
||||
msg->getLineAddress() = line_address(msg->getPhysicalAddress());
|
||||
msg->getType() = write ? SequencerRequestType_ST : SequencerRequestType_LD;
|
||||
int offset = paddr & m_data_block_mask;
|
||||
|
||||
msg.getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ?
|
||||
msg->getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ?
|
||||
len : RubySystem::getBlockSizeBytes() - offset;
|
||||
|
||||
if (write) {
|
||||
msg.getDataBlk().setData(data, offset, msg.getLen());
|
||||
msg->getDataBlk().setData(data, offset, msg->getLen());
|
||||
}
|
||||
|
||||
assert(m_mandatory_q_ptr != NULL);
|
||||
m_mandatory_q_ptr->enqueue(msg);
|
||||
active_request.bytes_issued += msg.getLen();
|
||||
active_request.bytes_issued += msg->getLen();
|
||||
|
||||
return RequestStatus_Issued;
|
||||
}
|
||||
@@ -113,34 +113,34 @@ DMASequencer::issueNext()
|
||||
return;
|
||||
}
|
||||
|
||||
SequencerMsg msg;
|
||||
msg.getPhysicalAddress() = Address(active_request.start_paddr +
|
||||
SequencerMsg *msg = new SequencerMsg;
|
||||
msg->getPhysicalAddress() = Address(active_request.start_paddr +
|
||||
active_request.bytes_completed);
|
||||
|
||||
assert((msg.getPhysicalAddress().getAddress() & m_data_block_mask) == 0);
|
||||
msg.getLineAddress() = line_address(msg.getPhysicalAddress());
|
||||
assert((msg->getPhysicalAddress().getAddress() & m_data_block_mask) == 0);
|
||||
msg->getLineAddress() = line_address(msg->getPhysicalAddress());
|
||||
|
||||
msg.getType() = (active_request.write ? SequencerRequestType_ST :
|
||||
msg->getType() = (active_request.write ? SequencerRequestType_ST :
|
||||
SequencerRequestType_LD);
|
||||
|
||||
msg.getLen() =
|
||||
msg->getLen() =
|
||||
(active_request.len -
|
||||
active_request.bytes_completed < RubySystem::getBlockSizeBytes() ?
|
||||
active_request.len - active_request.bytes_completed :
|
||||
RubySystem::getBlockSizeBytes());
|
||||
|
||||
if (active_request.write) {
|
||||
msg.getDataBlk().
|
||||
msg->getDataBlk().
|
||||
setData(&active_request.data[active_request.bytes_completed],
|
||||
0, msg.getLen());
|
||||
msg.getType() = SequencerRequestType_ST;
|
||||
0, msg->getLen());
|
||||
msg->getType() = SequencerRequestType_ST;
|
||||
} else {
|
||||
msg.getType() = SequencerRequestType_LD;
|
||||
msg->getType() = SequencerRequestType_LD;
|
||||
}
|
||||
|
||||
assert(m_mandatory_q_ptr != NULL);
|
||||
m_mandatory_q_ptr->enqueue(msg);
|
||||
active_request.bytes_issued += msg.getLen();
|
||||
active_request.bytes_issued += msg->getLen();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -239,7 +239,7 @@ MemoryControl::enqueue(const MsgPtr& message, int latency)
|
||||
{
|
||||
Time current_time = g_eventQueue_ptr->getTime();
|
||||
Time arrival_time = current_time + latency;
|
||||
const MemoryMsg* memMess = dynamic_cast<const MemoryMsg*>(message.ref());
|
||||
const MemoryMsg* memMess = safe_cast<const MemoryMsg*>(message.get());
|
||||
physical_address_t addr = memMess->getAddress().getAddress();
|
||||
MemoryRequestType type = memMess->getType();
|
||||
bool is_mem_read = (type == MemoryRequestType_MEMORY_READ);
|
||||
@@ -285,7 +285,7 @@ const Message*
|
||||
MemoryControl::peek()
|
||||
{
|
||||
MemoryNode node = peekNode();
|
||||
Message* msg_ptr = node.m_msgptr.ref();
|
||||
Message* msg_ptr = node.m_msgptr.get();
|
||||
assert(msg_ptr != NULL);
|
||||
return msg_ptr;
|
||||
}
|
||||
@@ -536,7 +536,7 @@ MemoryControl::issueRequest(int bank)
|
||||
req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W',
|
||||
current_time, bank);
|
||||
}
|
||||
if (req.m_msgptr.ref() != NULL) { // don't enqueue L3 writebacks
|
||||
if (req.m_msgptr) { // don't enqueue L3 writebacks
|
||||
enqueueToDirectory(req, m_mem_ctl_latency + m_mem_fixed_delay);
|
||||
}
|
||||
m_oldRequest[bank] = 0;
|
||||
|
||||
@@ -536,9 +536,9 @@ Sequencer::issueRequest(const RubyRequest& request)
|
||||
|
||||
Address line_addr(request.paddr);
|
||||
line_addr.makeLineAddress();
|
||||
CacheMsg msg(line_addr, Address(request.paddr), ctype,
|
||||
Address(request.pc), amtype, request.len, PrefetchBit_No,
|
||||
request.proc_id);
|
||||
CacheMsg *msg = new CacheMsg(line_addr, Address(request.paddr), ctype,
|
||||
Address(request.pc), amtype, request.len, PrefetchBit_No,
|
||||
request.proc_id);
|
||||
|
||||
if (Debug::getProtocolTrace()) {
|
||||
g_system_ptr->getProfiler()->
|
||||
|
||||
@@ -48,12 +48,12 @@ class EnqueueStatementAST(StatementAST):
|
||||
msg_type = self.type_ast.type
|
||||
|
||||
# Add new local var to symbol table
|
||||
v = Var(self.symtab, "out_msg", self.location, msg_type, "out_msg",
|
||||
v = Var(self.symtab, "out_msg", self.location, msg_type, "*out_msg",
|
||||
self.pairs)
|
||||
self.symtab.newSymbol(v)
|
||||
|
||||
# Declare message
|
||||
code("${{msg_type.ident}} out_msg;")
|
||||
code("${{msg_type.ident}} *out_msg = new ${{msg_type.ident}};")
|
||||
|
||||
# The other statements
|
||||
t = self.statements.generate(code, None)
|
||||
|
||||
@@ -205,7 +205,6 @@ class Type(Symbol):
|
||||
#include <iostream>
|
||||
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/gems_common/Allocator.hh"
|
||||
''')
|
||||
|
||||
for dm in self.data_members.values():
|
||||
@@ -242,6 +241,26 @@ $klass ${{self.c_ident}}$parent
|
||||
code.dedent()
|
||||
code('}')
|
||||
|
||||
# ******** Copy constructor ********
|
||||
if not self.isGlobal:
|
||||
code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
|
||||
|
||||
# Call superclass constructor
|
||||
if "interface" in self:
|
||||
code(' : ${{self["interface"]}}(other)')
|
||||
|
||||
code('{')
|
||||
code.indent()
|
||||
|
||||
for dm in self.data_members.values():
|
||||
code('m_${{dm.ident}} = other.m_${{dm.ident}};')
|
||||
|
||||
if self.isMessage:
|
||||
code('proc_id = other.proc_id;')
|
||||
|
||||
code.dedent()
|
||||
code('}')
|
||||
|
||||
# ******** Full init constructor ********
|
||||
if not self.isGlobal:
|
||||
params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
|
||||
@@ -270,44 +289,18 @@ $klass ${{self.c_ident}}$parent
|
||||
code.dedent()
|
||||
code('}')
|
||||
|
||||
# create a static factory method
|
||||
if "interface" in self:
|
||||
code('''
|
||||
static ${{self["interface"]}}*
|
||||
# create a static factory method and a clone member
|
||||
code('''
|
||||
static ${{self.c_ident}}*
|
||||
create()
|
||||
{
|
||||
return new ${{self.c_ident}}();
|
||||
}
|
||||
''')
|
||||
|
||||
# ******** Message member functions ********
|
||||
# FIXME: those should be moved into slicc file, slicc should
|
||||
# support more of the c++ class inheritance
|
||||
|
||||
if self.isMessage:
|
||||
code('''
|
||||
Message *
|
||||
${{self.c_ident}}*
|
||||
clone() const
|
||||
{
|
||||
checkAllocator();
|
||||
return s_allocator_ptr->allocate(*this);
|
||||
}
|
||||
|
||||
void
|
||||
destroy()
|
||||
{
|
||||
checkAllocator();
|
||||
s_allocator_ptr->deallocate(this);
|
||||
}
|
||||
|
||||
static Allocator<${{self.c_ident}}>* s_allocator_ptr;
|
||||
|
||||
static void
|
||||
checkAllocator()
|
||||
{
|
||||
if (s_allocator_ptr == NULL) {
|
||||
s_allocator_ptr = new Allocator<${{self.c_ident}}>;
|
||||
}
|
||||
return new ${{self.c_ident}}(*this);
|
||||
}
|
||||
''')
|
||||
|
||||
@@ -414,8 +407,6 @@ operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
|
||||
using namespace std;
|
||||
''')
|
||||
|
||||
if self.isMessage:
|
||||
code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
|
||||
code('''
|
||||
/** \\brief Print the state of this object */
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user