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

Subversion Repositories xge_mac

[/] [xge_mac/] [trunk/] [tbench/] [systemc/] [sc_xgmii_if.cpp] - Blame information for rev 12

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

Line No. Rev Author Line
1 2 antanguay
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "sc_xgmii_if.cpp"                                 ////
4
////                                                              ////
5
////  This file is part of the "10GE MAC" project                 ////
6
////  http://www.opencores.org/cores/xge_mac/                     ////
7
////                                                              ////
8
////  Author(s):                                                  ////
9
////      - A. Tanguay (antanguay@opencores.org)                  ////
10
////                                                              ////
11
//////////////////////////////////////////////////////////////////////
12
////                                                              ////
13
//// Copyright (C) 2008 AUTHORS. All rights reserved.             ////
14
////                                                              ////
15
//// This source file may be used and distributed without         ////
16
//// restriction provided that this copyright statement is not    ////
17
//// removed from the file and that any derivative work contains  ////
18
//// the original copyright notice and the associated disclaimer. ////
19
////                                                              ////
20
//// This source file is free software; you can redistribute it   ////
21
//// and/or modify it under the terms of the GNU Lesser General   ////
22
//// Public License as published by the Free Software Foundation; ////
23
//// either version 2.1 of the License, or (at your option) any   ////
24
//// later version.                                               ////
25
////                                                              ////
26
//// This source is distributed in the hope that it will be       ////
27
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
28
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
29
//// PURPOSE.  See the GNU Lesser General Public License for more ////
30
//// details.                                                     ////
31
////                                                              ////
32
//// You should have received a copy of the GNU Lesser General    ////
33
//// Public License along with this source; if not, download it   ////
34
//// from http://www.opencores.org/lgpl.shtml                     ////
35
////                                                              ////
36
//////////////////////////////////////////////////////////////////////
37
 
38
#include <stdio.h>
39
#include <iostream>
40
#include <sys/times.h>
41
#include <sys/stat.h>
42
 
43
#include "systemc.h"
44
 
45
#include "sc_xgmii_if.h"
46
 
47
sc_fifo<packet_t*> * xgmii_if::get_tx_fifo_ptr() {
48
    return &tx_fifo;
49
}
50
 
51
sc_fifo<packet_t*> * xgmii_if::get_rx_fifo_ptr() {
52
    return &rx_fifo;
53
}
54
 
55
void xgmii_if::init(void) {
56
    allow_idle_errors = false;
57
    disable_padding = false;
58
}
59
 
60
void xgmii_if::connect_scoreboard(scoreboard *sbptr, scoreboard::sbSourceId sid) {
61
    sb = sbptr;
62
    sb_id = sid;
63
}
64
 
