Skip to content

Commit 398bd50

Browse files
committed
misc: Add latency tracking, no buffer mode
Latency tracking (in buffer + network delay) No buffer mode; does not store in a buffer at all Config script accepts a --no-buffer arg
1 parent ec287d3 commit 398bd50

File tree

6 files changed

+78
-21
lines changed

6 files changed

+78
-21
lines changed

configs/supernetwork/SRNoC.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ def create_base_parser():
160160
default=1,
161161
help="values per port per window",
162162
)
163+
parser.add_argument(
164+
"--no-buffer",
165+
action="store_true",
166+
help="Use no buffer mode (default is buffered mode)",
167+
)
163168
return parser
164169

165170

@@ -326,6 +331,11 @@ def main():
326331
for layer in layers:
327332
layer.setRandomTrafficMode()
328333

334+
# Set the no buffer mode if specified.
335+
if args.no_buffer:
336+
for layer in layers:
337+
layer.setNoBufferMode()
338+
329339
exit_event = m5.simulate()
330340
print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}")
331341

src/network/Layer.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,5 @@ class Layer(ClockedObject):
6868
PyBindMethod("setBitComplementTrafficMode"),
6969
PyBindMethod("setNearestNeighborTrafficMode"),
7070
PyBindMethod("setShuffle"),
71+
PyBindMethod("setNoBufferMode"),
7172
]

src/network/buffered_port.cc

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,35 @@ BufferedPort::getAddr()
6262
void
6363
BufferedPort::assignValue(uint64_t dest_addr)
6464
{
65-
valueQueue.push(dest_addr); // Queue the dest
65+
valueQueue.emplace(ValueEntry{dest_addr, curTick()});
6666
DPRINTF(BufferedPort,
6767
"BufferedPort %d assigned value "
6868
"to destination %d\n",
6969
addr, dest_addr
7070
);
7171
}
7272

73+
// Clear the queue of values
74+
void
75+
BufferedPort::clearQueue()
76+
{
77+
while (!valueQueue.empty()) {
78+
valueQueue.pop();
79+
}
80+
}
81+
7382
// Retrieves and removes the next value from the queue
7483
// Returns 0 if no values are available
75-
uint64_t
84+
ValueEntry
7685
BufferedPort::getNextValue()
7786
{
7887
if (!valueQueue.empty()) {
7988
// Get the next value and remove it from the queue
80-
uint64_t nextValue = valueQueue.front();
89+
ValueEntry nextValue = valueQueue.front();
8190
valueQueue.pop();
8291
return nextValue;
8392
}
84-
return 0; // No value available
93+
return ValueEntry{0, 0}; // No value available
8594
}
8695

8796
// Checks if there are any values in the queue
@@ -118,9 +127,9 @@ uint64_t
118127
BufferedPort::peekNextValue() const
119128
{
120129
if (!valueQueue.empty()) {
121-
return valueQueue.front();
130+
return valueQueue.front().dest;
122131
}
123-
return -1; // No value available
132+
return -1; // No value available
124133
}
125134

126135
} // namespace gem5

src/network/buffered_port.hh

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@
3636

