OpenCores
URL https://opencores.org/ocsvn/ht_tunnel/ht_tunnel/trunk

Subversion Repositories ht_tunnel

[/] [ht_tunnel/] [trunk/] [bench/] [vc_ht_tunnel_l1_tb/] [LogicalLayer.cpp] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 acastong
//LogicalLayer.cpp
2
 
3
/* ***** BEGIN LICENSE BLOCK *****
4
 * Version: MPL 1.1
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version
7
 * 1.1 (the "License"); you may not use this file except in compliance with
8
 * the License. You may obtain a copy of the License at
9
 * http://www.mozilla.org/MPL/
10
 *
11
 * Software distributed under the License is distributed on an "AS IS" basis,
12
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
 * for the specific language governing rights and limitations under the
14
 * License.
15
 *
16
 * The Original Code is HyperTransport Tunnel IP Core.
17
 *
18
 * The Initial Developer of the Original Code is
19
 * Ecole Polytechnique de Montreal.
20
 * Portions created by the Initial Developer are Copyright (C) 2005
21
 * the Initial Developer. All Rights Reserved.
22
 *
23
 * Contributor(s):
24
 *   Ami Castonguay <acastong@grm.polymtl.ca>
25
 *
26
 * Alternatively, the contents of this file may be used under the terms
27
 * of the Polytechnique HyperTransport Tunnel IP Core Source Code License
28
 * (the  "PHTICSCL License", see the file PHTICSCL.txt), in which case the
29
 * provisions of PHTICSCL License are applicable instead of those
30
 * above. If you wish to allow use of your version of this file only
31
 * under the terms of the PHTICSCL License and not to allow others to use
32
 * your version of this file under the MPL, indicate your decision by
33
 * deleting the provisions above and replace them with the notice and
34
 * other provisions required by the PHTICSCL License. If you do not delete
35
 * the provisions above, a recipient may use your version of this file
36
 * under either the MPL or the PHTICSCL License."
37
 *
38
 * ***** END LICENSE BLOCK ***** */
39
 
40
#include "../core/PacketContainer.h"
41
#include "../core/InfoPacket.h"
42
#include "../core/RequestPacket.h"
43
#include "LogicalLayer.h"
44
 
45
 
46
const int LogicalLayer::PER_PACKET_CRC_POLY = 0x04C11DB7;
47
const int LogicalLayer::MAX_BUFFERS = 8;
48
 
49
#include <iostream>
50
 
51
using namespace std;
52
 
53
LogicalLayer::LogicalLayer(sc_module_name name) : sc_module(name){
54
        SC_THREAD(reset_thread);
55
        sensitive_pos(clk);
56
        sensitive_neg(resetx);
57
 
58
        inter = NULL;
59
        physicalLayer = NULL;
60
 
61
        packetIdCounter = 0;
62
        retry_mode = false;
63
        retry_mode_after_reset = false;
64
        initiate_retry_disconnect = false;
65
 
66
        receivedPacket = NULL;
67
        receivedDataCount = 0;
68
        receive_state = RECEIVE_IDLE;
69
        rx_ack_value = 0;
70
        rx_retry_waiting_for_nop = false;
71
 
72
 
73
        nopSendPacket = NULL;
74
        currentSendPacket.data = NULL;
75
        currentSendPacket.packet = NULL;
76
        disconNop = false;
77
        ignoreIncoming = false;
78
        displayReceivedDword = false;
79
 
80
        for(int n = 0; n < 3; n++){
81
                nextNodeCommandBuffersFree[n] = 0;
82
                nextNodeDataBuffersFree[n] = 0;
83
 
84
                commandBuffersAdvertised[n] = 0;
85
                dataBuffersAdvertised[n] = 0;
86
                commandBuffersFree[n] = MAX_BUFFERS;
87
                dataBuffersFree[n] = MAX_BUFFERS;
88
        }
89
}
90
 
