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

Subversion Repositories openhmc

[/] [openhmc/] [trunk/] [openHMC/] [sim/] [tb/] [common/] [src/] [bfm_2_hmc_monitor.sv] - Rev 15

Compare with Previous | Blame | View Log

/*
 *                              .--------------. .----------------. .------------.
 *                             | .------------. | .--------------. | .----------. |
 *                             | | ____  ____ | | | ____    ____ | | |   ______ | |
 *                             | ||_   ||   _|| | ||_   \  /   _|| | | .' ___  || |
 *       ___  _ __   ___ _ __  | |  | |__| |  | | |  |   \/   |  | | |/ .'   \_|| |
 *      / _ \| '_ \ / _ \ '_ \ | |  |  __  |  | | |  | |\  /| |  | | || |       | |
 *       (_) | |_) |  __/ | | || | _| |  | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
 *      \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
 *           | |               | |            | | |              | | |          | |
 *           |_|               | '------------' | '--------------' | '----------' |
 *                              '--------------' '----------------' '------------'
 *
 *  openHMC - An Open Source Hybrid Memory Cube Controller
 *  (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
 *  www.ziti.uni-heidelberg.de
 *  B6, 26
 *  68159 Mannheim
 *  Germany
 *
 *  Contact: openhmc@ziti.uni-heidelberg.de
 *  http://ra.ziti.uni-heidelberg.de/openhmc
 *
 *   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 3 of the License, or
 *   (at your option) any later version.
 *
 *   This source file 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 file.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 */

