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

Subversion Repositories xge_mac

[/] [xge_mac/] [trunk/] [tbench/] [systemc/] [sc_scoreboard.cpp] - Rev 26

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

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  File name "sc_scoreboard.cpp"                               ////
////                                                              ////
////  This file is part of the "10GE MAC" project                 ////
////  http://www.opencores.org/cores/xge_mac/                     ////
////                                                              ////
////  Author(s):                                                  ////
////      - A. Tanguay (antanguay@opencores.org)                  ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2008 AUTHORS. All rights reserved.             ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
#include <stdio.h>
#include <iostream>
#include <sys/times.h>
#include <sys/stat.h>
 
#include "systemc.h"
 
#include "sc_scoreboard.h"
 
 
void scoreboard::init(void) {
    disable_padding = false;
    disable_crc_check = false;
    disable_packet_check = false;
    disable_flags_check = false;
    disable_signal_check = false;
}
 
void scoreboard::notify_packet_tx(sbSourceId sid, packet_t* pkt) {
 
    //---
    // Save packet to a fifo
 
    if (sid == SB_PIF_ID) {
        cout << "SCOREBOARD PACKET INTERFACE TX (" 
             << pkt->length << ")" << endl;
 
        //---
        // Store packet in scoreboard
 
        pif_fifo.write(pkt);
        pif_stats.tx_pkt_cnt++;
 
    }
 
    if (sid == SB_XGM_ID) {
 
        cout << "SCOREBOARD XGMII INTERFACE TX (" 
             << pkt->length << ")" << endl;
 
        //---
        // Store packet in scoreboard
 
        if (sid == SB_XGM_ID && (pkt->dest_addr & 0xffff) == 0x000001 &&
            ((pkt->dest_addr >> 24) & 0xffffff) == 0x0180c2) {
 
            // Pause frames will be dropped
            cout << "SCOREBOARD PAUSE INJECTED" << endl;
            xgm_stats.inject_pause_frame_cnt++;
 
        }
        else {
 
            xgm_fifo.write(pkt);
            xgm_stats.tx_pkt_cnt++;
 
        }
 
    }
 
    //---
    // Update stats
 
    if (sid == SB_XGM_ID && pkt->err_flags & PKT_FLAG_ERR_CODING) {
        xgm_stats.crc_error_cnt++;
    }
 
    if (sid == SB_XGM_ID && pkt->err_flags & PKT_FLAG_LOCAL_FAULT) {
        // If less than 4 faults in 128 columns, it will not be detected
        if (pkt->err_info <= (128 - 4)) {
            xgm_stats.inject_local_fault_cnt++;
        }
    }
 
    if (sid == SB_XGM_ID && pkt->err_flags & PKT_FLAG_REMOTE_FAULT) {
        // If less than 4 faults in 128 columns, it will not be detected
        if (pkt->err_info <= (128 - 4)) {
            xgm_stats.inject_remote_fault_cnt++;
        }
    }
 
    //cout << *pkt << endl;
}
 