91
LogicalLayer::~LogicalLayer(){
92
        delete nopSendPacket;
93
        //currentSendPacket is deleted after it's used, no need to delete immediately
94
        delete receivedPacket;
95
        //Packets are both in history and packetQueue.  Clear packetQueue and delete 
96
        //the entries in packetHistory
97
        packetQueue.clear();
98
 
99
        //Delete packets in the history
100
        deque<PacketAndData>::iterator i;
101
        for(i = packetHistory.begin(); i != packetHistory.end();i++){
102
                delete (*i).packet;
103
                delete [] (*i).data;
104
        }
105
}
106
 
107
void LogicalLayer::reset_thread(){
108
        while(true){
109
                if(!resetx.read()){
110
                        retry_mode = retry_mode_after_reset;
111
 
112
                        packetIdCounter = 0;
113
                        receivedDataCount = 0;
114
                        rx_ack_value = 0;
115
                        receive_state = RECEIVE_IDLE;
116
 
117
                        //Packets are both in history and packetQueue.  Clear packetQueue and delete 
118
                        //the entries in packetHistory
119
                        packetQueue.clear();
120
 
121
                        //Delete packets in the history
122
                        deque<PacketAndData>::iterator i;
123
                        for(i = packetHistory.begin(); i != packetHistory.end();i++){
124
                        delete (*i).packet;
125
                        delete [] (*i).data;
126
                        }
127
                        packetHistory.clear();
128
 
129
                        for(int n = 0; n < 3; n++){
130
                                nextNodeCommandBuffersFree[n] = 0;
131
                                nextNodeDataBuffersFree[n] = 0;
132
 
133
                                commandBuffersAdvertised[n] = 0;
134
                                dataBuffersAdvertised[n] = 0;
135
                        }
136
                }
137
                wait();
138
        }
139
}
140
 