65
void xgmii_if::transmit() {
66
 
67
    packet_t* pkt;
68
 
69
    sc_uint<64> txd = 0;
70
    sc_uint<8> txc = 0;
71
 
72
    int lane = 0;
73
    int bytecnt = 0;
74
    int length = 0;
75
    int preamblecnt = 0;
76
    int ifg = 0;
77
    int fragment_size = 8;
78
    int coding_offset = 0;
79
    int fault_cnt = 0;
80
    int fault_byte = 0;
81
    int fault_spacing;
82
    int fault_spacing_cnt = 0;
83
 
84
    while (true) {
85
 
86
        if (length == 0 && tx_fifo.nb_read(pkt)) {
87
 
88
            if (!disable_padding) {
89
                pad(pkt, 60);
90
            }
91
            pack(pkt);
92
 
93
            calc_crc(pkt);
94
 
95
            //---
96
            // Inject errors
97
 
98
            if (pkt->err_flags & PKT_FLAG_ERR_CRC) {
99
                pkt->crc++;
100
            }
101
 
102
            if (pkt->err_flags & PKT_FLAG_ERR_FRG) {
103
                pkt->length = fragment_size;
104
                fragment_size++;
105
                if (fragment_size > 64) {
106
                    fragment_size = 8;
107
                }
108
            }
109
 
110
            if (pkt->err_flags & PKT_FLAG_ERR_CODING) {
111
                if (coding_offset >= pkt->length) {
112
                    pkt->err_info = pkt->length-1;
113
                }
114
                else {
115
                    pkt->err_info = coding_offset;
116
                }
117
                coding_offset++;
118
                if (coding_offset >= 70) {
119
                    coding_offset = 0;
120
                }
121
            }
122
 
123
            //---
124
            // Inject local / remote faults
125
 
126
            if (pkt->err_flags & PKT_FLAG_LOCAL_FAULT ||
127
                pkt->err_flags & PKT_FLAG_REMOTE_FAULT) {
128
                fault_cnt = 4;
129
                fault_byte = 4;
130
                fault_spacing_cnt = 0;
131
 
132
                fault_spacing = pkt->err_info;
133
                cout << "INFO: Fault insert, spacing: " << fault_spacing << endl;
134
            }
135
 
136
            //---
137
            // Pass packet to scoreboard
138
 
139
            sb->notify_packet_tx(sb_id, pkt);
140
 
141
            add_crc(pkt);
142
            strip_crc(pkt);
143
            length = pkt->length + 4;
144
 
145
            //cout << "Transmit XGMII packet:\n" << * pkt << endl;
146
 
147
        }
148
 
149
 
150
        if (ifg != 0) {
151
            txd |= ((sc_uint<64>)0x07) << (8 * lane);
152
            txc |= 0x01 << lane;
153
            ifg--;
154
 
155
        }
156
        else if (fault_spacing_cnt != 0) {
157
 
158
            txd |= ((sc_uint<64>)0x07) << (8 * lane);
159
            txc |= 0x01 << lane;
160
 
161
            fault_spacing_cnt--;
162
 
163
        }
164
        else if ((lane == 0 || lane == 4) && fault_byte == 4) {
165
 
166
            txd |= ((sc_uint<64>)0x9c) << (8 * lane);
167
            txc |= 0x01 << lane;
168
 
169
            fault_byte--;
170
 
171
        }
172
        else if (fault_byte == 3 || fault_byte == 2) {
173
 
174
            fault_byte--;
175
 
176
        }
177
        else if (fault_byte == 1) {
178
 
179
            if (pkt->err_flags & PKT_FLAG_LOCAL_FAULT) {
180
                txd |= ((sc_uint<64>)0x01) << (8 * lane);
181
            }
182
            else {
183
                txd |= ((sc_uint<64>)0x02) << (8 * lane);
184
            }
185
            fault_byte--;
186
 
187
            fault_cnt--;
188
            if (fault_cnt > 0) {
189
                fault_byte = 4;
190
            }
191
 
192
            if (fault_cnt == 1) {
193
                fault_spacing_cnt = 4 * fault_spacing;
194
            }
195
        }
196
        else if ((lane == 0 || lane == 4) && bytecnt != length && preamblecnt == 0) {
197
 
198
            txd |= ((sc_uint<64>)0xfb) << (8 * lane);
199
            txc |= 0x01 << lane;
200
 
201
            preamblecnt++;
202
 
203
        }
204
        else if (preamblecnt > 0 && preamblecnt < 7) {
205
 
206
            txd |= ((sc_uint<64>)0x55) << (8 * lane);
207
 
208
            preamblecnt++;
209
 
210
        }
211
        else if (preamblecnt == 7) {
212
 
213
            txd |= ((sc_uint<64>)0xd5) << (8 * lane);
214
 
215
            preamblecnt++;
216
 
217
        }
218
        else if (preamblecnt > 7 && (bytecnt == (length-4)) &&
219
                 (pkt->err_flags & PKT_FLAG_ERR_FRG)) {
220
 
221
            //---
222
            // Fragment insertion
223
 
224
            bytecnt = 0;
225
            length = 0;
226
            preamblecnt = 0;
227
            ifg = 0;
228
 
229
        }
230
        else if (preamblecnt >7 && bytecnt == pkt->err_info &&
231
                 (pkt->err_flags & PKT_FLAG_ERR_CODING)) {
232
 
233
            //---
234
            // Coding error insertion
235
 
236
            txc |= 0x01 << lane;
237
            txd |= ((sc_uint<64>)pkt->data[bytecnt]) << (8 * lane);
238
            bytecnt++;
239
 
240
        }
241
        else if (preamblecnt > 7 && bytecnt < length) {
242
 
243
            txd |= ((sc_uint<64>)pkt->data[bytecnt]) << (8 * lane);
244
            bytecnt++;
245
 
246
        }
247
        else if (preamblecnt > 7 && bytecnt == length) {
248
 
249
            //---
250
            // End of frame TERMINATE
251
 
252
            txd |= ((sc_uint<64>)0xfd) << (8 * lane);
253
            txc |= 0x01 << lane;
254
 
255
            bytecnt = 0;
256
            length = 0;
257
            preamblecnt = 0;
258
 
259
            // Minimum IFG is 5 including TERMINATE
260
            ifg = 4;
261
 
262
        }
263
        else {
264
            txd |= ((sc_uint<64>)0x07) << (8 * lane);
265
            txc |= 0x01 << lane;
266
        }
267
        if (lane == 7) {
268
            xgmii_rxd = txd;
269
            xgmii_rxc = txc;
270
            txd = 0;
271
            txc = 0;
272
            wait();
273
        }
274
        lane = (lane + 1) % 8;
275
 
276
    }
277
};
278
 