void scoreboard::notify_packet_rx(sbSourceId sid, packet_t* pkt) {
 
    sbStats_t* stats;
 
    packet_t* pkt_tx;
    bool status;
 
    //---
    // Read matching packet from fifo
 
    if (sid == SB_PIF_ID) {
        status = xgm_fifo.nb_read(pkt_tx);
        if (status) {
            cout << "SCOREBOARD PACKET INTERFACE RX (TX SIZE=" 
                 << pkt_tx->length << "  RX SIZE="
                 << pkt->length << ")" << endl;
        }
    }
 
    if (sid == SB_XGM_ID) {
        status = pif_fifo.nb_read(pkt_tx);
        if (status) {
            cout << "SCOREBOARD XGMII INTERFACE RX (TX SIZE="
                 << pkt_tx->length << "  RX SIZE="
                 << pkt->length << ")" << endl;
        }
    }
 
    if (!status) {
        cout << "ERROR: FIFO EMPTY" << endl;
        sc_stop();
    }
 
    //---
    // Update stats
 
    if (sid == SB_PIF_ID) {
        stats = &pif_stats;
    }
 
    if (sid == SB_XGM_ID) {
        stats = &xgm_stats;
    }
 
    stats->rx_pkt_cnt++;
 
    if (stats->timestamp_first_pkt == 0) {
        stats->timestamp_first_pkt = sc_simulation_time();
    }
 
    stats->timestamp_last_pkt = sc_simulation_time();
 
    //---
    // Pad packet if it expected to be padded by MAC
 
    if (sid == SB_XGM_ID && !disable_padding) {
        pad(pkt_tx, 60);
    }
 
    //---
    // Calculate CRC
 
    calc_crc(pkt_tx);
    calc_crc(pkt);
 
    //cout << *pkt_tx << *pkt << endl;
 
    //---
    // Compare TX and RX packets
 
    if (disable_packet_check) {
 
        cout << "INFO: Packet check disabled" << endl;
 
    }
    else if ((pkt_tx->err_flags & PKT_FLAG_ERR_FRG) &&
             (pkt->err_flags |= PKT_FLAG_ERR_SIG)) {
 
        cout << "INFO: Fragment detected" << endl;
 
    }
    else if ((pkt_tx->err_flags & PKT_FLAG_ERR_CODING) &&
             (pkt->err_flags |= PKT_FLAG_ERR_SIG)) {
 
        cout << "INFO: Coding error detected:" << pkt_tx->err_info << endl;
 
    }
    else if ((sid == SB_PIF_ID || pkt->crc == pkt->crc_rx || disable_crc_check) &&
             compare(pkt_tx, pkt)) {
 
        //cout << "GOOD: Packets are matching" << endl;
 
    }
    else {
 
        cout << "ERROR: Packets don't match or bad CRC" << endl;
 
        cout << "<<<" << endl;
        cout << *pkt_tx << endl;
        cout << *pkt << endl;
        cout << ">>>" << endl;
 
        sc_stop();
 
    }
 
    //---
    // Check IFG against predicted IFG
 
    if (sid == SB_XGM_ID) {
 
        cout << "PKTMOD " << pkt->length % 4 \
             << " LANE " << pkt->start_lane \
             << " DIC " << stats->deficit_idle_count \
             << " IFGLEN " << stats->next_ifg_length  << endl;
 
        if (pkt->ifg < 1000 && stats->next_ifg_length != 1000) {
            if (pkt->ifg != stats->next_ifg_length) {
                cout << "ERROR: DIC IFG " << pkt->ifg                   \
                     << " Predicted: " << stats->next_ifg_length << endl;
                sc_stop();
            }
        }
 
    }
 
    //---
    // Update deficit idle count and predict IFG
 
    if (sid == SB_XGM_ID) {
 
        stats->next_ifg_length = 12 - (pkt->length % 4);
        stats->deficit_idle_count += (pkt->length % 4);
        if (stats->deficit_idle_count > 3) {
            stats->next_ifg_length += 4;
            stats->deficit_idle_count = stats->deficit_idle_count % 4;
        }
    }
 
    //---
    // Check error flags
 
    // CRC ERRORS
 
    if (sid == SB_PIF_ID && (pkt_tx->err_flags & PKT_FLAG_ERR_CRC)) {
 
        if (pkt->err_flags & PKT_FLAG_ERR_SIG) {
 
            cout << "SCOREBOARD CRC ERROR CHECKED" << endl;
            pif_stats.crc_error_cnt++;
 
            if (cpu_stats.crc_error_cnt+1 < pif_stats.crc_error_cnt) {
                cout << "ERROR: CRC error not reported to cpu" << endl;
                sc_stop();
            }
        }
        else {
            cout << "ERROR: CRC error not detected: " << hex << pkt->err_flags << dec << endl;
            sc_stop();
        }
 
        pkt->err_flags &= ~PKT_FLAG_ERR_SIG;
    }
 
 
    // FRAGMENT ERRORS
 
    if (sid == SB_PIF_ID && (pkt_tx->err_flags & PKT_FLAG_ERR_FRG)) {
 
        if (pkt->err_flags & PKT_FLAG_ERR_SIG) {
 
            cout << "SCOREBOARD FRAGMENT ERROR CHECKED" << endl;
            pif_stats.fragment_error_cnt++;
 
            if ((cpu_stats.fragment_error_cnt + cpu_stats.crc_error_cnt + 1)
                < pif_stats.fragment_error_cnt) {
                cout << "ERROR: FRAGMENT error not reported to cpu" << endl;
                sc_stop();
            }
        }
        else {
            cout << "ERROR: FRAGMENT error not detected: "
                 << hex << pkt->err_flags << dec << endl;
            sc_stop();
        }
 
        pkt->err_flags &= ~PKT_FLAG_ERR_SIG;
    }
 
 
    // CODING ERRORS
 
    if (sid == SB_PIF_ID && (pkt_tx->err_flags & PKT_FLAG_ERR_CODING)) {
 
        if (pkt->err_flags & PKT_FLAG_ERR_SIG) {
 
            cout << "SCOREBOARD CODING ERROR CHECKED" << endl;
 
            if (cpu_stats.crc_error_cnt+1 < xgm_stats.crc_error_cnt) {
                cout << "CPU Count: " << cpu_stats.crc_error_cnt <<
                    " XGM Count: " << xgm_stats.crc_error_cnt << endl;
                cout << "ERROR: CODING error not reported to cpu" << endl;
                sc_stop();
            }
        }
        else {
            cout << "ERROR: CODING error not detected: "
                 << hex << pkt->err_flags << dec << endl;
            sc_stop();
        }
 
        pkt->err_flags &= ~PKT_FLAG_ERR_SIG;
    }
 
 
    if (pkt->err_flags != 0) {
        stats->flags_error_cnt++;
        if (!disable_flags_check) {
            cout << "ERROR: Error flags set: " << hex << pkt->err_flags << dec << endl;
            sc_stop();
        }
        else {
            cout << "INFO: Error flags set: " << hex << pkt->err_flags << dec << endl;
        }
    }
 
    //---
    // Delete packets
 
    delete(pkt_tx);
    delete(pkt);
}
 
