//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// File name "sc_pkt_if.cpp" ////
|
//// File name "sc_pkt_if.cpp" ////
|
//// ////
|
//// ////
|
//// This file is part of the "10GE MAC" project ////
|
//// This file is part of the "10GE MAC" project ////
|
//// http://www.opencores.org/cores/xge_mac/ ////
|
//// http://www.opencores.org/cores/xge_mac/ ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// - A. Tanguay (antanguay@opencores.org) ////
|
//// - A. Tanguay (antanguay@opencores.org) ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2008 AUTHORS. All rights reserved. ////
|
//// Copyright (C) 2008 AUTHORS. All rights reserved. ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <iostream>
|
#include <iostream>
|
#include <sys/times.h>
|
#include <sys/times.h>
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
|
|
#include "systemc.h"
|
#include "systemc.h"
|
|
|
#include "sc_pkt_if.h"
|
#include "sc_pkt_if.h"
|
|
|
sc_fifo<packet_t*> * pkt_if::get_tx_fifo_ptr() {
|
sc_fifo<packet_t*> * pkt_if::get_tx_fifo_ptr() {
|
return &tx_fifo;
|
return &tx_fifo;
|
}
|
}
|
|
|
sc_fifo<packet_t*> * pkt_if::get_rx_fifo_ptr() {
|
sc_fifo<packet_t*> * pkt_if::get_rx_fifo_ptr() {
|
return &rx_fifo;
|
return &rx_fifo;
|
}
|
}
|
|
|
void pkt_if::init(void) {
|
void pkt_if::init(void) {
|
disable_rx = false;
|
disable_rx = false;
|
allow_rx_sop_err = false;
|
allow_rx_sop_err = false;
|
}
|
}
|
|
|
void pkt_if::connect_scoreboard(scoreboard *sbptr, scoreboard::sbSourceId sid) {
|
void pkt_if::connect_scoreboard(scoreboard *sbptr, scoreboard::sbSourceId sid) {
|
sb = sbptr;
|
sb = sbptr;
|
sb_id = sid;
|
sb_id = sid;
|
}
|
}
|
|
|
void pkt_if::transmit() {
|
void pkt_if::transmit() {
|
|
|
packet_t* pkt;
|
packet_t* pkt;
|
|
|
while (true) {
|
while (true) {
|
|
|
wait();
|
wait();
|
|
|
if (tx_fifo.nb_read(pkt)) {
|
if (tx_fifo.nb_read(pkt)) {
|
|
|
pack(pkt);
|
pack(pkt);
|
|
|
//cout << "Transmit PKT_IF packet:\n" << * pkt << endl;
|
//cout << "Transmit PKT_IF packet:\n" << * pkt << endl;
|
|
|
pkt_tx_val = 1;
|
pkt_tx_val = 1;
|
|
|
for (int i = 0; i < pkt->length; i += 8) {
|
for (int i = 0; i < pkt->length; i += 8) {
|
|
|
pkt_tx_data = pkt->data[i+7] << 56 |
|
pkt_tx_data = pkt->data[i] << 56 |
|
pkt->data[i+6] << 48 |
|
pkt->data[i+1] << 48 |
|
pkt->data[i+5] << 40 |
|
pkt->data[i+2] << 40 |
|
pkt->data[i+4] << 32 |
|
pkt->data[i+3] << 32 |
|
pkt->data[i+3] << 24 |
|
pkt->data[i+4] << 24 |
|
pkt->data[i+2] << 16 |
|
pkt->data[i+5] << 16 |
|
pkt->data[i+1] << 8 |
|
pkt->data[i+6] << 8 |
|
pkt->data[i];
|
pkt->data[i+7];
|
|
|
if (i == 0) {
|
if (i == 0) {
|
pkt_tx_sop = 1;
|
pkt_tx_sop = 1;
|
}
|
}
|
else {
|
else {
|
pkt_tx_sop = 0;
|
pkt_tx_sop = 0;
|
}
|
}
|
|
|
if (i + 8 >= pkt->length) {
|
if (i + 8 >= pkt->length) {
|
pkt_tx_eop = 1;
|
pkt_tx_eop = 1;
|
pkt_tx_mod = pkt->length % 8;
|
pkt_tx_mod = pkt->length % 8;
|
}
|
}
|
else {
|
else {
|
pkt_tx_eop = 0;
|
pkt_tx_eop = 0;
|
}
|
}
|
|
|
wait();
|
wait();
|
}
|
}
|
|
|
pkt_tx_val = 0;
|
pkt_tx_val = 0;
|
|
|
|
|
//---
|
//---
|
// Pass packet to scoreboard
|
// Pass packet to scoreboard
|
|
|
sb->notify_packet_tx(sb_id, pkt);
|
sb->notify_packet_tx(sb_id, pkt);
|
|
|
//---
|
//---
|
// Enforce minimum spacing between SOP's
|
// Enforce minimum spacing between SOP's
|
|
|
for (int i = (pkt->length+7)/8; i < 8; i++) {
|
for (int i = (pkt->length+7)/8; i < 8; i++) {
|
wait();
|
wait();
|
}
|
}
|
}
|
}
|
}
|
}
|
};
|
};
|
|
|
|
|
void pkt_if::receive() {
|
void pkt_if::receive() {
|
|
|
packet_t* pkt;
|
packet_t* pkt;
|
|
|
sc_uint<64> data;
|
sc_uint<64> data;
|
|
|
wait();
|
wait();
|
|
|
while (true) {
|
while (true) {
|
|
|
if (pkt_rx_avail && !disable_rx) {
|
if (pkt_rx_avail && !disable_rx) {
|
|
|
pkt = new(packet_t);
|
pkt = new(packet_t);
|
pkt->length = 0;
|
pkt->length = 0;
|
|
|
// If reading already selected just keep going,
|
// If reading already selected just keep going,
|
// if not we must enable ren
|
// if not we must enable ren
|
if (!pkt_rx_ren) {
|
if (!pkt_rx_ren) {
|
pkt_rx_ren = 1;
|
pkt_rx_ren = 1;
|
wait();
|
wait();
|
};
|
};
|
|
|
while (true) {
|
while (true) {
|
|
|
wait();
|
wait();
|
|
|
if (!pkt_rx_val) {
|
if (!pkt_rx_val) {
|
continue;
|
continue;
|
}
|
}
|
|
|
// Check SOP
|
// Check SOP
|
|
|
if (pkt->length != 0 && pkt_rx_sop) {
|
if (pkt->length != 0 && pkt_rx_sop) {
|
if (allow_rx_sop_err) {
|
if (allow_rx_sop_err) {
|
cout << "INFO: SOP errors allowed" << endl;
|
cout << "INFO: SOP errors allowed" << endl;
|
pkt->length = 0;
|
pkt->length = 0;
|
pkt->err_flags = 0;
|
pkt->err_flags = 0;
|
}
|
}
|
else {
|
else {
|
pkt->err_flags |= PKT_FLAG_ERR_SOP;
|
pkt->err_flags |= PKT_FLAG_ERR_SOP;
|
}
|
}
|
}
|
}
|
|
|
// Check error line
|
// Check error line
|
|
|
if (pkt_rx_err) {
|
if (pkt_rx_err) {
|
pkt->err_flags |= PKT_FLAG_ERR_SIG;
|
pkt->err_flags |= PKT_FLAG_ERR_SIG;
|
}
|
}
|
|
|
// Capture data
|
// Capture data
|
|
|
data = pkt_rx_data;
|
data = pkt_rx_data;
|
|
|
for (int lane = 0; lane < 8; lane++) {
|
for (int lane = 0; lane < 8; lane++) {
|
|
|
pkt->data[pkt->length++] = (data >> (8 * lane)) & 0xff;
|
pkt->data[pkt->length++] = (data >> (8 * (7-lane))) & 0xff;
|
|
|
if (pkt->length >= 10000) {
|
if (pkt->length >= 10000) {
|
cout << "ERROR: Packet too long" << endl;
|
cout << "ERROR: Packet too long" << endl;
|
sc_stop();
|
sc_stop();
|
}
|
}
|
|
|
if (pkt_rx_eop && (pkt_rx_mod == ((lane+1) % 8))) {
|
if (pkt_rx_eop && (pkt_rx_mod == ((lane+1) % 8))) {
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
// Stop on EOP
|
// Stop on EOP
|
|
|
if (pkt_rx_eop) {
|
if (pkt_rx_eop) {
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
//---
|
//---
|
// Store packet
|
// Store packet
|
|
|
unpack(pkt);
|
unpack(pkt);
|
//rx_fifo.write(pkt);
|
//rx_fifo.write(pkt);
|
|
|
//cout << "Receive PKT_IF packet:\n" << * pkt << endl;
|
//cout << "Receive PKT_IF packet:\n" << * pkt << endl;
|
|
|
//---
|
//---
|
// Pass packet to scoreboard
|
// Pass packet to scoreboard
|
|
|
sb->notify_packet_rx(sb_id, pkt);
|
sb->notify_packet_rx(sb_id, pkt);
|
|
|
}
|
}
|
else {
|
else {
|
pkt_rx_ren = 0;
|
pkt_rx_ren = 0;
|
wait();
|
wait();
|
}
|
}
|
}
|
}
|
};
|
};
|
|
|