OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_c/] [synfull/] [traffic-generator/] [src/] [TrafficGenerator.cpp] - Blame information for rev 54

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 54 alirezamon
/*
2
Copyright (c) 2014, Mario Badr
3
All rights reserved.
4
 
5
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
 
7
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
 
9
2. 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.
10
 
11
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 HOLDER 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.
12
*/
13
/*
14
 * TrafficGenerator.cpp
15
 *
16
 *  Created on: 2013-01-13
17
 *      Author: mario
18
 */
19
 
20
#include <iostream>
21
#include <list>
22
#include <math.h>
23
 
24
#include "assert.h"
25
#include <map>
26
#include <list>
27
#include <set>
28
 
29
#include "socketstream.h"
30
#include "messages.h"
31
#include "Global.h"
32
 
33
#include "PacketQueue.h"
34
 
35
using namespace std;
36
 
37
//Set this to 0 to debug without connecting to booksim
38
#define CONNECT 1
39
 
40
SocketStream m_channel;
41
 
42
static unsigned long long next_interval;
43
static unsigned long long next_hinterval;
44
 
45
static unsigned long long cycle;
46
 
47
static unsigned long int total_pck_queud=0;
48
 
49
int state = 1;
50
int lastState = 1;
51
int lastHState = 1;
52
 
53
int messageId = 0;
54
 
55
int allPacketsEjected=0;
56
 
57
//Steady state
58
map<int, map<int, int> > steadyState;
59
map<int, int> hSteadyState;
60
map<int, double> acceptable_mse;
61
double acceptable_hmse;
62
 
63
struct transaction_t {
64
    int source;
65
    int dest;
66
    int invs_sent;
67
    int acks_received;
68
    bool data_received;
69
    bool unblock_received;
70
 
71
    bool Completed() {
72
        return (invs_sent == acks_received) && data_received && unblock_received;
73
    }
74
 
75
    transaction_t() : source(-1), dest(-1), invs_sent(0), acks_received(0),
76
            data_received(false), unblock_received(false) {}
77
};
78
 
79
map<int, InjectReqMsg> inTransitPackets;
80
map<int, transaction_t> inTransitTransactions;
81
PacketQueue packet_queue;
82
 
83
void TranslateIndex(int index, int& source, int& destination) {
84
    source = (int) index / 32; //Truncate remainder
85
    destination = index - (source * 32);
86
}
87
 
88
void printPacket(InjectReqMsg msg) {
89
    cout << msg.id << " ";
90
    cout << cycle << " ";
91
    cout << msg.source << " ";
92
    cout << msg.dest << " ";
93
    cout << msg.packetSize << " ";
94
    cout << msg.msgType << " ";
95
    cout << msg.coType << " ";
96
    cout << msg.address << " ";
97
    cout << state;
98
    cout << endl;
99
}
100
 
101
void connect() {
102
#if CONNECT
103
    // connect to network simulator
104
    assert(m_channel.connect(NS_HOST, NS_PORT) == 0);
105
 
106
    // send request to initialize
107
    InitializeReqMsg req;
108
    InitializeResMsg res;
109
    m_channel << req >> res;
110
#endif
111
}
112
 
113
void exit() {
114
        cout << "Total packet sent to queue: " << total_pck_queud << endl;
115
#if CONNECT
116
    // Notify network we are quitting
117
    QuitReqMsg req;
118
    QuitResMsg res;
119
    m_channel << req >> res;
120
#endif
121
}
122
 
123
void sendPacket(InjectReqMsg& req) {
124
    req.id = messageId;
125
 
126
    if((int) req.address == -1) {
127
        req.address = messageId;
128
        inTransitTransactions[req.address].source = req.source;
129
        inTransitTransactions[req.address].dest = req.dest;
130
        inTransitTransactions[req.address].invs_sent = 0;
131
        inTransitTransactions[req.address].acks_received = 0;
132
    }
133
    messageId++;
134
 
135
    inTransitPackets[req.id] = req;
136
 
137
#if CONNECT
138
    InjectResMsg res;
139
 
140
    m_channel << req >> res;
141
#endif
142
}
143
 
144
double calculate_mse(vector<double> predict, vector<double> actual) {
145
    if(predict.size() != actual.size()) {
146
        return -1;
147
    }
148
 
149
    double sum = 0;
150
    for(unsigned int i = 0; i < predict.size(); i++) {
151
        sum += (predict[i] - actual[i]) * (predict[i] - actual[i]);
152
    }
153
 
154
    return ((double) sum / predict.size());
155
}
156
 