141
void LogicalLayer::receivedDwordEvent(sc_bv<32> &dword,bool lctl,bool hctl){
142
        if(displayReceivedDword) cout << "Received dword: " << dword.to_string(SC_HEX) << endl;
143
 
144
        //If reset or during a retry sequence, ignore the received data
145
        if(!resetx.read() || initiate_retry_disconnect || ignoreIncoming)return;
146
 
147
        if(receive_state == RECEIVE_SECOND_DWORD){
148
                //Set the seconde dword of the packet (it only had the first dword set)
149
                receivedPacket->setSecondDword(dword);
150
 
151
                //If there is any data with that packet, go into receiving data state
152
                if(receivedPacket->hasDataAssociated()){
153
                        receivedDataCount = 0;
154
                        receive_state = RECEIVE_DATA;
155
                }
156
                else{
157
                        //If in retry mode, start by receiving the CRC
158
                        if(retry_mode){
159
                                receive_state = RECEIVE_CRC;
160
                        }
161
                        else{
162
                                //Generate event of received packet and wait for next packet
163
                                receive_state = RECEIVE_IDLE;
164
                                inter->receivedHtPacketEvent(receivedPacket,NULL,this);
165
                                updateRxBufferCount(receivedPacket);
166
                        }
167
                }
168
        }
169
 
170
 
171
        else if(receive_state == RECEIVE_DATA){
172
                //If CTL is activated, it is a nop inside data
173
                if(lctl || hctl){
174
                        if(retry_mode){
175
                                firstReceivedDword = dword;
176
                                receive_state = RECEIVE_NOP_CRC;
177
                        }
178
                        else handleNopPacket(dword);
179
                }
180
                else{
181
                        //Set the received data
182
                        receivedData[receivedDataCount] = dword.to_int();
183
 
184
                        //Check if receiving data is done
185
                        if(receivedDataCount++ == receivedPacket->getDataLengthm1()){
186
                                if(retry_mode){
187
                                        receive_state = RECEIVE_CRC;
188
                                }
189
                                else{
190
                                        //When it's done, generate event that packet is received
191
                                        inter->receivedHtPacketEvent(receivedPacket,receivedData,this);
192
                                        updateRxBufferCount(receivedPacket);
193
                                        receive_state = RECEIVE_IDLE;
194
                                }
195
                        }
196
                }
197
        }
198
 
199
 
200
        else if(receive_state == RECEIVE_CRC){
201
                //Calculate the packet CRC
202
                int crc = calcultatePacketCrc(receivedPacket,receivedData);
203
 
204
                //CRC is inversed before being sent out, check if it's invalid
205
                if(~crc != dword.to_int()){
206
                        cout << "Wrong CRC received for packet: " << (*receivedPacket) << endl;
207
                        initiateRetrySequence();
208
                }
209
                /**If valid, handle the packet*/
210
                else{
211
                        //If nop, update the buffer count
212
                        if(receivedPacket->getPacketCommand() == NOP)
213
                                handleNopPacket(firstReceivedDword);
214
                        //Otherwise, notify of received packet and update ack value
215
                        else{
216
                                rx_ack_value++;
217
                                inter->receivedHtPacketEvent(receivedPacket,receivedData,this);
218
                                updateRxBufferCount(receivedPacket);
219
                        }
220
                }
221
                receive_state = RECEIVE_IDLE;
222
        }
223
 
224
        //RECEIVE_NOP_CRC is a state for receiving nops inside data packets.  Check
225
        //if the crc is correct, handle the nop packet and go back to receiving data,
226
        //or initiate retry sequence if crc is incorrect
227
        else if(receive_state == RECEIVE_NOP_CRC){
228
                PacketContainer c = ControlPacket::createPacketFromDword(firstReceivedDword);
229
                int crc = calcultatePacketCrc(c.getPacketRef(),NULL);
230
                if(~crc != dword.to_int()) initiateRetrySequence();
231
                else handleNopPacket(firstReceivedDword);
232
                receive_state = RECEIVE_DATA;
233
        }
234
 
235
        //Otherwise in IDLE state
236
        else{
237
                //store the received dword
238
                firstReceivedDword = dword;
239
 
240
                //Create a packet object from the dword
241
                PacketContainer c = ControlPacket::createPacketFromDword(dword);
242
 
243
                //If its a nop
244
                if(c->getPacketCommand() == NOP){
245
                        if(retry_mode){
246
                                //Delete any previously allocated packet
247
                                delete receivedPacket;
248
                                receivedPacket = c.giveControl();
249
                                receive_state = RECEIVE_CRC;
250
                        }
251
                        else handleNopPacket(dword);
252
                }
253
                //If if only has one dword
254
                else if(c->isDwordPacket()){
255
                        //If it has any data associated to it, go to receiving data state
256
                        if(c->hasDataAssociated()){
257
                                receive_state = RECEIVE_DATA;
258
                                receivedDataCount = 0;
259
                                //Delete any previously allocated packet
260
                                delete receivedPacket;
261
                                receivedPacket = c.giveControl();
262
                        }
263
                        else{
264
                                //packet received, either receive CRC if in retry mode or generate event
265
                                if(retry_mode){
266
                                        receive_state = RECEIVE_CRC;
267
                                        //Delete any previously allocated packet
268
                                        delete receivedPacket;
269
                                        receivedPacket = c.giveControl();
270
                                }
271
                                else{
272
                                        inter->receivedHtPacketEvent(c.getPacketRef(),NULL,this);
273
                                        updateRxBufferCount(c.getPacketRef());
274
                                }
275
                        }
276
                }
277
                //If not dword packet, go to receive second dword state
278
                else{
279
                        receive_state = RECEIVE_SECOND_DWORD;
280
                        delete receivedPacket;
281
                        receivedPacket = c.giveControl();
282
                }
283
        }
284
}
285
 
