/* -*- c++ -*- * * SOCLIB_LGPL_HEADER_BEGIN * * This file is part of SoCLib, GNU LGPLv2.1. * * SoCLib 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; version 2.1 of the License. * * SoCLib 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 SoCLib; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA * * SOCLIB_LGPL_HEADER_END * * Copyright (c) UPMC, Lip6 * Ghassan Almaless , 2011 * * Maintainers: Ghassan */ #include "vci_profiler.h" #include #include #include "vci_buffers.h" #include #include #include #include namespace soclib { namespace caba { #define tmpl(...) template __VA_ARGS__ VciProfiler #define ABS(x) (((x) < 0) ? -(x) : (x)) #define VCI_iRD_CMD 4 #define VCI_iTLB_RD_CMD 5 #define VCI_iTLB_LL_CMD 6 #define VCI_iTLB_SC_CMD 7 #define VCI_DTLB_RD_CMD 8 #define VCI_DTLB_LL_CMD 9 #define VCI_DTLB_SC_CMD 10 #define _CMD_ITLB 0x1 #define _CMD_DTLB 0x2 #define _CMD_USR 0x4 static const char* vci_cmd_names[VCI_CMD_NR] = {"SC_CMD ", "RD_CMD ", "WR_CMD ", "LL_CMD ", "iRD_CMD", "iTLB_RD_CMD", "iTLB_LL_CMD", "iTLB_SC_CMD", "DTLB_RD_CMD", "DTLB_LL_CMD", "DTLB_SC_CMD"}; tmpl(void)::print_stats() { unsigned long local_cntr; unsigned long total_cost; unsigned long total_flits; unsigned long total_rflits; unsigned long total_estmtd_enrg; std::ostream &output = m_l1->m_log; if(m_period == 0) return; total_cost = 0; total_flits = 0; total_rflits = 0; total_estmtd_enrg = 0; local_cntr = m_access_cntr - m_remote_cntr; output << name() << " Cycles: " << std::dec << m_tm_now << std::endl << "Access_Rate = " << (double) m_access_cntr / m_cycles_cntr << std::endl << "Remote_% = " << (double) m_remote_cntr / m_access_cntr << std::endl << "LL_% = " << (double) m_cmd_tbl[vci_param::CMD_LOCKED_READ].trans / m_access_cntr << std::endl << "SC_% = " << (double) m_cmd_tbl[vci_param::CMD_STORE_COND].trans / m_access_cntr << std::endl; for(long i = 0; i < VCI_CMD_NR; i++) { local_cntr = m_cmd_tbl[i].distance * m_cmd_tbl[i].rflits; output << vci_cmd_names[i] << " [" << m_cmd_tbl[i].trans << ", " << m_cmd_tbl[i].remote << ", " << m_cmd_tbl[i].trans - m_cmd_tbl[i].remote << ", " << m_cmd_tbl[i].cost << ", " << m_cmd_tbl[i].rcost << ", " << m_cmd_tbl[i].cost - m_cmd_tbl[i].rcost << ", " << m_cmd_tbl[i].limit1 << ", " << m_cmd_tbl[i].limit2 << ", " << m_cmd_tbl[i].rmax_cost << ", " << m_cmd_tbl[i].rmax_time << ", " << m_cmd_tbl[i].lmax_cost << ", " << m_cmd_tbl[i].lmax_time << ", " << m_cmd_tbl[i].flits << ", " << m_cmd_tbl[i].rflits << ", " << std::hex << m_cmd_tbl[i].raddr << ", " << std::dec << m_cmd_tbl[i].distance << "," << m_cmd_tbl[i].d1_limit << "," << m_cmd_tbl[i].d2_limit << "," << m_cmd_tbl[i].max_dist << "," << local_cntr << "]" << std::endl; total_cost += m_cmd_tbl[i].cost; total_flits += m_cmd_tbl[i].flits; total_rflits += m_cmd_tbl[i].rflits; total_estmtd_enrg += local_cntr; } output << "Total_CMDs = " << m_access_cntr << std::endl << "Total_Cost = " << total_cost << std::endl << "Total_Flits = " << total_flits << std::endl << "Total_Remote_Flits = " << total_rflits << std::endl << "Total_Estmtd_Enrg = " << total_estmtd_enrg << std::endl; } tmpl(void)::clear_stats() { memset(m_cmd_tbl, 0, sizeof(m_cmd_tbl)); m_access_cntr = 0; m_remote_cntr = 0; m_cycles_cntr = 0; } tmpl(void)::set_limits(unsigned long limit1, unsigned long limit2) { m_limit1 = limit1; m_limit2 = limit2; } tmpl(void)::set_L1_cache(VciCcVCacheWrapper2V1 *l1) { m_l1 = l1; } tmpl()::VciProfiler( sc_core::sc_module_name insname, size_t index, size_t x_id, size_t y_id, size_t x_width, size_t y_width, size_t addr_width) : BaseModule(insname), p_resetn("resetn"), p_clk("clk"), p_vci("vci") { clear_stats(); m_index = index; m_x = x_id; m_y = y_id; m_xWidth = x_width; m_yWidth = y_width; m_width = x_width + y_width; m_bits = addr_width; m_tm_now = 0; m_tm_start = 0; m_isPending = false; m_isCMDPending = false; m_isPeriod = false; m_isDebug = false; m_last_cmd = 0; m_limit1 = 0; m_limit2 = 0; m_d1_limit = 0; m_d2_limit = 0; m_period = 0; m_debug_cntr = 0; m_threshold = 1000000; char *ptr = getenv("TSAR_PROFILER_PERIOD"); if(ptr != NULL) m_period = atol(ptr); ptr = getenv("TSAR_PROFILER_THRESHOLD"); if(ptr != NULL) m_threshold = atol(ptr); ptr = getenv("TSAR_PROFILER_DEBUG"); if(ptr != NULL) m_isDebug = (atol(ptr) != 0) ? true : false; ptr = getenv("TSAR_PROFILER_LIMIT1"); if(ptr != NULL) m_limit1 = atol(ptr); ptr = getenv("TSAR_PROFILER_LIMIT2"); if(ptr != NULL) m_limit2 = atol(ptr); ptr = getenv("TSAR_PROFILER_D1_LIMIT"); if(ptr != NULL) m_d1_limit = atol(ptr); ptr = getenv("TSAR_PROFILER_D2_LIMIT"); if(ptr != NULL) m_d2_limit = atol(ptr); #if 0 if(m_period != 0) m_log.open(insname, std::ios::out); #endif SC_METHOD(transition); dont_initialize(); sensitive << p_clk.pos(); } tmpl()::~VciProfiler() { } tmpl(void)::transition() { unsigned long cmd; unsigned long shift; unsigned long msb; long x_coord; long y_coord; unsigned long distance; unsigned long cost; bool isUser; std::ostream &output = m_l1->m_log; if(m_period == 0) return; if( p_vci.cmdval.read() && p_vci.cmdack.read() ) { if(m_isPending == false) { m_isCMDPending = true; m_isPending = true; m_tm_start = m_tm_now; cmd = p_vci.cmd.read(); m_access_cntr ++; if((cmd == vci_param::CMD_READ) && (p_vci.trdid.read() > 1)) cmd = VCI_iRD_CMD; else if((cmd == vci_param::CMD_READ) && (p_vci.pktid.read() & _CMD_ITLB)) cmd = VCI_iTLB_RD_CMD; else if((cmd == vci_param::CMD_READ) && (p_vci.pktid.read() & _CMD_DTLB)) cmd = VCI_DTLB_RD_CMD; else if((cmd == vci_param::CMD_LOCKED_READ) && (p_vci.pktid.read() & _CMD_ITLB)) cmd = VCI_iTLB_LL_CMD; else if((cmd == vci_param::CMD_LOCKED_READ) && (p_vci.pktid.read() & _CMD_DTLB)) cmd = VCI_DTLB_LL_CMD; else if((cmd == vci_param::CMD_STORE_COND) && (p_vci.pktid.read() & _CMD_ITLB)) cmd = VCI_iTLB_SC_CMD; else if((cmd == vci_param::CMD_STORE_COND) && (p_vci.pktid.read() & _CMD_DTLB)) cmd = VCI_DTLB_SC_CMD; m_last_cmd = cmd; m_last_addr = p_vci.address.read(); m_cmd_tbl[cmd].trans ++; m_cmd_tbl[cmd].flits += ((p_vci.plen.read() / 4) + 1); shift = m_bits - m_width; msb = m_last_addr >> shift; distance = 0; m_isRemote = (msb == m_index) ? false : true; if(m_isRemote == true) { isUser = (p_vci.pktid.read() & _CMD_USR) ? true : false; m_cmd_tbl[cmd].remote ++; m_remote_cntr ++; x_coord = msb >> m_yWidth; y_coord = msb & ((1 << m_yWidth) - 1); distance = ABS(m_x - x_coord) + ABS(m_y - y_coord); output << ">> " << vci_cmd_names[cmd] << "\t(" << m_x << "," << m_y << ") --> (" << x_coord << "," << y_coord << ")\t[ D: " << distance << " @: " << std::hex << m_last_addr << std::dec << " T: " << m_tm_now << " "<< ((isUser) ? "U" : "K") << " ]" << std::endl; m_cmd_tbl[cmd].rflits += ((p_vci.plen.read() / 4) + 1); m_cmd_tbl[cmd].distance += distance; if(distance > m_cmd_tbl[cmd].max_dist) m_cmd_tbl[cmd].max_dist = distance; if(distance >= m_d2_limit) m_cmd_tbl[cmd].d2_limit ++; else if(distance >= m_d1_limit) m_cmd_tbl[cmd].d1_limit ++; } #if 1 if(m_isDebug) { output << ">>> " << std::dec << "Cycle: "<< m_tm_now << ", Addr " << std::hex << m_last_addr << ", isRemote " << m_isRemote << ", Distance " << distance << ", " << vci_cmd_names[m_last_cmd]; } #endif } if(p_vci.eop.read()) m_isPending = false; } if ( p_vci.rspval.read() && p_vci.rspack.read() ) { if( p_vci.reop.read() ) { m_isCMDPending = false; cost = m_tm_now - m_tm_start; m_cmd_tbl[m_last_cmd].cost += cost; if(m_isRemote == true) m_cmd_tbl[m_last_cmd].rcost += cost; if(cost > m_limit2) m_cmd_tbl[m_last_cmd].limit2 ++; else if(cost > m_limit1) m_cmd_tbl[m_last_cmd].limit1 ++; if(m_isRemote == true) { if(cost > m_cmd_tbl[m_last_cmd].rmax_cost) { m_cmd_tbl[m_last_cmd].rmax_time = m_tm_now; m_cmd_tbl[m_last_cmd].rmax_cost = cost; m_cmd_tbl[m_last_cmd].raddr = m_last_addr; } } else { if(cost > m_cmd_tbl[m_last_cmd].lmax_cost) { m_cmd_tbl[m_last_cmd].lmax_time = m_tm_now; m_cmd_tbl[m_last_cmd].lmax_cost = cost; } } #if 1 if(m_isDebug) { output << " <<< " << std::dec << "Cycle: "<< m_tm_now << ", Cost: " << cost << ", Addr " << std::hex << m_last_addr << ", " << vci_cmd_names[m_last_cmd] << std::endl; } #endif } } m_tm_now ++; m_cycles_cntr ++; #if 1 if((m_isCMDPending == true) && ((m_tm_now - m_tm_start) > m_threshold) && (m_isDebug == false)) { output << "Threshold is reached: " << std::dec << "Tm_now: " << m_tm_now << " Tm_start: " << m_tm_start << " Val: " << m_tm_now - m_tm_start << " Threshold: " << m_threshold << std::endl; m_isDebug = true; } if(m_isDebug == true) { m_l1->print_trace(0); m_debug_cntr ++; } if(m_debug_cntr > 30) { m_isDebug = false; print_stats(); } #endif if((m_period != 0) && ((m_tm_now % m_period) == 0)) { output << "Period reached, " << std::dec << m_period << ", " << m_tm_now << ", " << m_isPeriod << ", " << m_isCMDPending << std::endl; m_isPeriod = true; } if((m_isPeriod == true) && (m_isCMDPending == false)) { print_stats(); clear_stats(); m_isPeriod = false; } } }} // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4