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 29

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 29 antanguay
    inject_noise = false;
59 2 antanguay
}
60
 
61
void xgmii_if::connect_scoreboard(scoreboard *sbptr, scoreboard::sbSourceId sid) {
62
    sb = sbptr;
63
    sb_id = sid;
64
}
65
 
66
void xgmii_if::transmit() {
67
 
68
    packet_t* pkt;
69
 
70
    sc_uint<64> txd = 0;
71
    sc_uint<8> txc = 0;
72
 
73 29 antanguay
    int64_t noise [] = {0x1, 0xd5555555555555fb,
74
                        0x1, 0xd5555555555555fb,
75
                        0x1, 0xd5555555555555fc,
76
                        0x0, 0xd5555555555555fb,
77
                        0x1, 0xd5555555555555fb,
78
                        0x0, 0xd5555555555555fb,
79
                        0x1, 0x1111111111111111,
80
                        };
81
 
82 2 antanguay
    int lane = 0;
83
    int bytecnt = 0;
84
    int length = 0;
85
    int preamblecnt = 0;
86
    int ifg = 0;
87
    int fragment_size = 8;
88
    int coding_offset = 0;
89
    int fault_cnt = 0;
90
    int fault_byte = 0;
91
    int fault_spacing;
92
    int fault_spacing_cnt = 0;
93 29 antanguay
    int count = 0;
94
    int i = 0;
95 2 antanguay
 
96
    while (true) {
97
 
98
        if (length == 0 && tx_fifo.nb_read(pkt)) {
99
 
100
            if (!disable_padding) {
101
                pad(pkt, 60);
102
            }
103
            pack(pkt);
104
 
105
            calc_crc(pkt);
106
 
107
            //---
108
            // Inject errors
109 15 antanguay
 
110 2 antanguay
            if (pkt->err_flags & PKT_FLAG_ERR_CRC) {
111
                pkt->crc++;
112
            }
113
 
114
            if (pkt->err_flags & PKT_FLAG_ERR_FRG) {
115
                pkt->length = fragment_size;
116
                fragment_size++;
117
                if (fragment_size > 64) {
118
                    fragment_size = 8;
119
                }
120
            }
121
 
122
            if (pkt->err_flags & PKT_FLAG_ERR_CODING) {
123
                if (coding_offset >= pkt->length) {
124
                    pkt->err_info = pkt->length-1;
125
                }
126
                else {
127
                    pkt->err_info = coding_offset;
128
                }
129
                coding_offset++;
130
                if (coding_offset >= 70) {
131
                    coding_offset = 0;
132
                }
133
            }
134
 
135
            //---
136
            // Inject local / remote faults
137
 
138
            if (pkt->err_flags & PKT_FLAG_LOCAL_FAULT ||
139
                pkt->err_flags & PKT_FLAG_REMOTE_FAULT) {
140
                fault_cnt = 4;
141
                fault_byte = 4;
142
                fault_spacing_cnt = 0;
143
 
144
                fault_spacing = pkt->err_info;
145
                cout << "INFO: Fault insert, spacing: " << fault_spacing << endl;
146
            }
147
 
148
            //---
149
            // Pass packet to scoreboard
150
 
151
            sb->notify_packet_tx(sb_id, pkt);
152
 
153
            add_crc(pkt);
154
            strip_crc(pkt);
155
            length = pkt->length + 4;
156
 
157
            //cout << "Transmit XGMII packet:\n" << * pkt << endl;
158
 
159
        }
160
 
161
 
162
        if (ifg != 0) {
163
            txd |= ((sc_uint<64>)0x07) << (8 * lane);
164
            txc |= 0x01 << lane;
165
            ifg--;
166
 
167
        }
168
        else if (fault_spacing_cnt != 0) {
169
 
170
            txd |= ((sc_uint<64>)0x07) << (8 * lane);
171
            txc |= 0x01 << lane;
172
 
173
            fault_spacing_cnt--;
174
 
175
        }
176
        else if ((lane == 0 || lane == 4) && fault_byte == 4) {
177
 
178
            txd |= ((sc_uint<64>)0x9c) << (8 * lane);
179
            txc |= 0x01 << lane;
180
 
181
            fault_byte--;
182
 
183
        }
184
        else if (fault_byte == 3 || fault_byte == 2) {
185
 
186
            fault_byte--;
187
 
188
        }
189
        else if (fault_byte == 1) {
190
 
191
            if (pkt->err_flags & PKT_FLAG_LOCAL_FAULT) {
192
                txd |= ((sc_uint<64>)0x01) << (8 * lane);
193
            }
194
            else {
195
                txd |= ((sc_uint<64>)0x02) << (8 * lane);
196
            }
197
            fault_byte--;
198
 
199
            fault_cnt--;
200
            if (fault_cnt > 0) {
201
                fault_byte = 4;
202
            }
203
 
204
            if (fault_cnt == 1) {
205
                fault_spacing_cnt = 4 * fault_spacing;
206
            }
207
        }
208
        else if ((lane == 0 || lane == 4) && bytecnt != length && preamblecnt == 0) {
209
 
210
            txd |= ((sc_uint<64>)0xfb) << (8 * lane);
211
            txc |= 0x01 << lane;
212
 
213
            preamblecnt++;
214
 
215
        }
216
        else if (preamblecnt > 0 && preamblecnt < 7) {
217
 
218
            txd |= ((sc_uint<64>)0x55) << (8 * lane);
219
 
220
            preamblecnt++;
221
 
222
        }
223
        else if (preamblecnt == 7) {
224
 
225
            txd |= ((sc_uint<64>)0xd5) << (8 * lane);
226
 
227
            preamblecnt++;
228
 
229
        }
230
        else if (preamblecnt > 7 && (bytecnt == (length-4)) &&
231
                 (pkt->err_flags & PKT_FLAG_ERR_FRG)) {
232
 
233
            //---
234
            // Fragment insertion
235
 
236
            bytecnt = 0;
237
            length = 0;
238
            preamblecnt = 0;
239
            ifg = 0;
240
 
241
        }
242 15 antanguay
        else if (preamblecnt >7 && bytecnt == pkt->err_info &&
243 2 antanguay
                 (pkt->err_flags & PKT_FLAG_ERR_CODING)) {
244
 
245
            //---
246
            // Coding error insertion
247
 
248
            txc |= 0x01 << lane;
249
            txd |= ((sc_uint<64>)pkt->data[bytecnt]) << (8 * lane);
250
            bytecnt++;
251
 
252
        }
253
        else if (preamblecnt > 7 && bytecnt < length) {
254
 
255
            txd |= ((sc_uint<64>)pkt->data[bytecnt]) << (8 * lane);
256
            bytecnt++;
257
 
258
        }
259
        else if (preamblecnt > 7 && bytecnt == length) {
260
 
261
            //---
262
            // End of frame TERMINATE
263
 
264
            txd |= ((sc_uint<64>)0xfd) << (8 * lane);
265
            txc |= 0x01 << lane;
266
 
267
            bytecnt = 0;
268
            length = 0;
269
            preamblecnt = 0;
270
 
271
            // Minimum IFG is 5 including TERMINATE
272
            ifg = 4;
273
 
274
        }
275
        else {
276
            txd |= ((sc_uint<64>)0x07) << (8 * lane);
277
            txc |= 0x01 << lane;
278
        }
279 29 antanguay
        if (inject_noise) {
280
            for (count = 0; count < 10000; count += 2) {
281
                i = 2 * (random() % (sizeof(noise)/16));
282
                cout << "NOISE: " << hex << noise[i] << " " << noise[i+1] << dec << endl;
283
                xgmii_rxd = noise[i+1];
284
                xgmii_rxc = noise[i];
285
                txd = 0;
286
                txc = 0;
287
                wait();
288
            }
289
            inject_noise = false;
290
        }
291
        else if (lane == 7) {
292 2 antanguay
            xgmii_rxd = txd;
293
            xgmii_rxc = txc;
294
            txd = 0;
295
            txc = 0;
296
            wait();
297
        }
298
        lane = (lane + 1) % 8;
299
 
300
    }
301
};
302
 