157
bool InHSteadyState(int numCycles) {
158
    vector<double> predict;
159
    int sum = 0;
160
    for (map<int, int>::iterator it=hSteadyState.begin();
161
            it!=hSteadyState.end(); ++it) {
162
        double value =  it->second;
163
        sum+= value;
164
        predict.push_back(value);
165
    }
166
 
167
    for(unsigned int i = 0; i < predict.size(); i++) {
168
        predict[i] = ((double) predict[i] / sum);
169
    }
170
 
171
    double mse = calculate_mse(predict, g_hierSState);
172
    if(mse >= 0 && mse < acceptable_hmse && cycle > numCycles*0.3) {
173
        return true;
174
    }
175
 
176
    if(cycle > numCycles*0.7) {
177
        return true;
178
    }
179
 
180
    return false;
181
}
182
 
183
 
184
 
185
void QueuePacket(int source, int destination, int msgType, int coType,
186
        int packetSize, int time, int address) {
187
    InjectReqMsg packet;
188
    packet.source = source;
189
    packet.dest = destination;
190
    packet.cl = 0;
191
    packet.network = 0;
192
    packet.packetSize = packetSize;
193
    packet.msgType = msgType;
194
    packet.coType = coType;
195
    packet.address = address;
196
 
197
    packet_queue.Enqueue(packet, time);
198
    total_pck_queud++;
199
}
200
 
201
void UniformInject(int writes, int reads, int ccrs, int dcrs) {
202
    int source, destination;
203
    UniformDistribution uni_dist(0, g_resolution/2 -1);
204
 
205
    int delta = 0;
206
 
207
    for(int i = 0; i < writes; i++) {
208
        delta = uni_dist.Generate(0) * 2;
209
        source = g_writeSpat[g_hierClass][state].Generate(0);
210
        source = source * 2;
211
 
212
        destination = g_writeDest[g_hierClass][state][source].Generate(0);
213
        destination = destination * 2 + 1;
214
 
215
        QueuePacket(source, destination, REQUEST, WRITE, CONTROL_SIZE,
216
                cycle + delta, -1);
217
    }
218
 
219
    for(int i = 0; i < reads; i++) {
220
        delta = uni_dist.Generate(0) * 2;
221
        source = g_readSpat[g_hierClass][state].Generate(0);
222
        source = source * 2;
223
 
224
        destination = g_readDest[g_hierClass][state][source].Generate(0);
225
        destination = destination * 2 + 1;
226
 
227
        QueuePacket(source, destination, REQUEST, READ, CONTROL_SIZE,
228
                cycle + delta, -1);
229
    }
230
 
231
    for(int i = 0; i < ccrs; i++) {
232
        delta = uni_dist.Generate(0) * 2;
233
        source = g_ccrSpat[g_hierClass][state].Generate(0);
234
        source = source * 2;
235
 
236
        destination = g_ccrDest[g_hierClass][state][source].Generate(0);
237
        destination = destination * 2 + 1;
238
 
239
        QueuePacket(source, destination, REQUEST, PUTC, CONTROL_SIZE,
240
                cycle + delta, -1);
241
    }
242
 
243
    for(int i = 0; i < dcrs; i++) {
244
        delta = uni_dist.Generate(0) * 2;
245
        source = g_dcrSpat[g_hierClass][state].Generate(0);
246
        source = source * 2;
247
 
248
        destination = g_dcrDest[g_hierClass][state][source].Generate(0);
249
        destination = destination * 2 + 1;
250
 
251
        QueuePacket(source, destination, REQUEST, PUTD, DATA_SIZE,
252
                cycle + delta, -1);
253
    }
254
}
255
 
256
//Volumes
257
void InitiateMessages() {
258
    int writes = g_writes[g_hierClass][state].Generate(0);
259
    int reads = g_reads[g_hierClass][state].Generate(0);
260
    int ccrs = g_ccrs[g_hierClass][state].Generate(0);
261
    int dcrs = g_dcrs[g_hierClass][state].Generate(0);
262
 
263
    //cout << "synfull: writes " << writes << " reads " << reads << " ccrs " << ccrs << " dcrs " << dcrs  << endl;
264
    UniformInject(writes, reads, ccrs, dcrs);
265
}
266
 