286
void LogicalLayer::handleNopPacket(sc_bv<32> &dword){
287
        //Create a nop packet
288
        NopPacket* nop = new NopPacket(dword);
289
 
290
        //Update the next node buffer free count
291
        nextNodeCommandBuffersFree[VC_POSTED] += (int)nop->getFreeBufPostedCmd();
292
        nextNodeDataBuffersFree[VC_POSTED] += (int)nop->getFreeBufPostedData();
293
        nextNodeCommandBuffersFree[VC_NON_POSTED] += (int)nop->freeBufNonPostedCmd();
294
        nextNodeDataBuffersFree[VC_NON_POSTED] += (int)nop->freeBufNonPostedData();
295
        nextNodeCommandBuffersFree[VC_RESPONSE] += (int)nop->freeBufResponseCmd();
296
        nextNodeDataBuffersFree[VC_RESPONSE] += (int)nop->freeBufResponseData();
297
        packetIdCounter = (int)nop->getRxNextPacketToAck();
298
 
299
        //If in retry mode, delete old entries in the history
300
        if(retry_mode){
301
                bool done = packetHistory.empty();
302
                while(!done){
303
                        if(((packetIdCounter - packetHistory.front().id + 256) % 256) < 128){
304
                                delete packetHistory.front().packet;
305
                                delete [] packetHistory.front().data;
306
                                packetHistory.pop_front();
307
                                done = packetHistory.empty();
308
                        }
309
                        else done = true;
310
                }
311
        }
312
}
313
 
