Permalink
Browse files

Large commit: forked cluster, cluster cache for non-functional modes

ClusterCacheBase has common functionality of CCacheFunctional,Structural
various small updates and fixes
Callback wrappers can specify a (templated) return type
InPortCallback returns result of the callback, not always Ack
  • Loading branch information...
1 parent e8f756b commit 39138476594d2aee5eb071458a8acd5e0857383c @drjohnson drjohnson committed Mar 25, 2012
View
2 rigel-sim/Makefile.am
@@ -74,8 +74,10 @@ common_SOURCES = \
src/cluster/cluster_legacy.cpp \
src/cluster/clusterbase.cpp \
src/cluster/cluster_functional.cpp \
+ src/cluster/cluster_structural.cpp \
src/cluster/cluster_cache_base.cpp \
src/cluster/cluster_cache_functional.cpp \
+ src/cluster/cluster_cache_structural.cpp \
src/core/corebase.cpp \
src/core/core_functional.cpp \
src/core/core_inorder_legacy.cpp \
View
1 rigel-sim/include/cluster.h
@@ -5,5 +5,6 @@
#include "cluster/clusterbase.h"
#include "cluster/cluster_legacy.h"
#include "cluster/cluster_functional.h"
+#include "cluster/cluster_structural.h"
#endif
View
13 rigel-sim/include/cluster/cluster_cache_base.h
@@ -5,7 +5,10 @@
#include "sim.h"
#include "define.h"
-#include "packet/packet.h"
+// forward declarations
+template<class T> class InPortBase;
+template<class T> class OutPortBase;
+class Packet;
namespace rigel {
class ConstructionPayload;
@@ -44,8 +47,16 @@ class ClusterCacheBase : public ComponentBase {
//virtual int sendRequest(PacketPtr ptr) = 0;
//virtual int recvResponse(PacketPtr ptr) = 0;
+ /// REMOVE ME: FIXME TODO HACK -- replace this with proper generic
+ //connections
+ InPortBase<Packet*>* getCoreSideInPort(int p) { return coreside_ins[p]; }
+ OutPortBase<Packet*>* getCoreSideOutPort(int p) { return coreside_outs[p]; }
+
protected:
+ std::vector< InPortBase<Packet*>* > coreside_ins;
+ std::vector< OutPortBase<Packet*>* > coreside_outs;
+
///
rigel::GlobalBackingStoreType *mem_backing_store;
View
39 rigel-sim/include/cluster/cluster_cache_functional.h
@@ -3,19 +3,15 @@
#include "cluster/cluster_cache_base.h"
#include "util/util.h"
-#include <queue>
#include <utility>
+#include "util/fifo.h"
+#include "port/port.h"
-// forward declarations
-template<class T> class InPortBase;
-template<class T> class OutPortBase;
-//class Packet;
-
-namespace rigel {
- class ConstructionPayload;
- class ComponentCount;
-}
+/// namespace rigel {
+/// class ConstructionPayload;
+/// class ComponentCount;
+/// }
class ClusterCacheFunctional : public ClusterCacheBase {
@@ -36,27 +32,28 @@ class ClusterCacheFunctional : public ClusterCacheBase {
void Heartbeat();
- /// REMOVE ME: FIXME TODO HACK -- replace this with proper generic
- //connections
- InPortBase<Packet*>* getCoreSideInPort(int p) { return coreside_ins[p]; }
- OutPortBase<Packet*>* getCoreSideOutPort(int p) { return coreside_outs[p]; }
+// /// REMOVE ME: FIXME TODO HACK -- replace this with proper generic
+// //connections
+// InPortBase<Packet*>* getCoreSideInPort(int p) { return coreside_ins[p]; }
+// OutPortBase<Packet*>* getCoreSideOutPort(int p) { return coreside_outs[p]; }
protected:
std::vector<clustercache::LDLSTC_entry_t> LinkTable;
- std::vector< InPortBase<Packet*>* > coreside_ins;
- std::vector< OutPortBase<Packet*>* > coreside_outs;
+ // std::vector< InPortBase<Packet*>* > coreside_ins;
+ // std::vector< OutPortBase<Packet*>* > coreside_outs;
private: // we don't want these visible to inherited classes
- void doMemoryAccess(PacketPtr p);
- void doLocalAtomic(PacketPtr p);
- void doGlobalAtomic(PacketPtr p);
+ void doMemoryAccess(Packet* p);
+ void doLocalAtomic(Packet* p);
+ void doGlobalAtomic(Packet* p);
- void FunctionalMemoryRequest(Packet* p);
+ port_status_t FunctionalMemoryRequest(Packet* p);
- std::queue< std::pair<uint64_t,Packet*> > outpackets;
+ /// for the functional model, we should use an UNSIZED queue to never run out of space
+ fifo< std::pair<uint64_t,Packet*> > outpackets;
int fixed_latency;
View
65 rigel-sim/include/cluster/cluster_cache_structural.h
@@ -0,0 +1,65 @@
+#ifndef __CLUSTER_CACHE_STRUCTURAL_H__
+#define __CLUSTER_CACHE_STRUCTURAL_H__
+
+#include "cluster/cluster_cache_base.h"
+#include "util/util.h"
+#include <utility>
+#include "util/fifo.h"
+#include "port/port.h"
+
+// forward declarations
+template<class T> class InPortBase;
+template<class T> class OutPortBase;
+class Packet;
+
+namespace rigel {
+ class ConstructionPayload;
+ class ComponentCount;
+}
+
+
+class ClusterCacheStructural : public ClusterCacheBase {
+
+ public:
+
+ /// constructor
+ ClusterCacheStructural(
+ rigel::ConstructionPayload cp,
+ InPortBase<Packet*>* in, ///< unused, the functional cache don't care!
+ OutPortBase<Packet*>* out ///< unused, the functional cache don't care!
+ );
+
+ /// component interface functions
+ int PerCycle();
+ void EndSim();
+ void Dump();
+ void Heartbeat();
+
+
+ /// REMOVE ME: FIXME TODO HACK -- replace this with proper generic
+ //connections
+// InPortBase<Packet*>* getCoreSideInPort(int p) { return coreside_ins[p]; }
+// OutPortBase<Packet*>* getCoreSideOutPort(int p) { return coreside_outs[p]; }
+
+ protected:
+
+ std::vector<clustercache::LDLSTC_entry_t> LinkTable;
+
+// std::vector< InPortBase<Packet*>* > coreside_ins;
+// std::vector< OutPortBase<Packet*>* > coreside_outs;
+
+ private: // we don't want these visible to inherited classes
+
+ void doMemoryAccess(Packet* p);
+ void doLocalAtomic(Packet* p);
+ void doGlobalAtomic(Packet* p);
+
+ port_status_t FunctionalMemoryRequest(Packet* p);
+
+ fifo< std::pair<uint64_t,Packet*> > outpackets;
+
+ int fixed_latency;
+
+};
+
+#endif
View
2 rigel-sim/include/cluster/cluster_functional.h
@@ -26,7 +26,7 @@ class ClusterFunctional : public ClusterBase {
virtual void save_state() const;
virtual void restore_state();
- /// cluster simple only
+ /// this cluster only
/// replace with generic port connections
InPortBase<Packet*>* get_inport() { return from_interconnect; }
View
50 rigel-sim/include/cluster/cluster_structural.h
@@ -0,0 +1,50 @@
+
+#ifndef __CLUSTER_STRUCTURAL_H__
+#define __CLUSTER_STRUCTURAL_H__
+
+#include "sim.h" //For GlobalBackingStoreType
+#include "cluster/clusterbase.h"
+#include "core.h"
+#include "cluster/cluster_cache.h"
+
+class ClusterStructural : public ClusterBase {
+
+ public:
+
+ ClusterStructural(rigel::ConstructionPayload cp);
+
+ ~ClusterStructural();
+
+ /// Component interface
+ void Heartbeat();
+ void Dump();
+ void EndSim();
+ int PerCycle();
+
+ int halted() { return (halted_ == numcores); }
+
+ virtual void save_state() const;
+ virtual void restore_state();
+
+ /// this cluster only
+
+ /// replace with generic port connections
+ InPortBase<Packet*>* get_inport() { return from_interconnect; }
+ OutPortBase<Packet*>* get_outport() { return to_interconnect; }
+
+ private:
+
+ CoreFunctional** cores; /// array of cores
+
+ ClusterCacheStructural *ccache; /// cluster cache object
+
+ int numcores; /// cores in this cluster
+
+ int halted_; /// halted cores (threads?)
+
+ OutPortBase<Packet*>* to_interconnect; ///< outport to the interconnect
+ InPortBase<Packet*>* from_interconnect; ///< inport from the interconnect
+
+};
+
+#endif
View
10 rigel-sim/include/core/core_functional.h
@@ -30,8 +30,8 @@ class CoreFunctional : public CoreBase {
public:
/// constructor
- CoreFunctional(rigel::ConstructionPayload cp,
- ClusterCacheFunctional* ccache);
+ CoreFunctional(rigel::ConstructionPayload cp);
+ //ClusterCacheFunctional* ccache);
/// destructor
~CoreFunctional();
@@ -71,9 +71,11 @@ class CoreFunctional : public CoreBase {
private:
+ int stall;
+
// private methods
void doMem(PipePacket* instr);
- void sendMemoryRequest(Packet* p);
+ void sendMemoryRequest(PipePacket* p);
void checkMemoryRequest(PipePacket* p);
void doSimSpecial(PipePacket* instr);
@@ -106,7 +108,7 @@ class CoreFunctional : public CoreBase {
int current_tid; // local thread id
- ClusterCacheFunctional* ccache;
+ //ClusterCacheFunctional* ccache;
// TODO FIXME: this should be a core base class member...
Syscall* syscall_handler;
View
12 rigel-sim/include/instr/pipe_packet.h
@@ -36,6 +36,7 @@ class PipePacket { // : public InstrBase { // maybe later...
) :
_valid(true),
_completed(false),
+ _request_pending(false),
_pc(pc),
raw_instr_bits(raw),
_tid(tid),
@@ -110,18 +111,20 @@ class PipePacket { // : public InstrBase { // maybe later...
void pretty_print(FILE * stream = stdout) {
dis_print();
- fprintf(stream,"\n");
+ //fprintf(stream,"\n");
}
/// dump useful internal state
void Dump() {
pretty_print();
_sdInfo.Dump();
+ printf("valid:%d completed:%d request_pending:%d\n", _valid, _completed, _request_pending);
// print regvals
printf("regs: ");
for(int i=0;i<NUM_ISA_OPERAND_REGS;i++) {
printf("%s:%08x ",isa_reg_names[i],regvals[i].i32()); /// for storing temporary register values
- } printf("\n");
+ }
+ printf("\n");
};
disassemble_info dis_info;
@@ -231,6 +234,9 @@ class PipePacket { // : public InstrBase { // maybe later...
bool isCompleted() { return _completed; }
void setCompleted() { _completed = true; }
+ bool requestPending() { return _request_pending; }
+ void setRequestPending() { _request_pending = true; }
+
Packet* memRequest() { return _mem_request; }
void memRequest(Packet* p) { _mem_request = p; }
@@ -255,6 +261,8 @@ class PipePacket { // : public InstrBase { // maybe later...
/// basic attributes
bool _valid;
bool _completed;
+ bool _request_pending;
+
uint32_t _pc; /// program counter associated with this instruction
uint32_t raw_instr_bits; /// for internal class use only
View
2 rigel-sim/include/interconnect/crossbar.h
@@ -29,7 +29,7 @@ class CrossBar : public ComponentBase {
void Dump() {};
void Heartbeat() {};
void EndSim() {};
- int PerCycle() {};
+ int PerCycle() { return 0;};
InPortBase<Packet*>* get_inport(int p) { return inports[p]; }
OutPortBase<Packet*>* get_outport(int p) { return outports[p]; }
View
33 rigel-sim/include/port/port.h
@@ -32,7 +32,7 @@ static std::string PortName( std::string parent, int id, std::string suffix, int
// forward declarations
template <class T> class OutPortBase;
template <class T> class InPortBase;
-template <class P> class CallbackWrapper;
+template <class, class> class CallbackWrapper;
typedef enum {
@@ -47,9 +47,9 @@ class InPortBase : public PortBase {
public:
InPortBase(std::string name) :
- _name(name),
- valid(false),
- ready(true)
+ _valid(false),
+ _ready(true),
+ _name(name)
{
PortManager<T>::registerInPort(this);
}
@@ -58,10 +58,10 @@ class InPortBase : public PortBase {
DPRINT(DEBUG_PORT,"%s\n", __PRETTY_FUNCTION__);
//msg->Dump();
// save msg
- if (ready) {
+ if (_ready) {
data = msg;
- valid = true;
- ready = false;
+ _valid = true;
+ _ready = false;
DPRINT(DEBUG_PORT,"%s ACK\n", __PRETTY_FUNCTION__);
return ACK;
} else {
@@ -71,9 +71,9 @@ class InPortBase : public PortBase {
};
virtual T read() {
- if (valid) {
- valid = false;
- ready = true;
+ if (_valid) {
+ _valid = false;
+ _ready = true;
return data;
} else {
return NULL; // FIXME this is evil...and stupid
@@ -89,10 +89,12 @@ class InPortBase : public PortBase {
friend class PortManager<T>;
+ bool ready() { return _ready; }
+
private:
+ bool _valid; /// data is valid
+ bool _ready; /// ready to accept a message
T data;
- bool valid; /// data is valid
- bool ready; /// ready to accept a message
std::string _name; ///< port name
};
@@ -105,20 +107,19 @@ class InPortCallback : public InPortBase<T> {
public:
InPortCallback( std::string name,
- CallbackWrapper<T>* handler
+ CallbackWrapper<T,port_status_t>* handler
) : InPortBase<T>(name),
handler(handler)
{ }
virtual port_status_t recvMsg(T msg) {
DPRINT(DEBUG_PORT,"%s\n", __PRETTY_FUNCTION__);
- (*handler)(msg);
- return ACK; // assume handler always works, since it doesn't return anything
+ return (*handler)(msg);
}
private:
- CallbackWrapper<T> *handler;
+ CallbackWrapper<T,port_status_t> *handler;
};
View
1 rigel-sim/include/sim.h
@@ -99,6 +99,7 @@ namespace rigel {
class ClusterBase;
class ClusterLegacy;
class ClusterFunctional;
+class ClusterStructural;
// Memory Model Classes
class MemoryModelSimple;
View
12 rigel-sim/include/util/callback.h
@@ -1,25 +1,27 @@
#ifndef __CALLBACK_H__
#define __CALLBACK_H__
-template <class P>
+template <class Payload, class ReturnType>
class CallbackWrapper {
public:
- virtual void operator() (P p) = 0;
+ virtual ReturnType operator() (Payload p) = 0;
CallbackWrapper() { };
private:
};
+// for wrapping a member function
template < class Obj,
class Payload,
- void (Obj::*Func)(Payload)
+ class ReturnType,
+ ReturnType (Obj::*Func)(Payload)
>
-class MemberCallbackWrapper : public CallbackWrapper<Payload> {
+class MemberCallbackWrapper : public CallbackWrapper<Payload,ReturnType> {
public:
MemberCallbackWrapper(Obj *o)
: object(o) { }
- void operator() (Payload p) {
+ ReturnType operator() (Payload p) {
(object->*Func)(p);
}
View
2 rigel-sim/src/cluster/cluster_cache_base.cpp
@@ -9,6 +9,8 @@ ClusterCacheBase::ClusterCacheBase(rigel::ConstructionPayload cp)
: ComponentBase(cp.parent,
cp.change_name("ClusterCacheBase").component_name.c_str(),
*(cp.change_component_count(ClusterCacheBaseCount).component_count)),
+ coreside_ins(rigel::CORES_PER_CLUSTER), // FIXME: make this non-const
+ coreside_outs(rigel::CORES_PER_CLUSTER), // FIXME: make this non-const
mem_backing_store(cp.backing_store)
{
}
View
53 rigel-sim/src/cluster/cluster_cache_functional.cpp
@@ -11,7 +11,7 @@
#define DB_CC 0
-#define CF_FIXED_LATENCY 0
+#define CF_FIXED_LATENCY 20
/// constructor
ClusterCacheFunctional::ClusterCacheFunctional(
@@ -21,16 +21,20 @@ ClusterCacheFunctional::ClusterCacheFunctional(
) :
ClusterCacheBase(cp.change_name("ClusterCacheFunctional")),
LinkTable(rigel::THREADS_PER_CLUSTER), // TODO FIXME dynamic
- coreside_ins(rigel::CORES_PER_CLUSTER), // FIXME: make this non-const
- coreside_outs(rigel::CORES_PER_CLUSTER), // FIXME: make this non-const
- outpackets(),
+ //coreside_ins(rigel::CORES_PER_CLUSTER), // FIXME: make this non-const
+ //coreside_outs(rigel::CORES_PER_CLUSTER), // FIXME: make this non-const
+ outpackets(99), // make this really big functional, TODO make it unsized
fixed_latency(CF_FIXED_LATENCY)
{
+ // TODO: make this an internal class of the port, so we don't have to specify port_status_t ?
+ CallbackWrapper<Packet*,port_status_t>* mcb
+ = new MemberCallbackWrapper<
+ ClusterCacheFunctional,
+ Packet*,
+ port_status_t,
+ &ClusterCacheFunctional::FunctionalMemoryRequest>(this);
- CallbackWrapper<Packet*>* mcb
- = new MemberCallbackWrapper<ClusterCacheFunctional,Packet*,
- &ClusterCacheFunctional::FunctionalMemoryRequest>(this);
for (int i = 0; i < coreside_ins.size(); i++) {
std::string n = PortName( name(), id(), "coreside_in", i );
coreside_ins[i] = new InPortCallback<Packet*>(n, mcb);
@@ -48,13 +52,20 @@ ClusterCacheFunctional::ClusterCacheFunctional(
int
ClusterCacheFunctional::PerCycle() {
- if (!outpackets.empty()) {
- if (outpackets.front().first <= rigel::CURR_CYCLE) {
- Packet* p;
- p = outpackets.front().second;
- coreside_outs[p->local_coreid()]->sendMsg(p);
- outpackets.pop();
- }
+ // return all ready responses
+ // functional sim does not bandwith limit responses right now (we could if we wanted to)
+ // this assumes packets in front are ready first, only true for silly fixed latency model
+ // otherwise, ready responses after waiting responses will be blocked here
+
+ while (!outpackets.empty() && outpackets.front().first <= rigel::CURR_CYCLE) {
+ Packet* p;
+ p = outpackets.front().second;
+
+ doMemoryAccess(p);
+ assert(p!=0);
+
+ coreside_outs[p->local_coreid()]->sendMsg(p);
+ outpackets.pop();
}
return 0;
@@ -75,16 +86,20 @@ ClusterCacheFunctional::Heartbeat() {};
/// CCFunctional specific
-void
+port_status_t
ClusterCacheFunctional::FunctionalMemoryRequest(Packet* p) {
- doMemoryAccess(p);
- assert(p!=0);
-
if (fixed_latency == 0) { // send immediately
+ doMemoryAccess(p);
+ assert(p!=0);
coreside_outs[p->local_coreid()]->sendMsg(p);
+ return ACK;
} else {
- outpackets.push( std::make_pair(rigel::CURR_CYCLE + fixed_latency, p) );
+ if ( outpackets.push( std::make_pair(rigel::CURR_CYCLE + fixed_latency, p) ) ) {
+ return ACK;
+ } else {
+ throw ExitSim("unhandled fifo overrun in cluster_cache_functional!");
+ }
}
}
View
240 rigel-sim/src/cluster/cluster_cache_structural.cpp
@@ -0,0 +1,240 @@
+#include "cluster/cluster_cache_structural.h"
+#include "sim/component_count.h"
+#include "util/construction_payload.h"
+#include "memory/backing_store.h"
+#include "port/port.h"
+#include "util/callback.h"
+
+#include "isa/rigel_isa.h"
+
+#include <sstream>
+
+#define DB_CC 0
+
+#define CF_FIXED_LATENCY 2
+
+/// constructor
+ClusterCacheStructural::ClusterCacheStructural(
+ rigel::ConstructionPayload cp,
+ InPortBase<Packet*>* in,
+ OutPortBase<Packet*>* out
+) :
+ ClusterCacheBase(cp.change_name("ClusterCacheStructural")),
+ LinkTable(rigel::THREADS_PER_CLUSTER), // TODO FIXME dynamic
+// coreside_ins(rigel::CORES_PER_CLUSTER), // FIXME: make this non-const
+// coreside_outs(rigel::CORES_PER_CLUSTER), // FIXME: make this non-const
+ outpackets(1),
+ fixed_latency(CF_FIXED_LATENCY)
+{
+
+ // TODO: make this an internal class of the port, so we don't have to specify port_status_t ?
+ CallbackWrapper<Packet*,port_status_t>* mcb
+ = new MemberCallbackWrapper<
+ ClusterCacheStructural,
+ Packet*,
+ port_status_t,
+ &ClusterCacheStructural::FunctionalMemoryRequest>(this);
+
+ for (int i = 0; i < coreside_ins.size(); i++) {
+ std::string n = PortName( name(), id(), "coreside_in", i );
+ coreside_ins[i] = new InPortCallback<Packet*>(n, mcb);
+ }
+
+ for (int i = 0; i < coreside_outs.size(); i++) {
+ std::string n = PortName( name(), id(), "coreside_out", i );
+ coreside_outs[i] = new OutPortBase<Packet*>(n);
+ }
+
+}
+
+/// component interface
+
+int
+ClusterCacheStructural::PerCycle() {
+
+ if (!outpackets.empty()) {
+ if (outpackets.front().first <= rigel::CURR_CYCLE) {
+ Packet* p;
+ p = outpackets.front().second;
+
+ doMemoryAccess(p);
+ assert(p!=0);
+
+ coreside_outs[p->local_coreid()]->sendMsg(p);
+ outpackets.pop();
+ }
+ }
+
+ return 0;
+};
+
+void
+ClusterCacheStructural::EndSim() {
+
+};
+
+void
+ClusterCacheStructural::Dump() {
+
+};
+
+void
+ClusterCacheStructural::Heartbeat() {};
+
+
+/// CCFunctional specific
+port_status_t
+ClusterCacheStructural::FunctionalMemoryRequest(Packet* p) {
+
+ if (fixed_latency == 0) { // send immediately
+ doMemoryAccess(p);
+ assert(p!=0);
+ coreside_outs[p->local_coreid()]->sendMsg(p);
+ return ACK;
+ } else {
+ if ( outpackets.push( std::make_pair(rigel::CURR_CYCLE + fixed_latency, p) ) ) {
+ return ACK;
+ } else {
+ return NACK;
+ throw ExitSim("unhandled fifo overrun!");
+ }
+ }
+}
+
+void
+ClusterCacheStructural::doMemoryAccess(PacketPtr p) {
+
+ //p->Dump();
+
+ // FIXME: TODO: pre-decode the message type (Local vs. Global, atomic)
+ // to avoid these switches all over...we already need one for implementing the
+ // operation, don't use a switch to select the handler func
+ switch(p->msgType()) {
+
+ // loads
+ case IC_MSG_READ_REQ:
+ case IC_MSG_GLOBAL_READ_REQ: {
+ uint32_t data = mem_backing_store->read_data_word(p->addr());
+ p->data(data);
+ p->setCompleted();
+ break;
+ }
+
+ // stores
+ case IC_MSG_WRITE_REQ:
+ case IC_MSG_GLOBAL_WRITE_REQ:
+ case IC_MSG_BCAST_UPDATE_REQ:
+ mem_backing_store->write_word(p->addr(), p->data());
+ p->setCompleted();
+ break;
+
+ // atomics
+ case IC_MSG_LDL_REQ:
+ case IC_MSG_STC_REQ:
+ doLocalAtomic(p);
+ break;
+
+ case IC_MSG_ATOMDEC_REQ:
+ case IC_MSG_ATOMINC_REQ:
+ case IC_MSG_ATOMADDU_REQ:
+ case IC_MSG_ATOMCAS_REQ:
+ case IC_MSG_ATOMXCHG_REQ:
+ case IC_MSG_ATOMMIN_REQ:
+ case IC_MSG_ATOMMAX_REQ:
+ case IC_MSG_ATOMAND_REQ:
+ case IC_MSG_ATOMOR_REQ:
+ case IC_MSG_ATOMXOR_REQ:
+ doGlobalAtomic(p);
+ break;
+
+ default:
+ p->Dump();
+ throw ExitSim("unhandled msgType()!");
+ }
+
+}
+
+/// doGlobalAtomic
+/// call a generic handler for Global Atomic operations
+/// side effect: updates p
+void
+ClusterCacheStructural::doGlobalAtomic(PacketPtr p) {
+ uint32_t result = RigelISA::execGlobalAtomic(p, mem_backing_store);
+ // convert the request to a reply
+ p->msgType( rigel::icmsg_convert(p->msgType()) );
+ p->data( result );
+ p->setCompleted();
+}
+
+/// doLocalAtomics
+/// local atomics (LDL/STC) require local state where they are completed
+/// side effect: updates p
+void
+ClusterCacheStructural::doLocalAtomic(PacketPtr p) {
+ int tid; // cluster-level thread ID
+ tid = p->cluster_tid();
+ if(tid >= LinkTable.size() ) {
+ printf("invalid tid size %d in %s\n", tid, __func__);
+ throw ExitSim("invalid tid size");
+ }
+ assert(tid < LinkTable.size());
+ switch(p->msgType()) {
+
+ // Load Linked
+ case IC_MSG_LDL_REQ: {
+ LinkTable[tid].valid = true;
+ LinkTable[tid].addr = p->addr();
+ LinkTable[tid].size = sizeof(uint32_t); // TODO FIXME: non-32-bit-word sizes
+ uint32_t readval = mem_backing_store->read_data_word(p->addr());
+ DPRINT(DB_CC,"LDL: tid %d read %08x at %08x\n",tid,readval,p->addr());
+ p->data(readval);
+ p->msgType(IC_MSG_LDL_REPLY);
+ break;
+ }
+
+ // Store Conditional
+ case IC_MSG_STC_REQ:
+
+ // STC succeeds if we have a valid addr match
+ // FIXME: check the addr size overlap as below
+ if (LinkTable[tid].valid && LinkTable[tid].addr == p->addr()) {
+
+ // do the store
+ mem_backing_store->write_word(p->addr(),p->data());
+ DPRINT(DB_CC,"STC succeeded [%d]: write %08x to %08x\n",tid,p->data(),p->addr());
+
+ // invalidate other outstanding LDL requests to same address
+ for (unsigned i = 0; i < LinkTable.size(); ++i) {
+
+ //printf("LinkTable[%d]: %08x v[%d]\n",i,LinkTable[i].addr,LinkTable[i].valid);
+
+ // Skip the requestor
+ if (tid == i) continue;
+
+ if (LinkTable[i].valid) {
+ uint32_t size_mask = ~(LinkTable[i].size - 1);
+ if ((p->addr() & size_mask) == (LinkTable[i].addr & size_mask)) {
+ LinkTable[i].valid = false;
+ }
+ }
+
+ }
+ p->data(1);
+ p->msgType(IC_MSG_STC_REPLY_ACK);
+ }
+ // STC fails otherwise
+ else {
+ //printf("STC failed [%d] at %08x\n",tid, p->addr());
+ for (unsigned i = 0; i < LinkTable.size(); ++i) {
+ //printf("LinkTable: %08x v[%d]\n",LinkTable[i].addr,LinkTable[i].valid);
+ }
+ p->data(0);
+ p->msgType(IC_MSG_STC_REPLY_NACK);
+ }
+ break;
+ default:
+ throw ExitSim("invalid message type in packet!");
+ }
+ p->setCompleted(); // access handled, return to core
+ return;
+};
View
10 rigel-sim/src/cluster/cluster_functional.cpp
@@ -35,7 +35,7 @@ ClusterFunctional::ClusterFunctional(
for (int i = 0; i < numcores; ++i) {
cp.core_state = cp.cluster_state->add_cores();
cp.component_index = i;
- cores[i] = new CoreFunctional(cp,ccache);
+ cores[i] = new CoreFunctional(cp);
ccache->getCoreSideInPort(i)->attach( cores[i]->getOutPort() );
cores[i]->getInPort()->attach( ccache->getCoreSideOutPort(i) );
}
@@ -73,9 +73,13 @@ ClusterFunctional::PerCycle() {
ccache->PerCycle();
+ // HACK: clock the cores in rotating priority to avoid starvation (should not be any)
+ // OK for FUNCTIONAL simulation, we are not limiting bandwidth or modelling contention
+ int idx = rigel::CURR_CYCLE % numcores;
int halted_cores = 0;
- for (int i=0; i < numcores; i++) {
- halted_cores += cores[i]->PerCycle();
+ for (int offset = 0; offset < numcores; offset++) {
+ halted_cores += cores[idx]->PerCycle();
+ idx = (idx + 1) % numcores;
}
halted_ = halted_cores;
View
116 rigel-sim/src/cluster/cluster_structural.cpp
@@ -0,0 +1,116 @@
+
+#include "cluster/cluster_structural.h"
+#include "cluster/cluster_cache_structural.h"
+#include "sim.h"
+#include "util/construction_payload.h"
+
+/// constructor
+ClusterStructural::ClusterStructural(
+ rigel::ConstructionPayload cp
+) :
+ ClusterBase(cp.change_name("ClusterStructural")),
+ numcores(rigel::CORES_PER_CLUSTER), // TODO: set dynamic
+ halted_(0),
+ to_interconnect(),
+ from_interconnect()
+{
+
+ cp.parent = this;
+ cp.component_name.clear();
+
+ // connect ccache to cluster ports
+ // this just assigns the ccache ports to be the cluster's ports
+ // we like this because the cluster is contained, but the ccache is a separate object
+ // we could instead try to use a DUMMY port object that basically does this assignment via attach
+ from_interconnect = new InPortBase<Packet*>( PortName(name(), id(), "in") );
+ to_interconnect = new OutPortBase<Packet*>( PortName(name(), id(), "out") );
+
+ // the ccache will actually be responsible for reading, writing to the cluster's ports
+ ccache = new ClusterCacheStructural(cp, from_interconnect, to_interconnect);
+
+ cores = new CoreFunctional*[numcores];
+
+ // make port connections:
+ // TODO: do this somewhere more generic
+ for (int i = 0; i < numcores; ++i) {
+ cp.core_state = cp.cluster_state->add_cores();
+ cp.component_index = i;
+ cores[i] = new CoreFunctional(cp);
+ ccache->getCoreSideInPort(i)->attach( cores[i]->getOutPort() );
+ cores[i]->getInPort()->attach( ccache->getCoreSideOutPort(i) );
+ }
+
+};
+
+/// destructor
+ClusterStructural::~ClusterStructural() {
+ if (cores) {
+ for (int i=0; i<numcores; i++) {
+ delete cores[i];
+ }
+ delete cores;
+ }
+}
+
+void
+ClusterStructural::Heartbeat() {
+
+ // p: core
+ for (int p = 0; p < rigel::CORES_PER_CLUSTER; p++) {
+ for (int t = 0; t < rigel::THREADS_PER_CORE; t++) {
+ fprintf(stderr, "cycle %"PRIu64": core %d, thread %d: 0x%08x\n", rigel::CURR_CYCLE, p, t, cores[p]->pc(t));
+ } // end thread
+ } // end core
+}
+
+/// PerCycle
+int
+ClusterStructural::PerCycle() {
+
+ if (halted()) {
+ return halted();
+ }
+
+ ccache->PerCycle();
+
+ // HACK: clock the cores in rotating priority to avoid starvation
+ // ideally, this should be done via multi-cycle arbitration and handled transparently
+ // on the other side of the port interface
+ int idx = rand() % numcores;
+ int halted_cores = 0;
+ for (int offset = 0; offset < numcores; offset++) {
+ halted_cores += cores[idx]->PerCycle();
+ idx = (idx + 1) % numcores;
+ }
+ halted_ = halted_cores;
+
+ if (halted()) {
+ printf("all %d cores halted in cluster %d\n", numcores, id());
+ }
+
+ return halted();
+};
+
+void
+ClusterStructural::Dump() {
+ assert( 0 && "unimplemented!");
+};
+
+void
+ClusterStructural::EndSim() {
+ profiler->end_sim();
+ profiler->accumulate_stats();
+ //assert( 0 && "unimplemented!");
+};
+
+void ClusterStructural::save_state() const {
+ for(int i = 0; i < rigel::CORES_PER_CLUSTER; i++) {
+ cores[i]->save_state();
+ }
+}
+
+void ClusterStructural::restore_state() {
+ for(int i = 0; i < rigel::CORES_PER_CLUSTER; i++) {
+ cores[i]->restore_state();
+ }
+}
View
44 rigel-sim/src/core/core_functional.cpp
@@ -38,21 +38,20 @@
/// constructor
///////////////////////////////////////////////////////////////////////////////
CoreFunctional::CoreFunctional(
- rigel::ConstructionPayload cp,
- ClusterCacheFunctional *ccache
+ rigel::ConstructionPayload cp
+ //ClusterCacheFunctional *ccache
) :
CoreBase(cp.change_name("CoreFunctional")),
width(CF_WIDTH),
numthreads(rigel::THREADS_PER_CORE),
current_tid(0),
- ccache(ccache),
+ //ccache(ccache),
syscall_handler(cp.syscall),
thread_state(numthreads)
{
cp.parent = this;
cp.component_name.clear();
-
std::string pname_out = PortName(name(), id(), "cache_out");
std::string pname_in = PortName(name(), id(), "cache_in");
to_ccache = new OutPortBase<Packet*>(pname_out);
@@ -139,7 +138,13 @@ CoreFunctional::PerCycle() {
memory(ts->instr);
} else { // check on the existing instruction
// handle memory stall
- checkMemoryRequest(ts->instr);
+ //ts->instr->Dump();
+ if (!ts->instr->requestPending()) {
+ sendMemoryRequest(ts->instr);
+ }
+ if (ts->instr->requestPending()) {
+ checkMemoryRequest(ts->instr);
+ }
}
// writeback
@@ -160,7 +165,7 @@ CoreFunctional::PerCycle() {
}
} else {
- // no thread available this cycle, stalled
+ throw ExitSim("we don't expect this at present (no thread selectable)"); // no thread available this cycle, stalled
}
if (DB_CF) { ts->rf.Dump(); }
@@ -456,19 +461,16 @@ CoreFunctional::doMem(PipePacket* instr) {
assert(0 && "unknown or unimplemented ATOMICOP");
break;
}
- sendMemoryRequest(p);
// store value
}
else if (instr->isStore()) {
DPRINT(DB_CF,"%s: isMem isStore\n", __func__);
-
switch (instr->type()) {
case I_STW:
case I_GSTW:
case I_BCAST_UPDATE: {
uint32_t data = instr->regval(DREG).u32();
p->initCorePacket(addr ,data, id(), GTID(instr->tid()));
- sendMemoryRequest(p); // no result for stores
break;
}
default:
@@ -483,7 +485,6 @@ CoreFunctional::doMem(PipePacket* instr) {
case I_LDW:
case I_GLDW: {
p->initCorePacket(addr, 0, id(), GTID(instr->tid()));
- sendMemoryRequest(p);
break;
}
default:
@@ -500,40 +501,55 @@ CoreFunctional::doMem(PipePacket* instr) {
// do nothing for these in functional mode, for now, with no caches
instr->setCompleted();
DRIGEL( printf("ignoring CACHECONTROL instruction for now...NOP\n"); )
+ return; // since we don't actually sent this request
break;
default:
throw ExitSim("unhandled CacheControl operation?");
}
} else if (instr->isPrefetch()) {
instr->setCompleted();
DRIGEL( printf("ignoring PREFETCH instruction for now...NOP\n"); )
+ return; // since we don't actually sent this request
} else {
instr->Dump();
throw ExitSim("unknown memory operation!");
}
instr->memRequest(p); // save pointer to request
+
+ // send packetized memory request
+ sendMemoryRequest(instr);
+ // no result for stores
+
if (instr->isCompleted()) {
return;
} else {
- checkMemoryRequest(instr);
+ if (instr->requestPending()) {
+ checkMemoryRequest(instr);
+ } else {
+ return;
+ }
}
}
// sendMemoryRequest
// actually poke the ports
void
-CoreFunctional::sendMemoryRequest(Packet* p) {
+CoreFunctional::sendMemoryRequest(PipePacket* instr) {
port_status_t status;
+ Packet* p = instr->memRequest();
+
status = to_ccache->sendMsg(p);
if (status == ACK) { // port accepted message
-
+ instr->setRequestPending();
} else {
- throw ExitSim("unhandled path sendMemoryRequest()");
+ DPRINT(false, "NACK! c%d t%d\n", id(),instr->tid());
+ return; // retry to send later
+ //throw ExitSim("unhandled path sendMemoryRequest()");
}
}
View
4 rigel-sim/src/tile/tile_new.cpp
@@ -38,8 +38,8 @@ TileNew::TileNew(
cp.component_index = numclusters * id() + i; // remove this, cluster ID assigned via ComponentCounter
clusters[i] = new rigel::ClusterType(cp);
// connect to tree network
- interconnect->get_inport(i)->attach( clusters[i]->get_outport() );
- clusters[i]->get_inport()->attach( interconnect->get_outport(i) );
+ //interconnect->get_inport(i)->attach( clusters[i]->get_outport() );
+ //clusters[i]->get_inport()->attach( interconnect->get_outport(i) );
}
// contruct ports with Clusters

0 comments on commit 3913847

Please sign in to comment.