/* -*- 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 * * Authors : alain.greiner@lip6.fr * Date : july 2010 * Copyright: UPMC - LIP6 * * Modified by: Cesar Fuguet Tortolero */ #include "../include/dspin_packet_generator.h" #include namespace soclib { namespace caba { using namespace soclib::caba; using namespace soclib::common; #define tmpl(x) template x DspinPacketGenerator ////////////////////////////////////////////////////// tmpl(/**/)::DspinPacketGenerator( sc_module_name name, const size_t srcid, // srcid for random const size_t length, // packet length (flits) const size_t load, // requested load * 1000 const size_t fifo_depth, // Fifo depth const size_t bcp, // broadcast period const size_t x_width, const size_t y_width, const size_t x_size, const size_t y_size, const size_t max_packets) : BaseModule(name), p_clk( "clk" ), p_resetn( "resetn" ), p_in( "p_in" ), p_out( "p_out" ), r_cycles( "r_cycles" ), r_posted_bc_packets( "r_posted_bc_packets" ), r_posted_packets( "r_posted_packets" ), r_send_fsm( "r_send_fsm" ), r_send_length( "r_send_length" ), r_send_dest( "r_send_dest" ), r_send_packets( "r_send_packets" ), r_send_bc_packets( "r_send_bc_packets" ), r_receive_fsm( "r_receive_fsm" ), r_receive_packets( "r_receive_packets" ), r_receive_latency( "r_receive_latency" ), r_receive_bc_packets( "r_receive_bc_packets" ), r_receive_bc_latency( "r_receive_bc_latency" ), r_transaction_fifo( "r_transaction_fifo", fifo_depth ), m_length( length ), m_load( load ), m_bcp( bcp ), m_srcid( srcid ), m_x_width( x_width ), m_y_width( y_width ), m_x_size( x_size ), m_y_size( y_size ), m_max_packets( max_packets ) { assert( (load <= 1000 ) and "DSPIN PACKET GENERATOR ERROR: The load should be between 0 and 1000" ); assert( (cmd_width >= 33) and "DSPIN PACKET GENERATOR ERROR: CMD flit width smaller than 33 bits"); assert( (length > 1 ) and "DSPIN PACKET GENERATOR ERROR: Packet length smaller than 2 flits"); SC_METHOD (transition); dont_initialize(); sensitive << p_clk.pos(); SC_METHOD (genMoore); dont_initialize(); sensitive << p_clk.neg(); } // end constructor //////////////////////// tmpl(void)::transition() { if ( not p_resetn.read() ) { r_send_fsm = SEND_IDLE; r_receive_fsm = RECEIVE_IDLE; r_cycles = 0; r_posted_date = 0; r_posted_packets = 0; r_posted_bc_packets = 0; r_send_packets = 0; r_send_bc_packets = 0; r_receive_packets = 0; r_receive_latency = 0; r_receive_bc_packets = 0; r_receive_bc_latency = 0; return; } // default values bool fifo_put = false; bool fifo_get = false; uint32_t alea = random(); ///////////////////////// GENERATOR FSM size_t bcast_flits = r_posted_bc_packets.read() * 2; size_t ucast_flits = r_posted_packets.read() * m_length; size_t posted_flits = bcast_flits + ucast_flits; size_t accepted_load = posted_flits * 1000 / (r_cycles.read() + 1); size_t total_packets = r_posted_bc_packets.read() + r_posted_packets.read(); bool is_broadcast = ((m_bcp != 0) && (((total_packets + 1) % m_bcp) == 0)); if( ((accepted_load + ((alea >> 16) & 0xF)) < m_load) ) { size_t total_packets = r_posted_packets.read() + r_posted_bc_packets.read(); bool max_not_reached = (total_packets < m_max_packets); if ( (m_max_packets == 0) || max_not_reached ) { fifo_put = true ; if( r_transaction_fifo.wok() ) { if (is_broadcast) { r_posted_bc_packets = r_posted_bc_packets.read() + 1; } else { r_posted_packets = r_posted_packets.read() + 1; } } } } /////////////////////////// CMD FSM switch( r_send_fsm.read() ) { case SEND_IDLE: if ( r_transaction_fifo.rok() ) { fifo_get = true; r_posted_date = (r_transaction_fifo.read() >> 1); // broadcast transaction if ( (r_transaction_fifo.read() & 1) == 1 ) { r_send_length = 2; r_send_fsm = SEND_BROADCAST; r_send_bc_packets = r_send_bc_packets.read() + 1; break; } // unicast transaction int x_dest = ((alea >> 8) & 0xFF) % m_x_size; int y_dest = ((alea ) & 0xFF) % m_y_size; r_send_length = m_length; r_send_fsm = SEND_UNICAST; r_send_packets = r_send_packets.read() + 1; r_send_dest = (x_dest << m_y_width) | y_dest; } break; case SEND_UNICAST: case SEND_BROADCAST: if( p_out.read.read() ) { r_send_length = r_send_length.read() - 1; if( r_send_length.read() == 1 ) { r_send_fsm = SEND_IDLE; } } break; } // end SEND FSM ////////////////////////////// RECEIVE FSM switch( r_receive_fsm.read() ) { case RECEIVE_IDLE: if ( p_in.write.read() ) { if ( ((p_in.data.read() & 1) == 1) ) { r_receive_fsm = RECEIVE_BROADCAST; } else { r_receive_fsm = RECEIVE_UNICAST; } } break; case RECEIVE_BROADCAST: if ( p_in.write.read() ) { uint32_t latency = r_cycles.read() - (uint32_t)p_in.data.read(); r_receive_bc_packets = r_receive_bc_packets.read() + 1; r_receive_bc_latency = r_receive_bc_latency.read() + latency ; r_receive_fsm = RECEIVE_IDLE; } break; case RECEIVE_UNICAST: if ( p_in.write.read() ) { uint32_t latency = r_cycles.read() - (uint32_t)p_in.data.read(); r_receive_packets = r_receive_packets.read() + 1; r_receive_latency = r_receive_latency.read() + latency; if ( p_in.eop.read() ) { r_receive_fsm = RECEIVE_IDLE; } else { r_receive_fsm = RECEIVE_WAIT_EOP; } } break; case RECEIVE_WAIT_EOP: if ( p_in.write.read() and p_in.eop.read() ) { r_receive_fsm = RECEIVE_IDLE; } break; } // end RECEIVE FSM // increment date r_cycles = r_cycles.read() + 1; // update fifos uint32_t fifo_data = (r_cycles.read() << 1) | (is_broadcast ? 1 : 0); r_transaction_fifo.update( fifo_get, fifo_put, fifo_data ); } // end transition ////////////////////// tmpl(void)::genMoore() { // p_out sc_uint data = 0; bool write = false; bool eop = false; if ( r_send_fsm.read() == SEND_UNICAST ) { write = true; if ( r_send_length.read() == m_length ) // first flit { sc_uint dest = r_send_dest.read(); data = dest << (cmd_width - m_x_width - m_y_width); } else if ( r_send_length.read() == (m_length-1) ) // second flit { data = (sc_uint)r_posted_date.read(); } eop = (r_send_length.read() == 1); } else if ( r_send_fsm.read() == SEND_BROADCAST ) { write = true; if ( r_send_length.read() == 2 ) // first flit { sc_uint boundaries = 0x07C1F; data = (boundaries << (cmd_width - 20)) | 1; } else // second flit { data = (sc_uint)r_posted_date.read(); } eop = (r_send_length.read() == 1); } p_out.data = data; p_out.eop = eop; p_out.write = write; p_in.read = true; } // end genMoore ///////////////////////// tmpl(void)::print_trace() { const char* cmd_str[] = { "IDLE", "SEND_UNICAST", "SEND_BROADCAST" }; const char* rsp_str[] = { "IDLE", "RECEIVE_UNICAST", "RECEIVE_BROADCAST", "RECEIVE_WAIT" }; std::cout << "DSPIN_GENERATOR " << name() << " : send_fsm = " << cmd_str[r_send_fsm.read()] << " / recv_fsm = " << rsp_str[r_receive_fsm.read()] << " / fifo_content = " << r_transaction_fifo.filled_status() << std::endl; } // end print_trace ///////////////////////// tmpl(void)::print_stats() { size_t bcast_flits = r_send_bc_packets.read() * 2; size_t ucast_flits = r_send_packets.read() * m_length; size_t load = (bcast_flits + ucast_flits * 1000) / r_cycles.read(); uint32_t latency = r_receive_latency.read() / (r_receive_packets.read() + 1); uint32_t bc_latency = r_receive_bc_latency.read() / (r_receive_bc_packets.read() + 1); std::cout << "DSPIN_GENERATOR " << name() << std::dec << "\n - offered load = " << m_load << "\n - accepted load = " << load << "\n - unicast sent packets = " << r_send_packets.read() << "\n - unicast received packets = " << r_receive_packets.read() << "\n - unicast latency = " << latency << "\n - broadcast sent packets = " << r_send_bc_packets.read() << "\n - broadcast received packets = " << r_receive_bc_packets.read() << "\n - broadcast latency = " << bc_latency << std::endl; } // end print_stats }} // end namespaces :w