303
 
304
void xgmii_if::receive() {
305
 
306
    packet_t* pkt;
307
 
308
    sc_uint<64> rxd;
309
    sc_uint<8> rxc;
310
 
311
    int lane, bytecnt, ifgcnt;
312
 
313
    lane = 0;
314
 
315
    wait();
316
 
317
    while (true) {
318
 
319
        ifgcnt = 1;
320
 
321
        rxd = xgmii_txd;
322
        rxc = xgmii_txc;
323
 
324
 
325
        //---
326
        // Wait for START code in lane0 or lane4
327
 
328
        while (true) {
329
 
330
            // Check for START character
331
            if (((rxd >> (8*lane)) & 0xff) == 0xfb && ((rxc >> lane) & 0x1) == 1) {
332
                if (disable_receive) {
333
                    cout << "INFO: XGMII Receive Disabled" << endl;
334
                }
335
                else {
336
                    break;
337
                }
338
            };
339
 
340
            // Check IDLE character and control lines
341
            if (((rxd >> (8*lane)) & 0xff) != 0x07 || ((rxc >> lane) & 0x1) != 1) {
342
                if (allow_idle_errors) {
343
                    cout << "INFO: IDLE check disabled" << endl;
344
                }
345
                else {
346
                    cout << "ERROR: IDLE character " << hex << rxd << " " << rxc << dec << lane << endl;
347
                    sc_stop();
348
                }
349
            };
350
 
351
            ifgcnt++;
352
 
353
            lane = (lane + 1) % 8;
354
            if (lane == 0) {
355
                wait();
356
                rxd = xgmii_txd;
357
                rxc = xgmii_txc;
358
            }
359
        }
360
 
361
        //cout << "START in lane " << lane << " IFG " << ifgcnt << endl;
362
 
363
        // Check starting lane
364
        if (lane != 0 && lane != 4) {
365
            cout << "ERROR: Lane aligment" << endl;
366
            sc_stop();
367
        }
368
 
369
        // Check for minimum inter frame gap
370
        if (ifgcnt < 9) {
371
            cout << "ERROR: MINIMUM IFG " << ifgcnt << endl;
372
            sc_stop();
373
        }
374
 
375
        //---
376
        // Capture data until end of frame is detected (TERMINATE)
377
 
378
        pkt = new(packet_t);
379
        pkt->ifg = ifgcnt;
380
        pkt->start_lane = lane;
381
        pkt->length = 0;
382
 
383
        bytecnt = 0;
384
        while (true) {
385
 
386
            // Look for end of frame delimiter in any lane
387
            if (((rxd >> (8*lane)) & 0xff) == 0xfd && ((rxc >> lane) & 0x1) == 1) {
388
                break;
389
            };
390
 
391
            // Stop if packet is too long
392
            if (bytecnt >=  10000) {
393
                break;
394
            }
395
 
396
            // Validate preamble bytes
397
            if (bytecnt > 0 && bytecnt <= 6 && ((rxd >> (8*lane)) & 0xff) != 0x55) {
398
                cout << "ERROR: Invalid preamble byte: " << bytecnt << endl;
399
                sc_stop();
400
            }
401
 
402
            // Validate SFD code in preamble
403
            if (bytecnt == 7 && ((rxd >> (8*lane)) & 0xff) != 0xd5) {
404
                cout << "ERROR: Invalid preamble byte: " << bytecnt << endl;
405
                sc_stop();
406
            }
407
 
408
            // Store all bytes after preamble
409
            if (bytecnt >  7) {
410
                if (((rxc >> lane) & 0x1) == 0) {
411
                    pkt->data[pkt->length] = ((rxd >> (8*lane)) & 0xff);
412
                    pkt->length++;
413
                }
414
                else {
415
                    cout << "ERROR: RXC high during data cycle" << endl;
416
                    sc_stop();
417
                }
418
            }
419
            else if (bytecnt > 0) {
420
                if (((rxc >> lane) & 0x1) == 1) {
421
                    cout << "ERROR: RXC high during preamble" << endl;
422
                    sc_stop();
423
                }
424
            }
425
 
426
            bytecnt++;
427
            lane = (lane + 1) % 8;
428
            if (lane == 0) {
429
                wait();
430
                rxd = xgmii_txd;
431
                rxc = xgmii_txc;
432
            }
433
        }
434
 
435
 
436
        lane = (lane + 1) % 8;
437
        if (lane == 0) {
438
            wait();
439
            rxd = xgmii_txd;
440
            rxc = xgmii_txc;
441
        }
442
 
443
        //---
444
        // Store packet
445
 
446
        strip_crc(pkt);
447
 
448
        unpack(pkt);
449
        //rx_fifo.write(pkt);
450
        //cout << "Received XGMII packet:" << * pkt << endl;
451
 
452
        //---
453
        // Pass packet to scoreboard
454
 
455
        sb->notify_packet_rx(sb_id, pkt);
456
 
457
    }
458
};
459
 