void scoreboard::notify_status(sbSourceId sid, sbStatusId statusId) {
 
    //---
    // Detect errors
 
    if (sid == SB_CPU_ID && statusId == CRC_ERROR) {
        cout << "SCOREBOARD CRC_ERROR SIGNAL" << endl;
        cpu_stats.crc_error_cnt++;
    }
 
    if (sid == SB_CPU_ID && statusId == FRAGMENT_ERROR) {
        cout << "SCOREBOARD FRAGMENT_ERROR SIGNAL" << endl;
        cpu_stats.fragment_error_cnt++;
    }
 
    if (sid == SB_CPU_ID && statusId == LOCAL_FAULT) {
        cout << "SCOREBOARD LOCAL_FAULT SIGNAL" << endl;
        cpu_stats.local_fault_cnt++;
 
        if (cpu_stats.local_fault_cnt != xgm_stats.inject_local_fault_cnt) {
            cout << "ERROR: Local fault not reported to cpu "
                 << cpu_stats.local_fault_cnt << " "
                 << xgm_stats.inject_local_fault_cnt << endl;
            sc_stop();
        }
 
        if (cpu_stats.local_fault_cnt != xgm_stats.detect_remote_fault_cnt) {
            cout << "ERROR: Remote fault not detected "
                 << cpu_stats.local_fault_cnt << " "
                 << xgm_stats.detect_remote_fault_cnt << endl;
            sc_stop();
        }
    }
 
    if (sid == SB_CPU_ID && statusId == REMOTE_FAULT) {
        cout << "SCOREBOARD REMOTE_FAULT SIGNAL" << endl;
        cpu_stats.remote_fault_cnt++;
 
        if (cpu_stats.remote_fault_cnt != xgm_stats.inject_remote_fault_cnt) {
            cout << "ERROR: Remote fault not reported to cpu "
                 << cpu_stats.remote_fault_cnt << " "
                 << xgm_stats.inject_remote_fault_cnt << endl;
            sc_stop();
        }
 
    }
 
    if (sid == SB_CPU_ID && statusId == RXD_FIFO_OVFLOW) {
        cout << "SCOREBOARD RXD_FIFO_OVFLOW SIGNAL" << endl;
        cpu_stats.rxd_fifo_ovflow_cnt++;
    }
 
    if (sid == SB_CPU_ID && statusId == RXD_FIFO_UDFLOW) {
        cout << "SCOREBOARD RXD_FIFO_UDFLOW SIGNAL" << endl;
        cpu_stats.rxd_fifo_udflow_cnt++;
    }
 
    if (sid == SB_CPU_ID && statusId == TXD_FIFO_OVFLOW) {
        cout << "SCOREBOARD TXD_FIFO_OVFLOW SIGNAL" << endl;
        cpu_stats.txd_fifo_ovflow_cnt++;
    }
 
    if (sid == SB_CPU_ID && statusId == TXD_FIFO_UDFLOW) {
        cout << "SCOREBOARD TXD_FIFO_UDFLOW SIGNAL" << endl;
        cpu_stats.txd_fifo_udflow_cnt++;
    }
 
    //---
    // Detect XGMII local/remote faults
 
    if (sid == SB_XGM_ID && statusId == LOCAL_FAULT) {
        cout << "SCOREBOARD RX LOCAL FAULT" << endl;
        xgm_stats.detect_local_fault_cnt++;
        sc_stop();
    }
 
    if (sid == SB_XGM_ID && statusId == REMOTE_FAULT) {
        cout << "SCOREBOARD RX REMOTE FAULT" << endl;
        xgm_stats.detect_remote_fault_cnt++;
    }
 
    //---
    // Packet receive indication
 
    if (sid == SB_CPU_ID && statusId == RX_GOOD_PAUSE_FRAME) {
        cout << "SCOREBOARD RX GOOD PAUSE FRAME SIGNAL" << endl;
        cpu_stats.rx_pause_frame_cnt++;
 
        if (cpu_stats.rx_pause_frame_cnt != xgm_stats.inject_pause_frame_cnt) {
            cout << "ERROR: Pause frame not reported "
                 << cpu_stats.rx_pause_frame_cnt << " "
                 << xgm_stats.inject_pause_frame_cnt << endl;
            sc_stop();
        }
    }
 
 
    if (!disable_signal_check) {
        cout << "ERROR: Signal Active" << endl;
        sc_stop();
    }
}
 