3737
namespace gem5
3838
{
39-
39+
struct ValueEntry
40+
{
41+
uint64_t dest;
42+
Tick enqueueTick;
43+
};
4044
// The BufferedPort class represents a single node in the network
4145
// responsible for storing, sending, and receiving values.
4246
// It tracks its data, address, and maintains statistics for
@@ -48,7 +52,7 @@ class BufferedPort : public ClockedObject
4852
uint64_t addr;
4953

5054
// Queue to hold values (destination addresses) assigned to the port
51-
std::queue<uint64_t> valueQueue;
55+
std::queue<ValueEntry> valueQueue;
5256

5357
// Variables to store the most recent received data and source addr
5458
uint64_t lastReceivedData = 0;
@@ -67,14 +71,18 @@ class BufferedPort : public ClockedObject
6771
uint64_t getAddr();
6872

6973
// Assigns a value to the queue with the given destination address
70-
void assignValue(uint64_t dest_addr);
74+
// The value is stored with the current tick as the enqueue time
75+
void assignValue(uint64_t dest);
76+
77+
// Clears the queue of values
78+
void clearQueue();
7179

7280
// Receives data from another port
7381
// Stores the received value and source
7482
void receiveData(uint64_t received_data, uint64_t src_addr);
7583

7684
// Retrieves and removes the next value from the queue
77-
uint64_t getNextValue();
85+
ValueEntry getNextValue();
7886

7987
// Checks if the port has any values in its queue
8088
bool hasValues() const;

src/network/layer.cc

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Layer::Layer(const LayerParams& params) :
6969
isFinished(false),
7070
fileMode(false),
7171
shuffleEnabled(false),
72+
noBufferMode(false),
7273
size(params.buffered_ports.size()),
7374
// Event for processing the next network event
7475
nextNetworkEvent([this]{ processNextNetworkEvent(); },
@@ -314,7 +315,8 @@ Layer::processValues(
314315

315316
uint64_t value_dest = -1;
316317
// Check if there's already a value in the buffer first
317-
if (port->hasValues()) {
318+
if (port->hasValues() && !noBufferMode) {
319+
// Peek the next value from the port's queue
318320
value_dest = port->peekNextValue();
319321
} else {
320322
if (!fileMode) {
@@ -430,9 +432,20 @@ Layer::processValues(
430432
// Check if value can be sent in the current time slot
431433
if (value_dest == allowed_dest) {
432434
// Remove the value if it was from the buffer
435+
Tick enqueue_tick = 0;
433436
if (port->hasValues()) {
434-
port->getNextValue();
437+
auto entry = port->getNextValue();
438+
value_dest = entry.dest;
439+
enqueue_tick = entry.enqueueTick;
440+
} else {
441+
enqueue_tick = curTick();
442+
}
443+
444+
// We can clear out the buffer
445+
if (!noBufferMode) {
446+
port->clearQueue();
435447
}
448+
436449
uint64_t payload;
437450
used_payloads.reserve(valuesPerPortPerWindow);
438451
while (used_payloads.size() < valuesPerPortPerWindow) {
@@ -472,9 +485,6 @@ Layer::processValues(
472485
crosspointDelay +
473486
variabilityCountingNetwork;
474487

475-
// Log the value processing details
476-
stats.valueLatency.sample(payload_specific_delay);
477-
478488
DPRINTF(Layer,
479489
"Processing value: src=%lu, dest=%lu, \
480490
data=%lu, specific delay=%lu ps\n",
@@ -488,8 +498,8 @@ Layer::processValues(
488498

489499
// Schedule value delivery with payload-specific timing
490500
schedule(new EventFunctionWrapper([this,
491-
src_addr, allowed_dest, p]() {
492-
deliverValue(src_addr, allowed_dest, p);
501+
src_addr, allowed_dest, p, enqueue_tick]() {
502+
deliverValue(src_addr, allowed_dest, p, enqueue_tick);
493503
}, "deliverValueEvent"), curTick() + payload_specific_delay);
494504

495505
// Check if we've reached max values after processing this one
@@ -500,7 +510,11 @@ Layer::processValues(
500510
}
501511
} else if (!fileMode) {
502512
// Value not allowed in the current time slot
503-
port->assignValue(value_dest);
513+
if (!noBufferMode){
514+
// If not in noBufferMode,
515+
// assign the value to the buffer
516+
port->assignValue(value_dest);
517+
}
504518
// Increment missed values for the BufferedPort
505519
port->incrementMissedValues();
506520
stats.missedValuesPerBufferedPort.sample(
@@ -545,13 +559,20 @@ Layer::processValues(
545559
// Deliver a value to its destination port
546560
void
547561
Layer::deliverValue(uint64_t src_addr,
548-
uint64_t dest_addr, uint64_t payload)
562+
uint64_t dest_addr, uint64_t payload,
563+
Tick enqueue_tick)
549564
{
565+
Tick total_latency = curTick() - enqueue_tick;
566+
DPRINTF(Layer,
567+
"Value delivery: src=%lu, dest=%lu, data=%lu, latency=%lu\n",
568+
src_addr, dest_addr, payload, total_latency
569+
);
550570
// Find the destination port
551571
BufferedPort* dest_port = getBufferedPort(dest_addr);
552572
if (dest_port != nullptr) {
553573
// Receive data at the destination port
554574
dest_port->receiveData(payload, src_addr);
575+
stats.valueLatency.sample(total_latency);
555576
DPRINTF(Layer,
556577
"Value delivered: src=%lu, dest=%lu, data=%lu\n",
557578
src_addr, dest_addr, payload
@@ -616,7 +637,8 @@ Layer::LayerStats::regStats()
616637
missedValuesPerBufferedPort.init(64);
617638

618639
valueLatency.init(64)
619-
.name("valueLatency");
640+
.name("valueLatency")
641+
.desc("End-to-end latency (ps) = buffer delay + network");
620642
}
621643

622644
} // namespace gem5

src/network/layer.hh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ private:
7979
bool isFinished; // Flag to indicate if the layer has finished
8080
bool fileMode; // Flag to indicate if a file is used for scheduling
8181
bool shuffleEnabled; // Flag to indicate if shuffling is enabled
82+
bool noBufferMode; // Flag to indicate if no buffering is used
8283
std::string schedulePath; // Path to the schedule file
8384
NetworkScheduler scheduler; // Scheduler for the network
8485
SuperNetwork* superNetwork; // Pointer to the super network
@@ -105,7 +106,8 @@ private:
105106
);
106107
// Method for delivering a value to its destination
107108
void deliverValue(uint64_t src_addr,
108-
uint64_t dest_addr, uint64_t payload
109+
uint64_t dest_addr, uint64_t payload,
110+
Tick enqueue_tick
109111
);
110112

111113
// Struct to hold statistics related to the Layer
@@ -218,6 +220,11 @@ public:
218220
}
219221

220222
void setShuffle() { shuffleEnabled = true; }
223+
224+
void setNoBufferMode()
225+
{
226+
noBufferMode = true;
227+
}
221228
};
222229

223230
} // namespace gem5

0 commit comments

Comments
 (0)