49#include "debug/RubyQueue.hh"
57using stl_helpers::operator<<;
60 :
SimObject(
p), m_stall_map_size(0), m_max_size(
p.buffer_size),
61 m_max_dequeue_rate(
p.max_dequeue_rate), m_dequeues_this_cy(0),
62 m_time_last_time_size_checked(0),
63 m_time_last_time_enqueue(0), m_time_last_time_pop(0),
64 m_last_arrival_time(0), m_last_message_strict_fifo_bypassed(false),
65 m_strict_fifo(
p.ordered),
66 m_randomization(
p.randomization),
67 m_allow_zero_latency(
p.allow_zero_latency),
68 m_routing_priority(
p.routing_priority),
69 ADD_STAT(m_not_avail_count, statistics::units::Count::get(),
70 "Number of times this buffer did not have N slots available"),
71 ADD_STAT(m_msg_count, statistics::units::Count::get(),
72 "Number of messages passed the buffer"),
73 ADD_STAT(m_buf_msgs, statistics::units::Rate<
74 statistics::units::Count, statistics::units::
Tick>::get(),
75 "Average number of messages in buffer"),
77 "Total number of ticks messages were stalled in this buffer"),
78 ADD_STAT(m_stall_count, statistics::units::Count::get(),
79 "Number of times messages were stalled"),
80 ADD_STAT(m_avg_stall_time, statistics::units::Rate<
81 statistics::units::
Tick, statistics::units::Count>::get(),
82 "Average stall ticks per message"),
83 ADD_STAT(m_occupancy, statistics::units::Rate<
84 statistics::units::Ratio, statistics::units::
Tick>::get(),
85 "Average occupancy of buffer capacity")
159 unsigned int current_size = 0;
160 unsigned int current_stall_size = 0;
181 if (current_size + current_stall_size +
n <=
m_max_size) {
184 DPRINTF(RubyQueue,
"n: %d, current_size: %d, heap size: %d, "
186 n, current_size + current_stall_size,
196 DPRINTF(RubyQueue,
"Peeking at head of queue.\n");
200 DPRINTF(RubyQueue,
"Message: %s\n", (*msg_ptr));
210 time += rng->random(0, 3);
211 if (rng->random(0, 7) == 0) {
212 time += 100 + rng->random(1, 15);
219 bool ruby_is_random,
bool ruby_warmup,
220 bool bypassStrictFIFO)
234 "Delta equals zero and allow_zero_latency is false during enqueue");
235 Tick arrival_time = 0;
243 arrival_time = current_time + delta;
257 assert(arrival_time >= current_time);
261 panic(
"FIFO ordering violated: %s name: %s current time: %d "
262 "delta: %d arrival_time: %d last arrival_time: %d\n",
263 *
this,
name(), current_time, delta, arrival_time,
276 Message* msg_ptr = message.get();
277 assert(msg_ptr != NULL);
280 "ensure we aren't dequeued early");
295 DPRINTF(RubyQueue,
"Enqueue arrival_time: %lld, Message: %s\n",
296 arrival_time, *(message.get()));
307 DPRINTF(RubyQueue,
"Popping\n");
314 message->updateDelayedTicks(current_time);
315 Tick delay = message->getDelayedTicks();
329 if (decrement_messages) {
375 DPRINTF(RubyQueue,
"Recycling.\n");
380 Tick future_time = current_time + recycle_latency;
381 node->setLastEnqueueTime(future_time);
391 while (!
lt.empty()) {
393 assert(
m->getLastEnqueueTime() <= schdTick);
397 std::greater<MsgPtr>());
401 DPRINTF(RubyQueue,
"Requeue arrival_time: %lld, Message: %s\n",
402 schdTick, *(
m.get()));
411 DPRINTF(RubyQueue,
"ReanalyzeMessages %#x\n",
addr);
429 DPRINTF(RubyQueue,
"ReanalyzeAllMessages\n");
476 DPRINTF(RubyQueue,
"Deferring enqueueing message: %s, Address %#x\n",
477 *(message.get()),
addr);
483 bool ruby_is_random,
bool ruby_warmup)
487 assert(msg_vec.size() > 0);
491 enqueue(
m, curTime, delay, ruby_is_random, ruby_warmup);
513 std::sort_heap(copy.begin(), copy.end(), std::greater<MsgPtr>());
525 (
m_prio_heap.front()->getLastEnqueueTime() <= current_time);
526 if (!can_dequeue && is_ready) {
530 return can_dequeue && is_ready;
545 DPRINTF(RubyQueue,
"functional %s for %#x\n",
546 is_read ?
"read" :
"write", pkt->
getAddr());
548 uint32_t num_functional_accesses = 0;
557 num_functional_accesses++;
559 num_functional_accesses++;
569 it != (map_iter->second).end(); ++it) {
575 num_functional_accesses++;
577 num_functional_accesses++;
581 return num_functional_accesses;
Cycles is a wrapper class for representing cycle counts, i.e.
virtual std::string name() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
std::shared_ptr< Random > RandomPtr
static RandomPtr genRandom()
Abstract superclass for simulation objects.
void scheduleEventAbsolute(Tick timeAbs)
void scheduleEvent(Cycles timeDelta)
virtual void storeEventInfo(int info)
statistics::Scalar m_stall_count
bool isDeferredMsgMapEmpty(Addr addr) const
void recycle(Tick current_time, Tick recycle_latency)
MessageBuffer(const Params &p)
bool areNSlotsAvailable(unsigned int n, Tick curTime)
bool isReady(Tick current_time) const
Tick m_time_last_time_enqueue
const Message * peek() const
Function for extracting the message at the head of the message queue.
const bool m_allow_zero_latency
unsigned int m_size_last_time_size_checked
void unregisterDequeueCallback()
bool m_last_message_strict_fifo_bypassed
const unsigned int m_max_dequeue_rate
When != 0, isReady returns false once m_max_dequeue_rate messages have been dequeued in the same cycl...
MessageBufferParams Params
void enqueueDeferredMessages(Addr addr, Tick curTime, Tick delay, bool ruby_is_random, bool ruby_warmup)
const unsigned int m_max_size
The maximum capacity.
void reanalyzeAllMessages(Tick current_time)
unsigned int m_stalled_at_cycle_start
unsigned int m_msgs_this_cycle
statistics::Formula m_avg_stall_time
Consumer * m_consumer
Consumer to signal a wakeup(), can be NULL.
Tick dequeue(Tick current_time, bool decrement_messages=true)
Updates the delay cycles of the message at the head of the queue, removes it from the queue and retur...
statistics::Average m_buf_msgs
statistics::Scalar m_stall_time
bool hasStalledMsg(Addr addr) const
std::vector< MsgPtr > m_prio_heap
Tick m_time_last_time_pop
void deferEnqueueingMessage(Addr addr, MsgPtr message)
void enqueue(MsgPtr message, Tick curTime, Tick delta, bool ruby_is_random, bool ruby_warmup, bool bypassStrictFIFO=false)
void registerDequeueCallback(std::function< void()> callback)
StallMsgMapType m_stall_msg_map
A map from line addresses to lists of stalled messages for that line.
Tick m_time_last_time_size_checked
void stallMessage(Addr addr, Tick current_time)
statistics::Scalar m_msg_count
unsigned int m_size_at_cycle_start
statistics::Formula m_occupancy
unsigned int m_dequeues_this_cy
void print(std::ostream &out) const
void reanalyzeMessages(Addr addr, Tick current_time)
const MessageRandomization m_randomization
void reanalyzeList(std::list< MsgPtr > &, Tick)
unsigned int getSize(Tick curTime)
int m_stall_map_size
Current size of the stall map.
statistics::Scalar m_not_avail_count
std::function< void()> m_dequeue_callback
uint32_t functionalAccess(Packet *pkt, bool is_read, WriteMask *mask)
DeferredMsgMapType m_deferred_msg_map
virtual bool functionalRead(Packet *pkt)
The two functions below are used for reading / writing the message functionally.
Tick getLastEnqueueTime() const
virtual bool functionalWrite(Packet *pkt)
void updateDelayedTicks(Tick curTime)
Update the delay this message has experienced so far.
void setMsgCounter(uint64_t c)
void setLastEnqueueTime(const Tick &time)
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
std::shared_ptr< Message > MsgPtr
const FlagsType nonan
Don't print if this is NAN.
const FlagsType nozero
Don't print if this is zero.
Copyright (c) 2024 Arm Limited All rights reserved.
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint64_t Tick
Tick count type.
void ccprintf(cp::Print &print)