314
void LogicalLayer::dwordToSendRequested(sc_bv<32> &dword,bool &lctl,bool &hctl){
315
        //during reset, don't send anything
316
        if(!resetx.read()) return;
317
 
318
        if(send_state == SEND_SECOND_DWORD){
319
                //get the second dword from the packet
320
                dword = currentSendPacket.packet->getVector().range(63,32);
321
                //Command packet have CTL=1
322
                lctl = true; hctl = true;
323
 
324
                //Go to the correct state depending on packet type
325
                if(currentSendPacket.packet->hasDataAssociated()){
326
                        sendDataCount = 0;
327
                        send_state = SEND_DATA;
328
                }
329
                else{
330
                        if(retry_mode){
331
                                send_state = SEND_CRC;
332
                        }
333
                        /** In retry mode, packets are stored in history and can be
334
                                deleted when history is acknowleged.  When not in retry mode,
335
                                this does not happen so delete immediately after send*/
336
                        else{
337
                                delete currentSendPacket.packet;
338
                                send_state = SEND_IDLE;
339
                        }
340
                }
341
        }
342
        //If sending an address extension.  This is not supported by the tunnel but
343
        //should be handle cleanly by responding with an error response.  If here,
344
        //the address extension has already been sent, now send the actual packet
345
        else if(send_state == SEND_ADDR_EXT){
346
                //send first dword
347
                dword = currentSendPacket.packet->getVector().range(31,0);
348
 
349
                //go to correct state depending on packet content
350
                bool has_data = currentSendPacket.packet->hasDataAssociated();
351
                VirtualChannel vc = currentSendPacket.packet->getVirtualChannel();
352
 
353
                if(!currentSendPacket.packet->isDwordPacket()){
354
                        send_state = SEND_SECOND_DWORD;
355
                }
356
                else if(has_data){
357
                        send_state = SEND_DATA;
358
                }
359
                else if(retry_mode){
360
                        send_state = SEND_CRC;
361
                }
362
                /** In retry mode, packets are stored in history and can be
363
                        deleted when history is acknowleged.  When not in retry mode,
364
                        this does not happen so delete immediately after send*/
365
                else{
366
                        send_state = SEND_IDLE;
367
                        delete currentSendPacket.packet;
368
                }
369
        }
370
        else if(send_state == SEND_DATA){
371
                //Check if sending a nop in the middle of the data is necessary
372
                if(isSendingNopRequired()){
373
                        //Delete any previous nop packet
374
                        delete nopSendPacket;
375
                        nopSendPacket = generateNopPacket();
376
                        dword = nopSendPacket->getVector().range(31,0);
377
                        lctl = true; hctl = true;
378
                        if(retry_mode){
379
                                send_state = SEND_NOP_CRC;
380
                        }
381
                }
382
                //otherwise keep sending data
383
                else{
384
                        lctl = false; hctl = false;
385
                        dword = currentSendPacket.data[sendDataCount];
386
                        if(sendDataCount++ == currentSendPacket.packet->getDataLengthm1()){
387
                                if(retry_mode){
388
                                        send_state = SEND_CRC;
389
                                }
390
                                /** In retry mode, packets are stored in history and can be
391
                                        deleted when history is acknowleged.  When not in retry mode,
392
                                        this does not happen so delete immediately after send*/
393
                                else{
394
                                        send_state = SEND_IDLE;
395
                                        delete currentSendPacket.packet;
396
                                        delete[] currentSendPacket.data;
397
                                }
398
                        }
399
                }
400
        }
401
        else if(send_state == SEND_NOP_CRC){
402
                int crc = calcultatePacketCrc(nopSendPacket,NULL);
403
                dword = ~crc;
404
                lctl = true; hctl = false;
405
                send_state = SEND_DATA;
406
        }
407
        else if(send_state == SEND_CRC){
408
                int crc = calcultatePacketCrc(currentSendPacket.packet,currentSendPacket.data);
409
                dword = ~crc;
410
                //Value of lctl and hctl depends on if the packet has data or not
411
                if(currentSendPacket.packet->hasDataAssociated()){
412
                        lctl = false; hctl = true;
413
                }
414
                else{
415
                        lctl = true; hctl = false;
416
                }
417
                send_state = SEND_IDLE;
418
 
419
                //If what was just sent a disconnect nop, then we must complete the retry sequence
420
                if(disconNop){
421
                        //reset retry initiation variables
422
                        initiate_retry_disconnect = false;
423
                        disconNop = false;
424
 
425
                        //Start the retry disconnect and reconnect on the physical level
426
                        physicalLayer->retryDisconnectAndReconnect();
427
 
428
                        //Clear current list of packets to send
429
                        packetQueue.clear();
430
                        packetQueue = packetHistory;
431
                        for(int n = 0; n < 3; n++){
432
                                commandBuffersAdvertised[n] = 0;
433
                                dataBuffersAdvertised[n] = 0;
434
                        }
435
                }
436
        }
437
        else{
438
                //If a retry sequence should be initiated
439
                if(initiate_retry_disconnect){
440
                        //Generate a disconnect nop
441
                        delete nopSendPacket;
442
                        nopSendPacket = new NopPacket(0,0,0,0,0,0,
443
                          true, false, false, 0);
444
                        currentSendPacket.packet = nopSendPacket;
445
                        currentSendPacket.data = NULL;
446
                        disconNop = true;
447
 
448
                        //Send that disconnect nop
449
                        dword = nopSendPacket->getVector().range(31,0); lctl = true; hctl = true;
450
                        send_state = SEND_CRC;
451
                }
452
                //Send nop if it is required (for buffer reasons, or if nothing else to send|)
453
                else if(isSendingNopRequired() || packetQueue.empty()){
454
                        //Delete any previous nop packet
455
                        delete nopSendPacket;
456
                        //create a new not
457
                        nopSendPacket = generateNopPacket();
458
                        currentSendPacket.packet = nopSendPacket;
459
                        currentSendPacket.data = NULL;
460
 
461
                        //Send the nop
462
                        dword = currentSendPacket.packet->getVector().range(31,0);
463
                        lctl = true; hctl = true;
464
                        if(retry_mode){
465
                                send_state = SEND_CRC;
466
                        }
467
                }
468
                //Otherwise, attempt to send the packet on top of the queue
469
                else{
470
 
471
                        //Check if the top packet can be sent : check if the next
472
                        //node has sufficient buffers to receive it
473
                        ControlPacket * cmd = packetQueue.front().packet;
474
                        bool has_data = cmd->hasDataAssociated();
475
                        VirtualChannel vc = cmd->getVirtualChannel();
476
                        bool canBeSent = false;
477
                        if(vc <= 2){
478
                                canBeSent = nextNodeCommandBuffersFree[vc] &&
479
                                        (nextNodeDataBuffersFree[vc] || !has_data);
480
                        }
481
                        bool delete_command = false;
482
 
483
                        //If it can be sent, go to the appropriate state to send it
484
                        if(cmd->getPacketCommand() == NOP){
485
                                currentSendPacket = packetQueue.front();
486
                                packetQueue.pop_front();
487
                                if(retry_mode){
488
                                        send_state = SEND_CRC;
489
                                }
490
                                else delete_command = true;
491
                        }
492
                        if(canBeSent){
493
                                nextNodeCommandBuffersFree[vc]--;
494
                                if(has_data) nextNodeDataBuffersFree[vc]--;
495
 
496
                                currentSendPacket = packetQueue.front();
497
                                packetQueue.pop_front();
498
                                if(cmd->getPacketCommand() == ADDR_EXT){
499
                                        send_state = SEND_ADDR_EXT;
500
                                }
501
                                else if(!cmd->isDwordPacket()){
502
                                        send_state = SEND_SECOND_DWORD;
503
                                }
504
                                else if(has_data){
505
                                        send_state = SEND_DATA;
506
                                }
507
                                else if(retry_mode){
508
                                        send_state = SEND_CRC;
509
                                }
510
                                /** In retry mode, packets are stored in history and can be
511
                                        deleted when history is acknowleged.  When not in retry mode,
512
                                        this does not happen so delete immediately after send*/
513
                                else delete_command = true;
514
                        }
515
                        //Otherwise, send a nop
516
                        else{
517
                                //cout << "Not enough buffers, sending nop instead" << endl;
518
                                delete nopSendPacket;
519
                                nopSendPacket = generateNopPacket();
520
                                currentSendPacket.packet = nopSendPacket;
521
                                currentSendPacket.data = NULL;
522
                                if(retry_mode){
523
                                        send_state = SEND_CRC;
524
                                }
525
                        }
526
 
527
                        //If the packet is an address extension, send the address extension first
528
                        if(currentSendPacket.packet->getPacketCommand() == ADDR_EXT){
529
                                dword = ((AddressExtensionPacket*)(currentSendPacket.packet))->getAddressExtension();
530
                        }
531
                        //otherwise, send the first dword
532
                        else{
533
                                dword = currentSendPacket.packet->getVector().range(31,0);
534
                        }
535
                        if(delete_command) delete cmd;
536
                        lctl = true; hctl = true;
537
                }
538
        }
539
}
540
 