`ifndef BFM_2_HMC
`define BFM_2_HMC
class bfm_2_hmc_mon extends hmc_module_mon;
        
        typedef enum {
         LENGTH_ERROR,
         CRC_ERROR,
         SEQ_ERROR,
         POISON
        }error_class_e;

        mailbox#(cls_pkt) in_mb;
        cls_pkt pkt;
        
        bit [2:0] seq_number = 0;
        
        bit bitstream[];
        
        int phit_size = 64;
        bit [64:0] header;      //-- phit size
        bit [64:0] tail  ;      //-- phit size
        int data_phit_count;
        
        int flit_size = 128;
        
        bit error_abort_mode = 0;
        int irtry_cnt = 0;
        
        int irtry = 0;
        
        
        hmc_link_config link_cfg;
        
        error_class_e current_error;
        hmc_command_encoding current_command;


        int lng_error = 0;
        int crc_error = 0;
        int seq_error = 0;
        int poisoned_pkt =0;
        
        int rsp_rcvd = 0;
        int err_rsp_rcvd = 0;
        int req_rcvd = 0;
        
        hmc_link_config hmc_link_cfg;
        
        `uvm_component_utils_begin(bfm_2_hmc_mon)
                `uvm_field_object(link_cfg, UVM_DEFAULT)
        `uvm_component_utils_end
                covergroup hmc_pkt_error_cg;
                option.per_instance = 1;
                ERROR_TYPE: coverpoint current_error;

                HMC_COMMAND: coverpoint current_command {
                        //bins request_commands[] =
                        bins flow_types[] = {
                                HMC_TRET,
                                HMC_PRET,
                                HMC_NULL
                        };
                        bins requests[] = {
                                HMC_WRITE_16,
                                HMC_WRITE_32,
                                HMC_WRITE_48,
                                HMC_WRITE_64,
                                HMC_WRITE_80,
                                HMC_WRITE_96,
                                HMC_WRITE_112,
                                HMC_WRITE_128,
                                
                                HMC_MODE_WRITE,
                                HMC_BIT_WRITE,
                                HMC_DUAL_8B_ADDI,
                                HMC_SINGLE_16B_ADDI,
                                
                                HMC_POSTED_WRITE_16,
                                HMC_POSTED_WRITE_32,
                                HMC_POSTED_WRITE_48,
                                HMC_POSTED_WRITE_64,
                                HMC_POSTED_WRITE_80,
                                HMC_POSTED_WRITE_96,
                                HMC_POSTED_WRITE_112,
                                HMC_POSTED_WRITE_128,
                                HMC_POSTED_BIT_WRIT,
                                
                                HMC_POSTED_BIT_WRIT,
                                HMC_POSTED_DUAL_8B_ADDI,
                                HMC_POSTED_SINGLE_16B_ADDI,
                                
                                HMC_MODE_READ,
                                HMC_READ_16,
                                HMC_READ_32,
                                HMC_READ_48,
                                HMC_READ_64,
                                HMC_READ_80,
                                HMC_READ_96,
                                HMC_READ_112, 
                                HMC_READ_128};

                        bins response[] = {
                                HMC_READ_RESPONSE,
                                HMC_WRITE_RESPONSE,
                                HMC_MODE_READ_RESPONSE,
                                HMC_MODE_WRITE_RESPONSE,
                                HMC_ERROR_RESPONSE
                        };
        
                        illegal_bins n_used = default;
                }
                CROSS_ERROR_TYPPE_COMMAND : cross ERROR_TYPE, HMC_COMMAND;
                
        endgroup
        
        function new ( string name="bfm_2_hmc_mon", uvm_component parent );
                super.new(name, parent);
                hmc_pkt_cg = new();
                hmc_pkt_error_cg = new();
        endfunction : new
        
        function void build_phase(uvm_phase phase);
                super.build_phase(phase);
                
                if (!uvm_config_db#(hmc_link_config)::get(this, "", "link_cfg", link_cfg)) begin
                        uvm_report_fatal(get_type_name(), $psprintf("hmc_link_config not set via config_db"));
                end
        endfunction : build_phase
        
        task run();
                cls_pkt old_pkt;
                `uvm_info(get_type_name(),$psprintf("starting BFM_2_HMC converter"), UVM_MEDIUM)
                forever begin
                        //mb_pkt.get(pkt);
                        old_pkt = pkt;
                        in_mb.peek(pkt);
                        if (pkt != old_pkt)
                                extract_hmc_pkt(pkt);
                        else
                                #5;
                end
                
        endtask
        
        task extract_hmc_pkt(cls_pkt pkt);
                header                          = pkt.get_header();
                tail                            = pkt.get_tail();
                data_phit_count         = pkt.data.size(); //-- 7 flits->14 phits --> 14-2 =12 data_phits

                bitstream                       = new [2*phit_size + data_phit_count*phit_size];

                //-- generate Bitstream

                if (header !=64'b0) begin

                        //-- check length
                        if( (header[10:7] != header[14:11]) || (header[10:7] != 1+data_phit_count /2)) begin
                                lng_error ++;
                                error_abort_mode = 1;
                                `uvm_info(get_type_name(),$psprintf("Set error abort mode: LNG/DLN ERROR, Command with header: %h", header), UVM_NONE)
                                irtry_cnt = 0;
                                
                                
                                current_error = LENGTH_ERROR;
                                current_command[5:0] = header[5:0];
                                hmc_pkt_error_cg.sample();
                        end else begin
                                
                                //-- convert the cls_pkt pkt to hmc_packet packet
                                cls_pkt_to_hmc_packet(pkt);

                                //-- check crc error
                                check_crc_error(packet);


                                //-- wait for irtry
                                if (error_abort_mode)
                                        clear_error_abort_mode();
        
                                else begin

                                        //-- count Start Error Mode IRTRY
                                        if (packet.start_retry) begin
                                                irtry++;
                                                `uvm_info(get_type_name(),$psprintf("Start Retry: %0d", irtry), UVM_HIGH)
                                        end

                                        //-- packet sequence check
                                        if ((packet.command == HMC_TRET) || (packet.get_command_type() != HMC_FLOW_TYPE))  begin
                                                irtry = 0; //-- reset start retry mode counter
                                                
                                                if (packet.sequence_number != seq_number+1'b1) begin
                                                        seq_error ++;
                                                        error_abort_mode = 1;
                                                        `uvm_info(get_type_name(),$psprintf("Set error abort mode: SEQ ERROR, Command: %s", packet.command.name()), UVM_NONE)
                                                        irtry_cnt = 0;


                                                        //-- sample seq error
                                                        current_error = SEQ_ERROR;
                                                        current_command = packet.command;
                                                        hmc_pkt_error_cg.sample();

                                                end else begin

                                                        seq_number = packet.sequence_number;

                                                        //-- check if poisoned
                                                        if ( packet.poisoned) begin
                                                                poisoned_pkt++;

                                                                //-- sample poison
                                                                current_error = POISON;
                                                                current_command = packet.command;
                                                                hmc_pkt_error_cg.sample();
                                                        end else
                                                                if((packet.get_command_type() != HMC_FLOW_TYPE))
                                                                        write_packet(packet);
                                                end
                                        end
                                end
                        end
                end
                
        endtask : extract_hmc_pkt
        
        
        
        function void check_crc_error(hmc_packet packet);
                if (packet.crc_error) begin
                        crc_error++;
                        error_abort_mode = 1;
                        `uvm_info(get_type_name(),$psprintf("Set error abort mode: CRC ERROR, Command: %s", packet.command.name()), UVM_NONE)
                        irtry_cnt = 0;
                        
                        current_error = CRC_ERROR;
                        current_command = packet.command;
                        hmc_pkt_error_cg.sample();
                end
        endfunction : check_crc_error
        
        function void clear_error_abort_mode();
                if ((packet.clear_error_abort)) begin
                        `uvm_info(get_type_name(), $psprintf("Clear Error Abort Mode: %0d",irtry_cnt ), UVM_HIGH)
                        irtry_cnt ++;
                end else begin 
                        irtry_cnt = 0;                                                  //-- reset counter
                end 
                
                if (irtry_cnt >= link_cfg.cfg_init_retry_rxcnt) begin                   //-- test threshold
                        error_abort_mode = 0;
                        `uvm_info(get_type_name(), $psprintf("Clear Error Abort Mode" ), UVM_NONE)
                end
        endfunction : clear_error_abort_mode


        function void cls_pkt_to_hmc_packet (cls_pkt pkt);
                //-- Convert the CLS_PKT to HMC_PKT
                                for (int b = 0; b < 64; b++) begin                                                              //-- read header to bitmap
                                        bitstream[b]=header[b];
                                end

                                if (data_phit_count > 0)
                                        for (int phit = 0; phit < data_phit_count; phit++)                      //-- read data to bitmap
                                                for (int b = 0; b < phit_size; b++)
                                                        bitstream[(phit + 1) * phit_size + b] = pkt.data[phit][b];
                        
                                for (int b = 0; b < 64; b++) begin                                                              //-- read tail to bitmap
                                        bitstream[(data_phit_count+1)*phit_size+b]=tail[b];
                                end
                                
                                //-- create hmc packet
                                `uvm_info(get_type_name(),$psprintf("Got a BFM Packet:  %s",pkt.convert2string()), UVM_HIGH)
                                packet = hmc_packet::type_id::create("packet", this);
                                void'(packet.unpack(bitstream));
                
        endfunction     :       cls_pkt_to_hmc_packet

        task write_packet(hmc_packet packet);
                
                if(packet.get_command_type() == HMC_RESPONSE_TYPE)begin
                        if(packet.command != HMC_ERROR_RESPONSE) begin
                                `uvm_info(get_type_name(),$psprintf("Rsp #%0d : %s",rsp_rcvd, packet.command.name()), UVM_HIGH)
                                `uvm_info(get_type_name(),$psprintf("Rsp #%0d : %s",rsp_rcvd, packet.sprint()), UVM_HIGH)
                                rsp_rcvd++;
                        end else begin
                                `uvm_info(get_type_name(),$psprintf("Err Rsp %0d : %s with error code %b",err_rsp_rcvd, packet.command.name(), packet.error_status), UVM_HIGH)
                                err_rsp_rcvd++;                         
                        end
                end else begin
                        `uvm_info(get_type_name(),$psprintf("Req %0d : %s",req_rcvd, packet.command.name()), UVM_HIGH)
                        req_rcvd++;
                end


                hmc_pkt_cg.sample();

                item_collected_port.write(packet);
                
        endtask : write_packet
        
        
        function void report_phase(uvm_phase phase);
                `uvm_info(get_type_name(),$psprintf("LNG error count  %0d", lng_error),         UVM_NONE)
                `uvm_info(get_type_name(),$psprintf("CRC error count  %0d", crc_error),         UVM_NONE)
                `uvm_info(get_type_name(),$psprintf("SEQ error count  %0d", seq_error),         UVM_NONE)
                `uvm_info(get_type_name(),$psprintf("poisoned packets %0d", poisoned_pkt),      UVM_NONE)
        endfunction : report_phase

endclass


`endif

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.