460
 
461
void xgmii_if::monitor() {
462
 
463
    sc_uint<64> rxd;
464
    sc_uint<8> rxc;
465
 
466
    wait();
467
 
468
    while (true) {
469
 
470
        rxd = xgmii_txd;
471
        rxc = xgmii_txc;
472
 
473
        //---
474
        // Check for local/remote fault
475
 
476
        if (((rxd & 0xffffffff) == 0x0100009c && (rxc & 0xf) == 0x1) &&
477
            (((rxd >> 32) & 0xffffffff) == 0x0100009c && ((rxc > 4) & 0xf) == 0x1)) {
478 15 antanguay
 
479 2 antanguay
            //--
480
            // Local fault detection
481
 
482
            if (!rx_local_fault) {
483
                cout << "XGMII Local Fault Asserted" << endl;
484
 
485
                // Notify Scoreboard
486
                sb->notify_status(sb_id, scoreboard::LOCAL_FAULT);
487
            }
488
            rx_local_fault = true;
489
 
490
        }
491
        else {
492
 
493
            if (rx_local_fault) {
494
                cout << "XGMII Local Fault De-Asserted" << endl;
495
            }
496
            rx_local_fault = false;
497
 
498
        }
499
 
500
        if (((rxd & 0xffffffff) == 0x0200009c && (rxc & 0xf) == 0x1) &&
501
            (((rxd >> 32) & 0xffffffff) == 0x0200009c && ((rxc > 4) & 0xf) == 0x1)) {
502
 
503
            //--
504
            // Remote fault detection
505
 
506
            if (!rx_remote_fault) {
507
                cout << "XGMII Remote Fault Asserted" << endl;
508
 
509
                // Notify Scoreboard
510
                sb->notify_status(sb_id, scoreboard::REMOTE_FAULT);
511
            }
512
            rx_remote_fault = true;
513
 
514
        }
515
        else {
516
 
517
            if (rx_remote_fault) {
518
                cout << "XGMII Remote Fault De-Asserted" << endl;
519
            }
520
            rx_remote_fault = false;
521
 
522
        }
523
 
524
        wait();
525
    }
526
};

powered by: WebSVN 2.1.0

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