541
void LogicalLayer::crcErrorDetected(){
542
        //If in retry mode, periodic CRC is not checked.  In retry mode,
543
        //pass the message up to the next layer
544
        if(!retry_mode)
545
                inter->crcErrorDetected();
546
}
547
 
548
void LogicalLayer::sendPacket(ControlPacket * packet,int * data){
549
        //Add the packet to the queue
550
        PacketAndData pad;
551
        pad.packet = packet;
552
        pad.data = data;
553
        pad.id = ++packetIdCounter;
554
        packetQueue.push_back(pad);
555
 
556
        //If in retry mode, also add it to history
557
        if(retry_mode)
558
                packetHistory.push_back(pad);
559
}
560
 
561
void LogicalLayer::flush(){
562
        //Wait (block) until all packet are sent
563
        while(!packetQueue.empty())wait();
564
}
565
 
566
int LogicalLayer::calcultatePacketCrc(ControlPacket * pkt,int * data){
567
        int crc = 0xFFFFFFFF;
568
        sc_bv<32> dword;
569
 
570
        if(pkt->getPacketCommand() == ADDR_EXT){
571
                dword = ((AddressExtensionPacket*)(currentSendPacket.packet))->getAddressExtension();
572
                calcultateDwordCrc(crc,dword,true);
573
        }
574
 
575
        dword = pkt->getVector().range(31,0);
576
        calcultateDwordCrc(crc,dword,true);
577
 
578
        if(!pkt->isDwordPacket()){
579
                dword = pkt->getVector().range(63,32);
580
                calcultateDwordCrc(crc,dword,true);
581
        }
582
 
583
        if(pkt->hasDataAssociated()){
584
                int max = (int)pkt->getDataLengthm1();
585
                for(int n = 0; n <= max; n++){
586
                        dword = data[n];
587
                        calcultateDwordCrc(crc,dword,false);
588
                }
589
        }
590
        return crc;
591
}
592
 