sbStats_t* scoreboard::get_pif_stats(void) {
    return &pif_stats;
}
 
sbStats_t* scoreboard::get_xgm_stats(void) {
    return &xgm_stats;
}
 
sbCpuStats_t* scoreboard::get_cpu_stats(void) {
    return &cpu_stats;
}
 
void scoreboard::clear_stats(void) {
 
    //---
    // Clear FIFOs
 
    while (pif_fifo.num_available() != 0) {
        delete(pif_fifo.read());
    }
 
    while (xgm_fifo.num_available() != 0) {
        delete(xgm_fifo.read());
    }
 
    //---
    // Clear stats
 
    pif_stats.tx_pkt_cnt = 0;
    pif_stats.rx_pkt_cnt = 0;
    pif_stats.crc_error_cnt = 0;
    pif_stats.flags_error_cnt = 0;
 
    xgm_stats.tx_pkt_cnt = 0;
    xgm_stats.rx_pkt_cnt = 0;
    xgm_stats.crc_error_cnt = 0;
    xgm_stats.flags_error_cnt = 0;
 
    pif_stats.timestamp_first_pkt = 0;
    pif_stats.timestamp_last_pkt = 0;
 
    xgm_stats.timestamp_first_pkt = 0;
    xgm_stats.timestamp_last_pkt = 0;
 
    xgm_stats.next_ifg_length = 1000;
    xgm_stats.deficit_idle_count = 0;
 
    cpu_stats.crc_error_cnt = 0;
    cpu_stats.fragment_error_cnt = 0;
    cpu_stats.rxd_fifo_ovflow_cnt = 0;
    cpu_stats.rxd_fifo_udflow_cnt = 0;
    cpu_stats.txd_fifo_ovflow_cnt = 0;
    cpu_stats.txd_fifo_udflow_cnt = 0;
}
 

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

powered by: WebSVN 2.1.0

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