*/
#include "mem/ruby/slicc_interface/AbstractController.hh"
+#include "mem/ruby/system/Sequencer.hh"
#include "mem/ruby/system/System.hh"
AbstractController::AbstractController(const Params *p)
- : SimObject(p), Consumer(this)
+ : ClockedObject(p), Consumer(this)
{
m_version = p->version;
+ m_clusterID = p->cluster_id;
+
m_transitions_per_cycle = p->transitions_per_cycle;
m_buffer_size = p->buffer_size;
m_recycle_latency = p->recycle_latency;
m_number_of_TBEs = p->number_of_TBEs;
m_is_blocking = false;
- p->ruby_system->registerAbstractController(this);
+
+ if (m_version == 0) {
+ // Combine the statistics from all controllers
+ // of this particular type.
+ Stats::registerDumpCallback(new StatsCallback(this));
+ }
+}
+
+void
+AbstractController::init()
+{
+ params()->ruby_system->registerAbstractController(this);
+ m_delayHistogram.init(10);
+ uint32_t size = Network::getNumberOfVirtualNetworks();
+ for (uint32_t i = 0; i < size; i++) {
+ m_delayVCHistogram.push_back(new Stats::Histogram());
+ m_delayVCHistogram[i]->init(10);
+ }
+}
+
+void
+AbstractController::resetStats()
+{
+ m_delayHistogram.reset();
+ uint32_t size = Network::getNumberOfVirtualNetworks();
+ for (uint32_t i = 0; i < size; i++) {
+ m_delayVCHistogram[i]->reset();
+ }
+}
+
+void
+AbstractController::regStats()
+{
+ m_fully_busy_cycles
+ .name(name() + ".fully_busy_cycles")
+ .desc("cycles for which number of transistions == max transitions")
+ .flags(Stats::nozero);
+}
+
+void
+AbstractController::profileMsgDelay(uint32_t virtualNetwork, Cycles delay)
+{
+ assert(virtualNetwork < m_delayVCHistogram.size());
+ m_delayHistogram.sample(delay);
+ m_delayVCHistogram[virtualNetwork]->sample(delay);
+}
+
+void
+AbstractController::connectWithPeer(AbstractController *c)
+{
+ getQueuesFromPeer(c);
+ c->getQueuesFromPeer(this);
+}
+
+void
+AbstractController::stallBuffer(MessageBuffer* buf, Address addr)
+{
+ if (m_waiting_buffers.count(addr) == 0) {
+ MsgVecType* msgVec = new MsgVecType;
+ msgVec->resize(m_in_ports, NULL);
+ m_waiting_buffers[addr] = msgVec;
+ }
+ (*(m_waiting_buffers[addr]))[m_cur_in_port] = buf;
+}
+
+void
+AbstractController::wakeUpBuffers(Address addr)
+{
+ if (m_waiting_buffers.count(addr) > 0) {
+ //
+ // Wake up all possible lower rank (i.e. lower priority) buffers that could
+ // be waiting on this message.
+ //
+ for (int in_port_rank = m_cur_in_port - 1;
+ in_port_rank >= 0;
+ in_port_rank--) {
+ if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) {
+ (*(m_waiting_buffers[addr]))[in_port_rank]->reanalyzeMessages(addr);
+ }
+ }
+ delete m_waiting_buffers[addr];
+ m_waiting_buffers.erase(addr);
+ }
+}
+
+void
+AbstractController::wakeUpAllBuffers(Address addr)
+{
+ if (m_waiting_buffers.count(addr) > 0) {
+ //
+ // Wake up all possible lower rank (i.e. lower priority) buffers that could
+ // be waiting on this message.
+ //
+ for (int in_port_rank = m_in_ports - 1;
+ in_port_rank >= 0;
+ in_port_rank--) {
+ if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) {
+ (*(m_waiting_buffers[addr]))[in_port_rank]->reanalyzeMessages(addr);
+ }
+ }
+ delete m_waiting_buffers[addr];
+ m_waiting_buffers.erase(addr);
+ }
+}
+
+void
+AbstractController::wakeUpAllBuffers()
+{
+ //
+ // Wake up all possible buffers that could be waiting on any message.
+ //
+
+ std::vector<MsgVecType*> wokeUpMsgVecs;
+
+ if(m_waiting_buffers.size() > 0) {
+ for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin();
+ buf_iter != m_waiting_buffers.end();
+ ++buf_iter) {
+ for (MsgVecType::iterator vec_iter = buf_iter->second->begin();
+ vec_iter != buf_iter->second->end();
+ ++vec_iter) {
+ if (*vec_iter != NULL) {
+ (*vec_iter)->reanalyzeAllMessages();
+ }
+ }
+ wokeUpMsgVecs.push_back(buf_iter->second);
+ }
+
+ for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin();
+ wb_iter != wokeUpMsgVecs.end();
+ ++wb_iter) {
+ delete (*wb_iter);
+ }
+
+ m_waiting_buffers.clear();
+ }
+}
+
+void
+AbstractController::blockOnQueue(Address addr, MessageBuffer* port)
+{
+ m_is_blocking = true;
+ m_block_map[addr] = port;
+}
+
+void
+AbstractController::unblock(Address addr)
+{
+ m_block_map.erase(addr);
+ if (m_block_map.size() == 0) {
+ m_is_blocking = false;
+ }
}