267
void Inject() {
268
    list<InjectReqMsg> packets = packet_queue.DeQueue(cycle);
269
    list<InjectReqMsg>::iterator it;
270
 
271
    for(it = packets.begin(); it != packets.end(); ++it) {
272
        sendPacket(*it);
273
    }
274
 
275
    packet_queue.CleanUp(cycle);
276
}
277
 
278
void react(EjectResMsg ePacket) {
279
    map<int, InjectReqMsg>::iterator it = inTransitPackets.find(ePacket.id);
280
    if(it == inTransitPackets.end()) {
281
        cerr << "Error: couldn't find in transit packet " << ePacket.id << endl;
282
        exit(-1);
283
    }
284
 
285
    InjectReqMsg request = it->second;
286
    InjectReqMsg response;
287
    inTransitPackets.erase(it);
288
 
289
    //cout << "synfull received packet id: " << request.id << " " << cycle  << endl;
290
 
291
 
292
    map<int, transaction_t>::iterator trans = inTransitTransactions.find(request.address);
293
 
294
    if(request.msgType == REQUEST &&
295
            (request.coType == WRITE || request.coType == READ)) {
296
        //Handle Read/Write Requests
297
        if((int) request.address == request.id) {
298
            //This is an initiating request. Should we forward it or go to
299
            //memory?
300
            bool isForwarded = g_toForward[g_hierClass][request.dest][request.coType].Generate(0) == 0;
301
 
302
            if(isForwarded) {
303
                int destination = g_forwardDest[g_hierClass][state][request.dest].Generate(0);
304
                destination = destination*2;
305
                if(destination % 2 != 0) {
306
                    cerr << "Error: Invalid destination for forwarded request." << endl;
307
                    exit();
308
                }
309
 
310
                QueuePacket(request.dest, destination, REQUEST, request.coType,
311
                        CONTROL_SIZE, cycle + 1, request.address);
312
 
313
                if(request.coType == WRITE) {
314
                    //How many invalidates to send
315
                    int numInv = g_numInv[g_hierClass][state][request.dest].Generate(0);
316
                    int s = state;
317
 
318
                    if(numInv <= 0) {
319
                        return;
320
                    }
321
 
322
                    //Ensure invalidate destinations are unique (i.e. no two
323
                    //invalidate messages to the same destination)
324
                    set<int> destinations;
325
                    destinations.insert(destination); //Request already forwarded here
326
                    while(destinations.size() != (unsigned int) numInv) {
327
                        int dest = g_invDest[g_hierClass][s][request.dest].Generate(0);
328
                        dest = dest*2;
329
                        destinations.insert(dest);
330
                    }
331
 
332
                    for(set<int>::iterator it = destinations.begin();
333
                            it != destinations.end(); ++it) {
334
                        QueuePacket(request.dest, *it, REQUEST, INV,
335
                                CONTROL_SIZE, cycle + 1, request.address);
336
                        trans->second.invs_sent++;
337
                    }
338
                }
339
 
340
            } else {
341
                //Access memory, queue up a data response for the future
342
                    //cout << "synfull mem access  id: " << request.id << " src:"<< request.source 
343
                    //    << " dst:" << request.dest << " addr:" << request.address 
344
                    //    << " " << cycle  << endl;
345
                QueuePacket(request.dest, request.source, RESPONSE, DATA,
346
                        DATA_SIZE, cycle + 80, request.address);
347
            }
348
 
349
            return;
350
        } else {
351
            //This is not an initiating request, so it's a forwarded request
352
            //if(request.id==52)
353
            //{
354
            //    cout << "synfull packet debug  id: " << request.id << " src:"<< request.dest 
355
            //        << " dst:" << trans->second.source << 
356
            //           " addr:" << request.address << " " << cycle  << endl;
357
            //}
358
 
359
            //Respond with Data
360
            QueuePacket(request.dest,
361
                    trans->second.source, RESPONSE,
362
                    DATA, DATA_SIZE, cycle + 1, request.address);
363
        }
364
    }
365
    else if(request.msgType == REQUEST &&
366
            (request.coType == PUTC || request.coType == PUTD)) {
367
        //Respond with WB_ACK
368
        QueuePacket(request.dest, request.source, RESPONSE, WB_ACK,
369
                CONTROL_SIZE, cycle + 1, request.address);
370
 
371
    }
372
    else if(request.msgType == REQUEST && request.coType == INV) {
373
        //Respond with Ack
374
        QueuePacket(request.dest, trans->second.source,
375
                RESPONSE, ACK, CONTROL_SIZE, cycle + 1, request.address);
376
    } else if(request.msgType == RESPONSE && request.coType == DATA) {
377
        trans->second.data_received = true;
378
        //Send unblock
379
        QueuePacket(inTransitTransactions[request.address].source,
380
                inTransitTransactions[request.address].dest, RESPONSE, UNBLOCK,
381
                CONTROL_SIZE, cycle + 1, request.address);
382
    } else if(request.msgType == RESPONSE && request.coType == ACK) {
383
        trans->second.acks_received++;
384
    } else if(request.msgType == RESPONSE && request.coType == UNBLOCK) {
385
                trans->second.unblock_received = true;
386
        }
387
 
388
    if(trans->second.Completed()) {
389
        inTransitTransactions.erase(trans);
390
    }
391
}
392
 