593
void LogicalLayer::calcultateDwordCrc(int &crc,sc_bv<32> &dword,bool ctl){
594
        for(int n = 0; n < 2; n++){
595
                int ctl_or = ctl ? 0x10000 : 0;
596
                int data = (dword.to_int() >> (n*16)) & 0xFFFF | ctl_or;
597
 
598
                for(int i = 0; i < 17; i++){
599
                        //xor highest bit w/ message
600
                        int tmp = ((crc >> 31 & 1)^((data >> i) & 1));
601
                        //substract poly if greater
602
                        crc = (tmp) ? (crc << 1) ^ PER_PACKET_CRC_POLY : ((crc << 1) | tmp);
603
                }
604
        }
605
}
606
 
607
 
608
void LogicalLayer::initiateRetrySequence(){
609
        //initiate_retry_disconnect will make the link send a disconnect nop and ignore RX
610
        initiate_retry_disconnect = true;
611
        //Go to idle RX state to be ready for a new packet when coming out of retry sequence
612
        receive_state = RECEIVE_IDLE;
613
 
614
        //Clear the current buffer count
615
        for(int n = 0; n < 3; n++){
616
                nextNodeCommandBuffersFree[n] = 0;
617
                nextNodeDataBuffersFree[n] = 0;
618
        }
619
}
620
 
621
bool LogicalLayer::isSendingNopRequired(){
622
        bool required = false;
623
        for(int n = 0; n < 3; n++){
624
                if((commandBuffersFree[n] - commandBuffersAdvertised[n]) > 2) required = true;
625
                if((dataBuffersFree[n] - dataBuffersAdvertised[n]) > 2) required = true;
626
        }
627
        return required;
628
}
629
 
630
void LogicalLayer::updateRxBufferCount(ControlPacket * receivedPacket){
631
        VirtualChannel vc = receivedPacket->getVirtualChannel();
632
        bool hasData = receivedPacket->hasDataAssociated();
633
 
634
        if(vc == VC_NONE) return;
635
        if(hasData) dataBuffersAdvertised[vc]--;
636
        else commandBuffersAdvertised[vc]--;
637
}
638
 
639
NopPacket * LogicalLayer::generateNopPacket(){
640
        sc_uint<2> responseBuffersToSend = min((commandBuffersFree[VC_RESPONSE] - commandBuffersAdvertised[VC_RESPONSE]),3);
641
        sc_uint<2> responseDataBuffersToSend = min((dataBuffersFree[VC_RESPONSE] - dataBuffersAdvertised[VC_RESPONSE]),3);
642
        sc_uint<2> postedBuffersToSend = min((commandBuffersFree[VC_POSTED] - commandBuffersAdvertised[VC_POSTED]),3);
643
        sc_uint<2> postedDataBuffersToSend = min((dataBuffersFree[VC_POSTED] - dataBuffersAdvertised[VC_POSTED]),3);
644
        sc_uint<2> npostedBuffersToSend = min((commandBuffersFree[VC_NON_POSTED] - commandBuffersAdvertised[VC_NON_POSTED]),3);
645
        sc_uint<2> npostedDataBuffersToSend = min((dataBuffersFree[VC_NON_POSTED] - dataBuffersAdvertised[VC_NON_POSTED]),3);
646
 
647
        commandBuffersAdvertised[VC_RESPONSE] += (int)responseBuffersToSend;
648
        dataBuffersAdvertised[VC_RESPONSE] += (int)responseDataBuffersToSend;
649
        commandBuffersAdvertised[VC_POSTED] += (int)postedBuffersToSend;
650
        dataBuffersAdvertised[VC_POSTED] += (int)postedDataBuffersToSend;
651
        commandBuffersAdvertised[VC_NON_POSTED] += (int)npostedBuffersToSend;
652
        dataBuffersAdvertised[VC_NON_POSTED] += (int)npostedDataBuffersToSend;
653
 
654
        return new NopPacket(responseBuffersToSend,
655
                      responseDataBuffersToSend,
656
                          postedBuffersToSend,
657
                      postedDataBuffersToSend,
658
                          npostedBuffersToSend,
659
                      npostedDataBuffersToSend,
660
                          false, false, false, rx_ack_value);
661
}
662
 

powered by: WebSVN 2.1.0

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