279
 
280
void xgmii_if::receive() {
281
 
282
    packet_t* pkt;
283
 
284
    sc_uint<64> rxd;
285
    sc_uint<8> rxc;
286
 
287
    int lane, bytecnt, ifgcnt;
288
 
289
    lane = 0;
290
 
291
    wait();
292
 
293
    while (true) {
294
 
295
        ifgcnt = 1;
296
 
297
        rxd = xgmii_txd;
298
        rxc = xgmii_txc;
299
 
300
 
301
        //---
302
        // Wait for START code in lane0 or lane4
303
 
304
        while (true) {
305
 
306
            // Check for START character
307
            if (((rxd >> (8*lane)) & 0xff) == 0xfb && ((rxc >> lane) & 0x1) == 1) {
308
                if (disable_receive) {
309
                    cout << "INFO: XGMII Receive Disabled" << endl;
310
                }
311
                else {
312
                    break;
313
                }
314
            };
315
 
316
            // Check IDLE character and control lines
317
            if (((rxd >> (8*lane)) & 0xff) != 0x07 || ((rxc >> lane) & 0x1) != 1) {
318
                if (allow_idle_errors) {
319
                    cout << "INFO: IDLE check disabled" << endl;
320
                }
321
                else {
322
                    cout << "ERROR: IDLE character " << hex << rxd << " " << rxc << dec << lane << endl;
323
                    sc_stop();
324
                }
325
            };
326
 
327
            ifgcnt++;
328
 
329
            lane = (lane + 1) % 8;
330
            if (lane == 0) {
331
                wait();
332
                rxd = xgmii_txd;
333
                rxc = xgmii_txc;
334
            }
335
        }
336
 
337
        //cout << "START in lane " << lane << " IFG " << ifgcnt << endl;
338
 
339
        // Check starting lane
340
        if (lane != 0 && lane != 4) {
341
            cout << "ERROR: Lane aligment" << endl;
342
            sc_stop();
343
        }
344
 
345
        // Check for minimum inter frame gap
346
        if (ifgcnt < 9) {
347
            cout << "ERROR: MINIMUM IFG " << ifgcnt << endl;
348
            sc_stop();
349
        }
350
 
351
        //---
352
        // Capture data until end of frame is detected (TERMINATE)
353
 
354
        pkt = new(packet_t);
355
        pkt->ifg = ifgcnt;
356
        pkt->start_lane = lane;
357
        pkt->length = 0;
358
 
359
        bytecnt = 0;
360
        while (true) {
361
 
362
            // Look for end of frame delimiter in any lane
363
            if (((rxd >> (8*lane)) & 0xff) == 0xfd && ((rxc >> lane) & 0x1) == 1) {
364
                break;
365
            };
366
 
367
            // Stop if packet is too long
368
            if (bytecnt >=  10000) {
369
                break;
370
            }
371
 
372
            // Validate preamble bytes
373
            if (bytecnt > 0 && bytecnt <= 6 && ((rxd >> (8*lane)) & 0xff) != 0x55) {
374
                cout << "ERROR: Invalid preamble byte: " << bytecnt << endl;
375
                sc_stop();
376
            }
377
 
378
            // Validate SFD code in preamble
379
            if (bytecnt == 7 && ((rxd >> (8*lane)) & 0xff) != 0xd5) {
380
                cout << "ERROR: Invalid preamble byte: " << bytecnt << endl;
381
                sc_stop();
382
            }
383
 
384
            // Store all bytes after preamble
385
            if (bytecnt >  7) {
386
                if (((rxc >> lane) & 0x1) == 0) {
387
                    pkt->data[pkt->length] = ((rxd >> (8*lane)) & 0xff);
388
                    pkt->length++;
389
                }
390
                else {
391
                    cout << "ERROR: RXC high during data cycle" << endl;
392
                    sc_stop();
393
                }
394
            }
395
            else if (bytecnt > 0) {
396
                if (((rxc >> lane) & 0x1) == 1) {
397
                    cout << "ERROR: RXC high during preamble" << endl;
398
                    sc_stop();
399
                }
400
            }
401
 
402
            bytecnt++;
403
            lane = (lane + 1) % 8;
404
            if (lane == 0) {
405
                wait();
406
                rxd = xgmii_txd;
407
                rxc = xgmii_txc;
408
            }
409
        }
410
 
411
 
412
        lane = (lane + 1) % 8;
413
        if (lane == 0) {
414
            wait();
415
            rxd = xgmii_txd;
416
            rxc = xgmii_txc;
417
        }
418
 
419
        //---
420
        // Store packet
421
 
422
        strip_crc(pkt);
423
 
424
        unpack(pkt);
425
        //rx_fifo.write(pkt);
426
        //cout << "Received XGMII packet:" << * pkt << endl;
427
 
428
        //---
429
        // Pass packet to scoreboard
430
 
431
        sb->notify_packet_rx(sb_id, pkt);
432
 
433
    }
434
};
435
 