393
unsigned long long int cntPackets = 0;
394
 
395
void Eject(unsigned int numPackets) {
396
#if CONNECT
397
    EjectReqMsg req; //The request to the network
398
    EjectResMsg res; //The response from the network
399
    bool hasRequests = true; //Whether there are more requests from the network
400
 
401
    //Loop through all the network's messages
402
    while(hasRequests) {
403
        m_channel << req >> res;
404
 
405
        if(res.id >= 0) {
406
            //Add responses to list
407
            if(res.id > -1) {
408
                cntPackets++;
409
                react(res);
410
            }
411
        }
412
        //Check if there are more messages from the network
413
        hasRequests = res.remainingRequests;
414
 
415
    }
416
 
417
        if (cntPackets == numPackets)
418
        {
419
            allPacketsEjected=1;
420
        }
421
#endif
422
}
423
 
424
void reset_ss() {
425
    for (std::map<int,int>::iterator it=steadyState[g_hierClass].begin();
426
            it!=steadyState[g_hierClass].end(); ++it) {
427
        it->second = 0;
428
    }
429
    state = 1;
430
}
431
 
432
void Run(unsigned int numCycles, bool ssExit, unsigned int numPackets) {
433
    next_interval = 0;
434
    next_hinterval = 0;
435
 
436
    //Calculate an acceptable MSE for the Markovian Steady-State
437
    double sensitivity = 1.04;
438
    vector<double> predict;
439
    for (unsigned int i = 0; i < g_hierSState.size(); i++) {
440
        predict.push_back(((double) g_hierSState[i] * sensitivity));
441
    }
442
    acceptable_hmse = calculate_mse(predict, g_hierSState);
443
 
444
    //Connect to network simulator
445
    connect();
446
 
447
        //Iterate through each cycle and inject packets
448
        for(cycle = 0; cycle < numCycles; ++cycle) {
449
            if(cycle >= next_hinterval) {
450
                next_hinterval += g_timeSpan;
451
 
452
                hSteadyState[g_hierClass]++;
453
 
454
                if(cycle != 0) {
455
                    lastHState = g_hierClass;
456
                    g_hierClass = g_hierState[g_hierClass].Generate(0) + 1;
457
                    reset_ss();
458
                }
459
 
460
                if(InHSteadyState(numCycles) && ssExit) {
461
                    cout << "Ending simulation at steady state: " << cycle << endl;
462
                    break;
463
                }
464
 
465
                cout << "Current hierarchical state: " << g_hierClass << endl;
466
            }
467
 
468
            if(cycle >= next_interval) {
469
                next_interval += g_resolution;
470
 
471
                //Track state history for markovian steady state
472
                steadyState[g_hierClass][state]++;
473
 
474
                if(cycle != 0) {
475
                    //Update state
476
                    lastState = state;
477
                    state = g_states1[g_hierClass][state].Generate(0) + 1;
478
                }
479
 
480
                //Queue up initiating messages for injection
481
                InitiateMessages();
482
            }
483
 
484
            //Inject all of this cycles' messages into the network
485
            Inject();
486
 
487
            //Eject from network
488
            Eject(numPackets);
489
 
490
            if (allPacketsEjected)
491
            {
492
                cycle = numCycles;
493
            }
494
            //Step the network
495
#if CONNECT
496
            StepReqMsg req;
497
            StepResMsg res;
498
            m_channel << req >> res;
499
#endif
500
        }
501
 
502
    //Close the connection
503
    exit();
504
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.