/* -*- c++ -*- * File : vci_traffic_generator.cpp * Date : 26/08/2010 * Copyright : UPMC / LIP6 * Authors : Christophe Choichillon * * 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 * * Maintainers: christophe.choichillon@lip6.fr */ #include "../include/vci_traffic_generator.h" namespace soclib { namespace caba { #define tmpl(x) template x VciTrafficGenerator //////////////////////////////// // Constructor //////////////////////////////// tmpl(/**/)::VciTrafficGenerator( sc_module_name name, const soclib::common::MappingTable &mtp, const soclib::common::MappingTable &mtc, const soclib::common::MappingTable &mtx, const soclib::common::IntTab &vci_ixr_index, const soclib::common::IntTab &vci_ini_index, const soclib::common::IntTab &vci_tgt_index, size_t nways, size_t nsets, size_t nwords) : soclib::caba::BaseModule(name), p_clk("clk"), p_resetn("resetn"), p_vci("vci_ini"), m_srcid_ini( mtc.indexForId(vci_ini_index) ), // FIFOs m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4), r_tgt_cmd_fsm("r_tgt_cmd_fsm"), { assert(IS_POW_OF_2(nsets)); assert(IS_POW_OF_2(nwords)); assert(IS_POW_OF_2(nways)); assert(nsets); assert(nwords); assert(nways); assert(nsets <= 1024); assert(nwords <= 32); assert(nways <= 32); // Get the segments associated to the MemCache //std::list segList(mtp.getSegmentList(vci_tgt_index)); std::list::iterator seg; /* for(seg = segList.begin(); seg != segList.end() ; seg++) { if( seg->size() > 8 ) m_mem_segment = *seg; else m_reg_segment = *seg; nseg++; } */ for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) { if( seg->size() > 8 ) nseg++; } //assert( (nseg == 2) && (m_reg_segment.size() == 8) ); m_seg = new soclib::common::Segment*[nseg]; size_t i = 0; for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) { if ( seg->size() > 8 ) { m_seg[i] = &(*seg); i++; } else { m_reg_segment = *seg; } } assert( (m_reg_segment.size() == 8) ); // Memory cache allocation & initialisation m_cache_data = new data_t**[nways]; for ( size_t i=0 ; i[TRANSACTION_TAB_LINES]; // Allocation for XRAM_RSP FSM r_xram_rsp_victim_data = new sc_signal[nwords]; r_xram_rsp_to_tgt_rsp_data = new sc_signal[nwords]; r_xram_rsp_to_tgt_rsp_val = new sc_signal[nwords]; r_xram_rsp_to_xram_cmd_data = new sc_signal[nwords]; // Allocation for READ FSM r_read_data = new sc_signal[nwords]; r_read_to_tgt_rsp_data = new sc_signal[nwords]; r_read_to_tgt_rsp_val = new sc_signal[nwords]; // Allocation for WRITE FSM r_write_data = new sc_signal[nwords]; r_write_be = new sc_signal[nwords]; r_write_to_init_cmd_data = new sc_signal[nwords]; r_write_to_init_cmd_we = new sc_signal[nwords]; // Simulation SC_METHOD(transition); dont_initialize(); sensitive << p_clk.pos(); SC_METHOD(genMoore); dont_initialize(); sensitive << p_clk.neg(); } // end constructor ///////////////////////////////////////// // This function prints the statistics ///////////////////////////////////////// tmpl(void)::print_stats() { std::cout << "----------------------------------" << std::dec << std::endl; std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl << "- READ RATE = " << (float)m_cpt_read/m_cpt_cycles << std::endl << "- READ MISS RATE = " << (float)m_cpt_read_miss/m_cpt_read << std::endl << "- WRITE RATE = " << (float)m_cpt_write/m_cpt_cycles << std::endl << "- WRITE MISS RATE = " << (float)m_cpt_write_miss/m_cpt_write << std::endl << "- WRITE BURST LENGTH = " << (float)m_cpt_write_cells/m_cpt_write << std::endl << "- UPDATE RATE = " << (float)m_cpt_update/m_cpt_cycles << std::endl << "- UPDATE ARITY = " << (float)m_cpt_update_mult/m_cpt_update << std::endl << "- INVAL RATE = " << (float)m_cpt_inval/m_cpt_cycles << std::endl << "- INVAL ARITY = " << (float)m_cpt_inval_mult/m_cpt_inval << std::endl << "- SAVE DIRTY RATE = " << (float)m_cpt_write_dirty/m_cpt_cycles << std::endl << "- CLEANUP RATE = " << (float)m_cpt_cleanup/m_cpt_cycles << std::endl << "- LL RATE = " << (float)m_cpt_ll/m_cpt_cycles << std::endl << "- SC RATE = " << (float)m_cpt_sc/m_cpt_cycles << std::endl; } ///////////////////////////////// tmpl(/**/)::~VciTrafficGenerator() ///////////////////////////////// { for(size_t i=0; icontains(p_vci_tgt.address.read()) ) { reached = true; r_index = index; } } if ( !reached ) { std::cout << "Out of segment access in VCI_MEM_CACHE" << std::endl; std::cout << "Faulty address = " << p_vci_tgt.address.read() << std::endl; std::cout << "Faulty initiator = " << p_vci_tgt.srcid.read() << std::endl; exit(0); } else if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) { r_tgt_cmd_fsm = TGT_CMD_READ; } else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ) && ( p_vci_tgt.trdid.read() == 0x0 ) ) { r_tgt_cmd_fsm = TGT_CMD_WRITE; } else if ((p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ) || (p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND) ) { r_tgt_cmd_fsm = TGT_CMD_ATOMIC; } else if (( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE ) && ( p_vci_tgt.trdid.read() == 0x1 )) { r_tgt_cmd_fsm = TGT_CMD_CLEANUP; } } break; } ////////////////// case TGT_CMD_READ: { assert(((p_vci_tgt.plen.read() == 4) || (p_vci_tgt.plen.read() == m_words*4)) && "All read request to the MemCache must have PLEN = 4 or PLEN = 4*nwords"); if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) { cmd_read_fifo_put = true; if ( p_vci_tgt.eop ) r_tgt_cmd_fsm = TGT_CMD_IDLE; else r_tgt_cmd_fsm = TGT_CMD_READ_EOP; } break; } ////////////////////// case TGT_CMD_READ_EOP: { if ( p_vci_tgt.cmdval && p_vci_tgt.eop ){ r_tgt_cmd_fsm = TGT_CMD_IDLE; } break; } /////////////////// case TGT_CMD_WRITE: { if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) { cmd_write_fifo_put = true; if( p_vci_tgt.eop ) r_tgt_cmd_fsm = TGT_CMD_IDLE; } break; } //////////////////// case TGT_CMD_ATOMIC: { assert(p_vci_tgt.eop && "Memory Cache Error: LL or SC command with length > 1 "); if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) { cmd_llsc_fifo_put = true; r_tgt_cmd_fsm = TGT_CMD_IDLE; } break; } ///////////////////// case TGT_CMD_CLEANUP: { assert(p_vci_tgt.eop && "Memory Cache Error: CLEANUP request with length > 1 "); if ( p_vci_tgt.cmdval && m_cmd_cleanup_nline_fifo.wok() ) { cmd_cleanup_fifo_put = true; r_tgt_cmd_fsm = TGT_CMD_IDLE; } break; } } // end switch tgt_cmd_fsm if ( cmd_cleanup_fifo_put ) { if ( cmd_cleanup_fifo_get ) { m_cmd_cleanup_srcid_fifo.put_and_get(p_vci_tgt.srcid.read()); m_cmd_cleanup_trdid_fifo.put_and_get(p_vci_tgt.trdid.read()); m_cmd_cleanup_pktid_fifo.put_and_get(p_vci_tgt.pktid.read()); m_cmd_cleanup_nline_fifo.put_and_get(p_vci_tgt.wdata.read()); } else { m_cmd_cleanup_srcid_fifo.simple_put(p_vci_tgt.srcid.read()); m_cmd_cleanup_trdid_fifo.simple_put(p_vci_tgt.trdid.read()); m_cmd_cleanup_pktid_fifo.simple_put(p_vci_tgt.pktid.read()); m_cmd_cleanup_nline_fifo.simple_put(p_vci_tgt.wdata.read()); } } else { if ( cmd_cleanup_fifo_get ) { m_cmd_cleanup_srcid_fifo.simple_get(); m_cmd_cleanup_trdid_fifo.simple_get(); m_cmd_cleanup_pktid_fifo.simple_get(); m_cmd_cleanup_nline_fifo.simple_get(); } } m_cpt_cycles++; } // end transition() ///////////////////////////// tmpl(void)::genMoore() ///////////////////////////// { //////////////////////////////////////////////////////////// // Command signals on the p_vci_ixr port //////////////////////////////////////////////////////////// p_vci_ixr.be = 0xF; p_vci_ixr.pktid = 0; p_vci_ixr.srcid = m_srcid_ixr; p_vci_ixr.cons = false; p_vci_ixr.wrap = false; p_vci_ixr.contig = true; p_vci_ixr.clen = 0; p_vci_ixr.cfixed = false; if ( r_xram_cmd_fsm.read() == XRAM_CMD_READ_NLINE ) { p_vci_ixr.cmd = vci_param::CMD_READ; p_vci_ixr.cmdval = true; p_vci_ixr.address = (r_read_to_xram_cmd_nline.read()*m_words*4); p_vci_ixr.plen = m_words*4; p_vci_ixr.wdata = 0x00000000; p_vci_ixr.trdid = r_read_to_xram_cmd_trdid.read(); p_vci_ixr.eop = true; } else if ( r_xram_cmd_fsm.read() == XRAM_CMD_LLSC_NLINE ) { p_vci_ixr.cmd = vci_param::CMD_READ; p_vci_ixr.cmdval = true; p_vci_ixr.address = (r_llsc_to_xram_cmd_nline.read()*m_words*4); p_vci_ixr.plen = m_words*4; p_vci_ixr.wdata = 0x00000000; p_vci_ixr.trdid = r_llsc_to_xram_cmd_trdid.read(); p_vci_ixr.eop = true; } else if ( r_xram_cmd_fsm.read() == XRAM_CMD_WRITE_NLINE ) { p_vci_ixr.cmd = vci_param::CMD_READ; p_vci_ixr.cmdval = true; p_vci_ixr.address = (r_write_to_xram_cmd_nline.read()*m_words*4); p_vci_ixr.plen = m_words*4; p_vci_ixr.wdata = 0x00000000; p_vci_ixr.trdid = r_write_to_xram_cmd_trdid.read(); p_vci_ixr.eop = true; } else if ( r_xram_cmd_fsm.read() == XRAM_CMD_XRAM_DATA ) { p_vci_ixr.cmd = vci_param::CMD_WRITE; p_vci_ixr.cmdval = true; p_vci_ixr.address = ((r_xram_rsp_to_xram_cmd_nline.read()*m_words+r_xram_cmd_cpt.read())*4); p_vci_ixr.plen = m_words*4; p_vci_ixr.wdata = r_xram_rsp_to_xram_cmd_data[r_xram_cmd_cpt.read()].read(); p_vci_ixr.trdid = r_xram_rsp_to_xram_cmd_trdid.read(); p_vci_ixr.eop = (r_xram_cmd_cpt == (m_words-1)); } else { p_vci_ixr.cmdval = false; p_vci_ixr.address = 0; p_vci_ixr.plen = 0; p_vci_ixr.wdata = 0; p_vci_ixr.trdid = 0; p_vci_ixr.eop = false; } //////////////////////////////////////////////////// // Response signals on the p_vci_ixr port //////////////////////////////////////////////////// if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) && (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) || (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true; else p_vci_ixr.rspack = false; //////////////////////////////////////////////////// // Command signals on the p_vci_tgt port //////////////////////////////////////////////////// switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) { case TGT_CMD_IDLE: p_vci_tgt.cmdack = false; break; case TGT_CMD_READ: p_vci_tgt.cmdack = m_cmd_read_addr_fifo.wok(); break; case TGT_CMD_READ_EOP: p_vci_tgt.cmdack = true; break; case TGT_CMD_WRITE: p_vci_tgt.cmdack = m_cmd_write_addr_fifo.wok(); break; case TGT_CMD_ATOMIC: p_vci_tgt.cmdack = m_cmd_llsc_addr_fifo.wok(); break; case TGT_CMD_CLEANUP: p_vci_tgt.cmdack = m_cmd_cleanup_nline_fifo.wok(); break; default: p_vci_tgt.cmdack = false; break; } //////////////////////////////////////////////////// // Response signals on the p_vci_tgt port //////////////////////////////////////////////////// switch ( r_tgt_rsp_fsm.read() ) { case TGT_RSP_READ_IDLE: case TGT_RSP_WRITE_IDLE: case TGT_RSP_LLSC_IDLE: case TGT_RSP_CLEANUP_IDLE: case TGT_RSP_XRAM_IDLE: case TGT_RSP_INIT_IDLE: case TGT_RSP_READ_TEST: case TGT_RSP_XRAM_TEST: p_vci_tgt.rspval = false; p_vci_tgt.rsrcid = 0; p_vci_tgt.rdata = 0; p_vci_tgt.rpktid = 0; p_vci_tgt.rtrdid = 0; p_vci_tgt.rerror = 0; p_vci_tgt.reop = false; break; case TGT_RSP_READ_LINE: p_vci_tgt.rspval = true; p_vci_tgt.rdata = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read(); p_vci_tgt.rsrcid = r_read_to_tgt_rsp_srcid.read(); p_vci_tgt.rtrdid = r_read_to_tgt_rsp_trdid.read(); p_vci_tgt.rpktid = r_read_to_tgt_rsp_pktid.read(); p_vci_tgt.rerror = 0; p_vci_tgt.reop = (r_tgt_rsp_cpt.read()==(m_words-1)); break; case TGT_RSP_READ_WORD: p_vci_tgt.rspval = true; p_vci_tgt.rdata = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read(); p_vci_tgt.rsrcid = r_read_to_tgt_rsp_srcid.read(); p_vci_tgt.rtrdid = r_read_to_tgt_rsp_trdid.read(); p_vci_tgt.rpktid = r_read_to_tgt_rsp_pktid.read(); p_vci_tgt.rerror = 0; p_vci_tgt.reop = true; break; case TGT_RSP_WRITE: p_vci_tgt.rspval = true; p_vci_tgt.rdata = 0; p_vci_tgt.rsrcid = r_write_to_tgt_rsp_srcid.read(); p_vci_tgt.rtrdid = r_write_to_tgt_rsp_trdid.read(); p_vci_tgt.rpktid = r_write_to_tgt_rsp_pktid.read(); p_vci_tgt.rerror = 0; p_vci_tgt.reop = true; break; case TGT_RSP_CLEANUP: p_vci_tgt.rspval = true; p_vci_tgt.rdata = 0; p_vci_tgt.rsrcid = r_cleanup_to_tgt_rsp_srcid.read(); p_vci_tgt.rtrdid = r_cleanup_to_tgt_rsp_trdid.read(); p_vci_tgt.rpktid = r_cleanup_to_tgt_rsp_pktid.read(); p_vci_tgt.rerror = 0; p_vci_tgt.reop = true; break; case TGT_RSP_LLSC: p_vci_tgt.rspval = true; p_vci_tgt.rdata = r_llsc_to_tgt_rsp_data.read(); p_vci_tgt.rsrcid = r_llsc_to_tgt_rsp_srcid.read(); p_vci_tgt.rtrdid = r_llsc_to_tgt_rsp_trdid.read(); p_vci_tgt.rpktid = r_llsc_to_tgt_rsp_pktid.read(); p_vci_tgt.rerror = 0; p_vci_tgt.reop = true; break; case TGT_RSP_XRAM_LINE: p_vci_tgt.rspval = true; p_vci_tgt.rdata = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read(); p_vci_tgt.rsrcid = r_xram_rsp_to_tgt_rsp_srcid.read(); p_vci_tgt.rtrdid = r_xram_rsp_to_tgt_rsp_trdid.read(); p_vci_tgt.rpktid = r_xram_rsp_to_tgt_rsp_pktid.read(); p_vci_tgt.rerror = 0; p_vci_tgt.reop = (r_tgt_rsp_cpt.read()==(m_words-1)); break; case TGT_RSP_XRAM_WORD: p_vci_tgt.rspval = true; p_vci_tgt.rdata = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read(); p_vci_tgt.rsrcid = r_xram_rsp_to_tgt_rsp_srcid.read(); p_vci_tgt.rtrdid = r_xram_rsp_to_tgt_rsp_trdid.read(); p_vci_tgt.rpktid = r_xram_rsp_to_tgt_rsp_pktid.read(); p_vci_tgt.rerror = 0; p_vci_tgt.reop = true; break; case TGT_RSP_INIT: p_vci_tgt.rspval = true; p_vci_tgt.rdata = 0; p_vci_tgt.rsrcid = r_init_rsp_to_tgt_rsp_srcid.read(); p_vci_tgt.rtrdid = r_init_rsp_to_tgt_rsp_trdid.read(); p_vci_tgt.rpktid = r_init_rsp_to_tgt_rsp_pktid.read(); p_vci_tgt.rerror = 0; p_vci_tgt.reop = true; break; } // end switch r_tgt_rsp_fsm /////////////////////////////////////////////////// // Command signals on the p_vci_ini port /////////////////////////////////////////////////// p_vci_ini.cmd = vci_param::CMD_WRITE; p_vci_ini.srcid = m_srcid_ini; p_vci_ini.pktid = 0; p_vci_ini.cons = true; p_vci_ini.wrap = false; p_vci_ini.contig = false; p_vci_ini.clen = 0; p_vci_ini.cfixed = false; switch ( r_init_cmd_fsm.read() ) { case INIT_CMD_UPDT_IDLE: case INIT_CMD_INVAL_IDLE: case INIT_CMD_UPDT_SEL: case INIT_CMD_INVAL_SEL: p_vci_ini.cmdval = false; p_vci_ini.address = 0; p_vci_ini.wdata = 0; p_vci_ini.be = 0; p_vci_ini.plen = 0; p_vci_ini.trdid = 0; p_vci_ini.eop = false; break; case INIT_CMD_INVAL_NLINE: p_vci_ini.cmdval = true; p_vci_ini.address = m_coherence_table[r_init_cmd_target.read()]; p_vci_ini.wdata = r_xram_rsp_to_init_cmd_nline.read(); p_vci_ini.be = 0xF; p_vci_ini.plen = 4; p_vci_ini.trdid = r_xram_rsp_to_init_cmd_trdid.read(); p_vci_ini.eop = true; break; case INIT_CMD_UPDT_NLINE: p_vci_ini.cmdval = true; p_vci_ini.address = m_coherence_table[r_init_cmd_target.read()] + 4; p_vci_ini.wdata = r_write_to_init_cmd_nline.read(); p_vci_ini.be = 0xF; p_vci_ini.plen = 4 * (r_write_to_init_cmd_count.read() + 2); p_vci_ini.trdid = r_write_to_init_cmd_trdid.read(); p_vci_ini.eop = false; break; case INIT_CMD_UPDT_INDEX: p_vci_ini.cmdval = true; p_vci_ini.address = m_coherence_table[r_init_cmd_target.read()] + 4; p_vci_ini.wdata = r_write_to_init_cmd_index.read(); p_vci_ini.be = 0xF; p_vci_ini.plen = 4 * (r_write_to_init_cmd_count.read() + 2); p_vci_ini.trdid = r_write_to_init_cmd_trdid.read(); p_vci_ini.eop = false; break; case INIT_CMD_UPDT_DATA: p_vci_ini.cmdval = true; p_vci_ini.address = m_coherence_table[r_init_cmd_target.read()] + 4; p_vci_ini.wdata = r_write_to_init_cmd_data[r_init_cmd_cpt.read() + r_write_to_init_cmd_index.read()].read(); if(r_write_to_init_cmd_we[r_init_cmd_cpt.read() + r_write_to_init_cmd_index.read()].read()) p_vci_ini.be = 0xF; else p_vci_ini.be = 0x0; p_vci_ini.plen = 4 * (r_write_to_init_cmd_count.read() + 2); p_vci_ini.trdid = r_write_to_init_cmd_trdid.read(); p_vci_ini.eop = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) ); break; } // end switch r_init_cmd_fsm ////////////////////////////////////////////////////// // Response signals on the p_vci_ini port ////////////////////////////////////////////////////// if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack = true; else p_vci_ini.rspack = false; } // end genMoore() }} // end name space