436
 
437
void xgmii_if::monitor() {
438
 
439
    sc_uint<64> rxd;
440
    sc_uint<8> rxc;
441
 
442
    wait();
443
 
444
    while (true) {
445
 
446
        rxd = xgmii_txd;
447
        rxc = xgmii_txc;
448
 
449
        //---
450
        // Check for local/remote fault
451
 
452
        if (((rxd & 0xffffffff) == 0x0100009c && (rxc & 0xf) == 0x1) &&
453
            (((rxd >> 32) & 0xffffffff) == 0x0100009c && ((rxc > 4) & 0xf) == 0x1)) {
454
 
455
            //--
456
            // Local fault detection
457
 
458
            if (!rx_local_fault) {
459
                cout << "XGMII Local Fault Asserted" << endl;
460
 
461
                // Notify Scoreboard
462
                sb->notify_status(sb_id, scoreboard::LOCAL_FAULT);
463
            }
464
            rx_local_fault = true;
465
 
466
        }
467
        else {
468
 
469
            if (rx_local_fault) {
470
                cout << "XGMII Local Fault De-Asserted" << endl;
471
            }
472
            rx_local_fault = false;
473
 
474
        }
475
 
476
        if (((rxd & 0xffffffff) == 0x0200009c && (rxc & 0xf) == 0x1) &&
477
            (((rxd >> 32) & 0xffffffff) == 0x0200009c && ((rxc > 4) & 0xf) == 0x1)) {
478
 
479
            //--
480
            // Remote fault detection
481
 
482
            if (!rx_remote_fault) {
483
                cout << "XGMII Remote Fault Asserted" << endl;
484
 
485
                // Notify Scoreboard
486
                sb->notify_status(sb_id, scoreboard::REMOTE_FAULT);
487
            }
488
            rx_remote_fault = true;
489
 
490
        }
491
        else {
492
 
493
            if (rx_remote_fault) {
494
                cout << "XGMII Remote Fault De-Asserted" << endl;
495
            }
496
            rx_remote_fault = false;
497
 
498
        }
499
 
500
        wait();
501
    }
502
};
503
 
504
 

powered by: WebSVN 2.1.0

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