/* 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 * * Author : Abdelmalek SI MERABET * Date : February 2013 * Copyright: UPMC - LIP6 */ ///////////////////////////////////////////////////////////////////////////// // Ring : Broadcast-inval : 2 flits l2(1)->l1(n) // //--------------------------------------------------------------------------- // 1st flit | eop |xmin |xmax |ymin |ymax | memcid | lid* |1| // (40) (1) (5) (5) (5) (5) (14) (4) (1) //--------------------------------------------------------------------------- // next flit | eop |res| trdid | nline | // (40) (1) (1) (4) (34) //--------------------------------------------------------------------------- // *lid : local id (port number on ring) for sequential broadcast ////////////////////////////////////////////////////////////////////////////// // Ring : Multicast-inval 2 flits (l2->l1) // //---------------------------------------------------------------------------- // 1st flit | eop | procid |res| memcid | trdid | type |0| // (40) (1) (14) (3) (14) (4) (3) (1) //---------------------------------------------------------------------------- // next flit | eop |res | nline | // (40) (1) (5) (34) ////////////////////////////////////////////////////////////////////////////// // Ring : Multicast-update 2+N flits l2(1)->l1(n) // //---------------------------------------------------------------------------- // 1st flit | eop | procid |res| memcid | trdid | type |0| // (40) (1) (14) (3) (14) (4) (3) (1) //---------------------------------------------------------------------------- // next flit | eop |res| wdidx | nline | // (40) (1) (1) (4) (34) //---------------------------------------------------------------------------- // next flits | eop | res | be | wdata | // (40) (1) (3) (4) (32) ////////////////////////////////////////////////////////////////////////////// // Ring : Cleanup Ack 1 flit l2(1)-l1(n) // //---------------------------------------------------------------------------- // 1st flit | eop | procid |res| set | way | type |0| // (40) (1) (14) (1) (16) (4) (3) (1) //---------------------------------------------------------------------------- // Type | cleanup ACK | Update/Inval | Data/instr | // (3) (1) (1) (1) //////////////////////////////////////////////////////////////////// // Ring : cleanup 2 flits l1(n)->l2(1) // //------------------------------------------------------------------ // 1st flit | eop | clustid*| procid | nline | way | type | // (33) (1) (10) (14) (2) (4) (2) // next flit | eop | nline | // (33) (1) (32) ///////////////////////////////////////////////////////////////////// // Ring : multicast ack 1 flit l1(n)->l2(1) // //------------------------------------------------------------------ // 1st flit | eop | clustid*| res | trdid | type | // (33) (1) (10) (16) (4) (2) //------------------------------------------------------------------ // Type | cleanup/MulticastACK | Data/instr | // (2) (1) (1) // *clusterid : identifiy cluster id of the dest memory cache. // all memory caches have the same Identifier in their clusters. //------------------------------------------------------------------ #ifndef DSPIN_LOCAL_RING_INITIATOR_FAST_H #define DSPIN_LOCAL_RING_INITIATOR_FAST_H #include "generic_fifo.h" #include "mapping_table.h" #include "ring_signals_fast.h" #include "dspin_interface.h" #define BRDCST_TGT_MASK 0xFFFFFFFFE1ULL #define I_DEBUG namespace soclib { namespace caba { namespace { const char *ring_cmd_fsm_state_str_i[] = { "CMD_IDLE", "OWNER", "BDC_FIRST", "BDC_SECOND", "SENDING", "WAIT_PALLOC_END", }; #ifdef I_DEBUG const char *ring_rsp_fsm_state_str_i[] = { "RSP_IDLE", "ALLOC", "NALLOC", "PALLOC2", "PALLOC1", }; #endif } // end namespace template class DspinLocalRingInitiatorFastC { typedef LocalRingSignals ring_signal_t; typedef DspinInput cmd_in_t; typedef DspinOutput rsp_out_t; private: enum ring_rsp_fsm_state_e { RSP_IDLE, // waiting for first flit of a response packet ALLOC, // next flit of a local rsp packet NALLOC, // next flit of a ring rsp packet PALLOC2, PALLOC1, }; enum ring_cmd_fsm_state_e { CMD_IDLE, OWNER, BDC_FIRST, BDC_SECOND, SENDING, WAIT_PALLOC_END, }; // structural parameters std::string m_name; bool m_alloc_init; // internal fifos GenericFifo m_cmd_fifo; // fifo for the local command packet GenericFifo m_rsp_fifo; // fifo for the local response packet // routing table soclib::common::AddressMaskingTable m_rt; soclib::common::AddressDecodingTable m_lt; uint64_t r_brdcst_save; uint32_t m_srcid; uint32_t m_nb_target; uint32_t m_x_width; uint32_t m_y_width; sc_core::sc_signal r_cpt_tgt; // target id for sequential broadcast sc_core::sc_signal r_ring_cmd_fsm; // ring command packet FSM (distributed) sc_core::sc_signal r_ring_rsp_fsm; // ring response packet FSM public : #define __renRegInit(x) x((((std::string) name)+"_" #x).c_str()) DspinLocalRingInitiatorFastC( const char *name, bool alloc_init, const int &wrapper_fifo_depth, const soclib::common::MappingTable &mt, const soclib::common::IntTab &ringid, const uint32_t &srcid, const uint32_t &nb_target, const uint32_t &x_width, const uint32_t &y_width) : m_name(name), m_alloc_init(alloc_init), m_cmd_fifo(((std::string) name)+"m_cmd_fifo", wrapper_fifo_depth), m_rsp_fifo(((std::string) name)+"m_rsp_fifo", wrapper_fifo_depth), m_rt(mt.getIdMaskingTable(ringid.level())), m_lt(mt.getIdLocalityTable(ringid)), m_srcid(srcid), m_nb_target(nb_target), m_x_width(x_width), m_y_width(y_width), __renRegInit(r_cpt_tgt), __renRegInit(r_ring_cmd_fsm), __renRegInit(r_ring_rsp_fsm) {} // end constructor void reset() { if(m_alloc_init) r_ring_cmd_fsm = OWNER; else r_ring_cmd_fsm = CMD_IDLE; r_ring_rsp_fsm = RSP_IDLE; m_cmd_fifo.init(); m_rsp_fifo.init(); } void transition(const cmd_in_t &p_cmd_in, const rsp_out_t &p_rsp_out, const ring_signal_t p_ring_in, cmd_str &init_cmd, bool &init_rsp_val) { bool cmd_fifo_get = false; bool cmd_fifo_put = false; uint64_t cmd_fifo_data = 0; bool rsp_fifo_put = false; uint64_t rsp_fifo_data = 0; //////////// ACCESS DSPIN FIFOS /////////////////// if (p_cmd_in.write.read()) { #ifdef I_DEBUG std::cout << sc_time_stamp() << " -- " << m_name << " -- DSPIN FIFO" << " -- cmd in rok : " << p_cmd_in.write << " -- in data : " << std::hex << p_cmd_in.data.read() << " -- fifo wok : " << m_cmd_fifo.wok() << std::endl; #endif cmd_fifo_data = (uint64_t) p_cmd_in.data.read(); cmd_fifo_put = m_cmd_fifo.wok(); } bool rsp_fifo_get = p_rsp_out.read.read(); //////////// RING CMD FSM ///////////////////////// switch( r_ring_cmd_fsm ) { case CMD_IDLE: // stay here while : !fifo_rok + !gnt #ifdef I_DEBUG if(m_cmd_fifo.rok()) std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_cmd_fsm = " << ring_cmd_fsm_state_str_i[r_ring_cmd_fsm] << " - fifo ROK : " << m_cmd_fifo.rok() << " - in grant : " << p_ring_in.cmd_grant << " - in palloc : " << p_ring_in.cmd_palloc << " - in wok : " << p_ring_in.cmd_r << " - fifo data : " << std::hex << m_cmd_fifo.read() << std::endl; #endif if ( p_ring_in.cmd_grant && m_cmd_fifo.rok() ) { if (m_cmd_fifo.read() & 0x1 == 0x1) // broadcast { r_cpt_tgt = m_nb_target; r_brdcst_save = m_cmd_fifo.read() & BRDCST_TGT_MASK; // save first flit of brdcst r_ring_cmd_fsm = BDC_FIRST; } else { r_ring_cmd_fsm = SENDING; } } break; case OWNER: if ( m_cmd_fifo.rok()) // && p_ring_in.cmd_wok.read() ) { #ifdef I_DEBUG std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_cmd_fsm = " << ring_cmd_fsm_state_str_i[r_ring_cmd_fsm] << " - fifo ROK : " << m_cmd_fifo.rok() << " - in grant : " << p_ring_in.cmd_grant << " - in preempt : " << p_ring_in.cmd_preempt << " - in palloc : " << p_ring_in.cmd_palloc << " - in wok : " << p_ring_in.cmd_r << " - fifo data : " << std::hex << m_cmd_fifo.read() << std::endl; #endif bool eop = ( (int) ((m_cmd_fifo.read() >> (ring_cmd_data_size - 1) ) & 0x1) == 1); if (m_cmd_fifo.read() & 0x1 == 0x1) // broadcast { r_cpt_tgt = m_nb_target; r_brdcst_save = m_cmd_fifo.read() & BRDCST_TGT_MASK; // save first flit of brdcst r_ring_cmd_fsm = BDC_FIRST; } // else { if ( eop && p_ring_in.cmd_r ) { cmd_fifo_get = true; if ( p_ring_in.cmd_grant ) r_ring_cmd_fsm = OWNER; else r_ring_cmd_fsm = CMD_IDLE; } if (!eop || !p_ring_in.cmd_r) { cmd_fifo_get = p_ring_in.cmd_r; r_ring_cmd_fsm = SENDING; } } } else if ( !p_ring_in.cmd_grant) r_ring_cmd_fsm = CMD_IDLE; break; case BDC_FIRST: #ifdef I_DEBUG std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_cmd_fsm = " << ring_cmd_fsm_state_str_i[r_ring_cmd_fsm] << " - fifo ROK : " << m_cmd_fifo.rok() << " - in grant : " << p_ring_in.cmd_grant << " - in preempt : " << p_ring_in.cmd_preempt << " - in palloc : " << p_ring_in.cmd_palloc << " - in wok : " << p_ring_in.cmd_r << " - cpt_tgt : " << r_cpt_tgt.read() << " - fifo data : " << std::hex << m_cmd_fifo.read() << std::endl; #endif if (p_ring_in.cmd_preempt) break; if (p_ring_in.cmd_r) { if (r_cpt_tgt.read() == m_nb_target) { cmd_fifo_get = true; } r_ring_cmd_fsm = BDC_SECOND; } break; case BDC_SECOND: #ifdef I_DEBUG std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_cmd_fsm = " << ring_cmd_fsm_state_str_i[r_ring_cmd_fsm] << " - fifo ROK : " << m_cmd_fifo.rok() << " - in grant : " << p_ring_in.cmd_grant << " - in preempt : " << p_ring_in.cmd_preempt << " - in palloc : " << p_ring_in.cmd_palloc << " - in wok : " << p_ring_in.cmd_r << " - fifo data : " << std::hex << m_cmd_fifo.read() << std::endl; #endif if (p_ring_in.cmd_preempt) break; if(m_cmd_fifo.rok() && p_ring_in.cmd_r) { if(r_cpt_tgt.read() == 0) { cmd_fifo_get = true; if ( !p_ring_in.cmd_palloc && p_ring_in.cmd_grant ) { r_ring_cmd_fsm = OWNER; } else if ( !p_ring_in.cmd_palloc && !p_ring_in.cmd_grant ) { r_ring_cmd_fsm = CMD_IDLE; } else { r_ring_cmd_fsm = WAIT_PALLOC_END; } } else { r_cpt_tgt = r_cpt_tgt - 1; r_ring_cmd_fsm = BDC_FIRST; } } break; case SENDING: // stay here while !release + cmd_preempt // release = fifo_rok.ring_in.wok.fifo_data.eop // palloc : a local target is stil allocated by the gateway_initiator #ifdef I_DEBUG if(m_cmd_fifo.rok()) std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_cmd_fsm = " << ring_cmd_fsm_state_str_i[r_ring_cmd_fsm] << " - fifo ROK : " << m_cmd_fifo.rok() << " - in grant : " << p_ring_in.cmd_grant << " - in preempt : " << p_ring_in.cmd_preempt << " - in palloc : " << p_ring_in.cmd_palloc << " - in wok : " << p_ring_in.cmd_r << " - fifo data : " << std::hex << m_cmd_fifo.read() << std::endl; #endif if(p_ring_in.cmd_preempt) break; if(m_cmd_fifo.rok() && p_ring_in.cmd_r) { cmd_fifo_get = true; bool eop = ((int) (m_cmd_fifo.read() >> (ring_cmd_data_size - 1) ) & 0x1) == 1; if (eop && !p_ring_in.cmd_palloc && p_ring_in.cmd_grant) { r_ring_cmd_fsm = OWNER; } else if (eop && !p_ring_in.cmd_palloc && !p_ring_in.cmd_grant) { r_ring_cmd_fsm = CMD_IDLE; } else if (eop && p_ring_in.cmd_palloc) { r_ring_cmd_fsm = WAIT_PALLOC_END; } } break; case WAIT_PALLOC_END: // stay here and keep token till last flit from Init Gate, ring is preempted bool eop = ((int) (p_ring_in.cmd_data >> (ring_cmd_data_size - 1) ) & 0x1) == 1; #ifdef I_DEBUG if(p_ring_in.cmd_w) std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_cmd_fsm = " << ring_cmd_fsm_state_str_i[r_ring_cmd_fsm] << " - palloc : " << p_ring_in.cmd_palloc << " - in grant : " << p_ring_in.cmd_grant << " - in preempt : " << p_ring_in.cmd_preempt << " - in rok : " << p_ring_in.cmd_w << " - in wok : " << p_ring_in.cmd_r << " - in data : " << std::hex << p_ring_in.cmd_data << " - eop : " << eop << std::endl; #endif if(p_ring_in.cmd_w && p_ring_in.cmd_r && eop) // last flit from init gate { if (p_ring_in.cmd_grant) r_ring_cmd_fsm = OWNER; else r_ring_cmd_fsm = CMD_IDLE; } break; } // end switch ring cmd fsm /////////// RING RSP FSM //////////////////////// switch( r_ring_rsp_fsm ) { case RSP_IDLE: { uint32_t rsrcid = (uint32_t) ((sc_dt::sc_uint) ((p_ring_in.rsp_data >> (ring_rsp_data_size-m_x_width-m_y_width - 1)) << (vci_param::S-m_x_width-m_y_width))); bool islocal = m_lt[rsrcid] && (m_rt[rsrcid] == m_srcid); bool reop = ((p_ring_in.rsp_data >> (ring_rsp_data_size - 1)) & 0x1) == 1; #ifdef I_DEBUG if(p_ring_in.rsp_w) std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_rsp_fsm = " << ring_rsp_fsm_state_str_i[r_ring_rsp_fsm] << " - in rok : " << p_ring_in.rsp_w << " - in data : " << std::hex << p_ring_in.rsp_data << " - rsrcid : " << rsrcid << " - isloc : " << islocal << " - in wok : " << p_ring_in.rsp_r << " - fifo wok : " << m_rsp_fifo.wok() << " - reop : " << reop << std::endl; #endif if (p_ring_in.rsp_w && islocal) { rsp_fifo_put = m_rsp_fifo.wok(); rsp_fifo_data = p_ring_in.rsp_data; if (reop && m_rsp_fifo.wok()) r_ring_rsp_fsm = RSP_IDLE; else r_ring_rsp_fsm = ALLOC; } else if (p_ring_in.rsp_w && !islocal) { if (reop && p_ring_in.rsp_r) r_ring_rsp_fsm = RSP_IDLE; else r_ring_rsp_fsm = NALLOC; } else // !p_ring_in.rsp_w { r_ring_rsp_fsm = RSP_IDLE; } } break; case ALLOC: { bool reop = ((p_ring_in.rsp_data >> (ring_rsp_data_size - 1)) & 0x1) == 1; #ifdef I_DEBUG if(p_ring_in.rsp_w) std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_rsp_fsm = " << ring_rsp_fsm_state_str_i[r_ring_rsp_fsm] << " - in rok : " << p_ring_in.rsp_w << " - in wok : " << p_ring_in.rsp_r << " - fifo wok : " << m_rsp_fifo.wok() << " - in data : " << std::hex << p_ring_in.rsp_data << " - reop : " << reop << std::endl; #endif if (p_ring_in.rsp_w && m_rsp_fifo.wok() && reop) { rsp_fifo_put = true; rsp_fifo_data = p_ring_in.rsp_data; r_ring_rsp_fsm = RSP_IDLE; } else // !p_ring_in.rsp_w || !m_rsp_fifo.wok() || !reop { rsp_fifo_put = p_ring_in.rsp_w && m_rsp_fifo.wok(); rsp_fifo_data = p_ring_in.rsp_data; r_ring_rsp_fsm = ALLOC; } } break; case NALLOC: { #ifdef I_DEBUG if(p_ring_in.rsp_w) std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_rsp_fsm = " << ring_rsp_fsm_state_str_i[r_ring_rsp_fsm] << " - preempt : " << p_ring_in.rsp_preempt << " - palloc : " << p_ring_in.rsp_palloc << " - header : " << p_ring_in.rsp_header << " - in rok : " << p_ring_in.rsp_w << " - in data : " << std::hex << p_ring_in.rsp_data << " - in wok : " << p_ring_in.rsp_r << " - fifo wok : " << m_rsp_fifo.wok() << std::endl; #endif bool reop = ((p_ring_in.rsp_data >> (ring_rsp_data_size - 1)) & 0x1) == 1; if(p_ring_in.rsp_preempt) { uint32_t rsrcid = (uint32_t) ((sc_dt::sc_uint) ((p_ring_in.rsp_data >> ring_rsp_data_size-m_x_width-m_y_width) << (vci_param::S-m_x_width-m_y_width))); bool islocal = m_lt[rsrcid] && (m_rt[rsrcid] == m_srcid); if(p_ring_in.rsp_header) { if (islocal) { rsp_fifo_put = m_rsp_fifo.wok(); rsp_fifo_data = p_ring_in.rsp_data; if (!reop) r_ring_rsp_fsm = PALLOC2; } } else // !header { // palloc=1, means IG is not allocated, thus, if last flit, all inits must be in IDLE state if (reop && p_ring_in.rsp_r && (p_ring_in.rsp_palloc == 1)) r_ring_rsp_fsm = RSP_IDLE; else r_ring_rsp_fsm = NALLOC; } } else // !preempt { if(p_ring_in.rsp_w && reop && p_ring_in.rsp_r && !p_ring_in.rsp_palloc) r_ring_rsp_fsm = RSP_IDLE; else r_ring_rsp_fsm = NALLOC; } } break; case PALLOC2: #ifdef I_DEBUG if(p_ring_in.rsp_w) std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_rsp_fsm = " << ring_rsp_fsm_state_str_i[r_ring_rsp_fsm] << " - in preempt : " << p_ring_in.rsp_preempt << " - in rok : " << p_ring_in.rsp_w << " - in data : " << std::hex << p_ring_in.rsp_data << " - in wok : " << p_ring_in.rsp_r << " - fifo wok : " << m_rsp_fifo.wok() << std::endl; #endif { bool eop = ( (int) ((p_ring_in.rsp_data >> (ring_rsp_data_size - 1) ) & 0x1) == 1); if(p_ring_in.rsp_preempt) { rsp_fifo_put = m_rsp_fifo.wok(); rsp_fifo_data = p_ring_in.rsp_data; if(eop && m_rsp_fifo.wok()) r_ring_rsp_fsm = NALLOC; else r_ring_rsp_fsm = PALLOC2; break; } if(p_ring_in.rsp_w && p_ring_in.rsp_r && eop) { r_ring_rsp_fsm = PALLOC1; } } break; case PALLOC1: #ifdef I_DEBUG std::cout << std::dec << sc_time_stamp() << " - " << m_name << " - ring_rsp_fsm = " << ring_rsp_fsm_state_str_i[r_ring_rsp_fsm] << " - in preempt : " << p_ring_in.rsp_preempt << " - in rok : " << p_ring_in.rsp_w << " - in data : " << std::hex << p_ring_in.rsp_data << " - in wok : " << p_ring_in.rsp_r << " - fifo wok : " << m_rsp_fifo.wok() << std::endl; #endif { bool eop = ( (int) ((p_ring_in.rsp_data >> (ring_rsp_data_size - 1) ) & 0x1) == 1); if ( p_ring_in.rsp_preempt && m_rsp_fifo.wok() && eop ) { rsp_fifo_put = true; rsp_fifo_data = p_ring_in.rsp_data; r_ring_rsp_fsm = RSP_IDLE; } else // !p_ring_in.rsp_w || !m_rsp_fifo.wok() || !eop { rsp_fifo_put = p_ring_in.rsp_preempt && m_rsp_fifo.wok(); rsp_fifo_data = p_ring_in.rsp_data; r_ring_rsp_fsm = PALLOC1; } } break; } // end switch rsp fsm //////////////////////// // fifos update // //////////////////////// //-- to keep trace on ring traffic : a valid initiator command is being sent init_cmd.cmdval = cmd_fifo_get; init_cmd.flit = m_cmd_fifo.read(); init_cmd.state = ring_cmd_fsm_state_str_i[r_ring_cmd_fsm]; //init_cmd_val = cmd_fifo_get; init_rsp_val = rsp_fifo_put; // local cmd fifo update if ( cmd_fifo_put && cmd_fifo_get ) m_cmd_fifo.put_and_get(cmd_fifo_data); else if ( cmd_fifo_put && !cmd_fifo_get ) m_cmd_fifo.simple_put(cmd_fifo_data); else if ( !cmd_fifo_put && cmd_fifo_get ) m_cmd_fifo.simple_get(); // local rsp fifo update if ( rsp_fifo_put && rsp_fifo_get ) m_rsp_fifo.put_and_get(rsp_fifo_data); else if ( rsp_fifo_put && !rsp_fifo_get ) m_rsp_fifo.simple_put(rsp_fifo_data); else if ( !rsp_fifo_put && rsp_fifo_get ) m_rsp_fifo.simple_get(); } // end Transition() /////////////////////////////////////////////////////////////////// void genMoore(cmd_in_t &p_cmd_in, rsp_out_t &p_rsp_out) /////////////////////////////////////////////////////////////////// { p_rsp_out.write = m_rsp_fifo.rok(); p_rsp_out.data = (sc_dt::sc_uint) m_rsp_fifo.read(); p_cmd_in.read= m_cmd_fifo.wok(); } // end genMoore ///////////////////////////////////////////////////////////////////////////// void update_ring_signals(ring_signal_t p_ring_in, ring_signal_t &p_ring_out) //////////////////////////////////////////////////////////////////////////// { switch( r_ring_cmd_fsm ) { case CMD_IDLE: p_ring_out.cmd_grant = !m_cmd_fifo.rok() && p_ring_in.cmd_grant; p_ring_out.cmd_palloc = p_ring_in.cmd_palloc; p_ring_out.cmd_preempt = p_ring_in.cmd_preempt; p_ring_out.cmd_w = p_ring_in.cmd_w; p_ring_out.cmd_data = p_ring_in.cmd_data; break; case OWNER: { bool eop = ((int) ((m_cmd_fifo.read() >> (ring_cmd_data_size - 1) ) & 0x1) == 1); bool brdcst = (m_cmd_fifo.read() & 0x1 == 0x1); p_ring_out.cmd_grant = (!m_cmd_fifo.rok() || (eop && p_ring_in.cmd_r)) ; p_ring_out.cmd_palloc = 0; //p_ring_in.cmd_palloc; p_ring_out.cmd_preempt = 0; //p_ring_in.cmd_preempt; p_ring_out.cmd_w = m_cmd_fifo.rok() && !brdcst; p_ring_out.cmd_data = m_cmd_fifo.read(); } break; case BDC_FIRST: p_ring_out.cmd_palloc = p_ring_in.cmd_palloc; p_ring_out.cmd_preempt = p_ring_in.cmd_preempt; p_ring_out.cmd_grant = false; // if cmd_preempt : Init Gate is sending to Local Target, ring preempted if (p_ring_in.cmd_preempt) { p_ring_out.cmd_w = p_ring_in.cmd_w; p_ring_out.cmd_data = p_ring_in.cmd_data; } else { p_ring_out.cmd_w = true; p_ring_out.cmd_data = r_brdcst_save | ((((uint64_t) r_cpt_tgt.read()) & 0xF) << 0x1); } break; case BDC_SECOND: p_ring_out.cmd_palloc = p_ring_in.cmd_palloc; p_ring_out.cmd_preempt = p_ring_in.cmd_preempt; // if cmd_preempt : Init Gate is sending to Local Target, ring preempted if (p_ring_in.cmd_preempt) { p_ring_out.cmd_w = p_ring_in.cmd_w; p_ring_out.cmd_data = p_ring_in.cmd_data; p_ring_out.cmd_grant = 0; } else { p_ring_out.cmd_grant = m_cmd_fifo.rok() && p_ring_in.cmd_r && (r_cpt_tgt.read() == 0); p_ring_out.cmd_w = m_cmd_fifo.rok(); p_ring_out.cmd_data = m_cmd_fifo.read(); } break; case SENDING: { bool eop = ((int) (m_cmd_fifo.read() >> (ring_cmd_data_size - 1) ) & 0x1) == 1; p_ring_out.cmd_palloc = p_ring_in.cmd_palloc; p_ring_out.cmd_preempt = p_ring_in.cmd_preempt; // if cmd_preempt : Init Gate is sending to Local Target, ring preempted if (p_ring_in.cmd_preempt) { p_ring_out.cmd_w = p_ring_in.cmd_w; p_ring_out.cmd_data = p_ring_in.cmd_data; p_ring_out.cmd_grant = 0; } else { p_ring_out.cmd_w = m_cmd_fifo.rok(); p_ring_out.cmd_data = m_cmd_fifo.read(); p_ring_out.cmd_grant = m_cmd_fifo.rok() && p_ring_in.cmd_r && eop && !p_ring_in.cmd_palloc; } } break; case WAIT_PALLOC_END: { bool eop = ((int) (p_ring_in.cmd_data >> (ring_cmd_data_size - 1) ) & 0x1) == 1; // No need to test preempt here // In this state, we're sure that only IG can transmit, all other IL but this, are in IDLE state p_ring_out.cmd_grant = p_ring_in.cmd_w && p_ring_in.cmd_r && eop; p_ring_out.cmd_palloc = p_ring_in.cmd_palloc; p_ring_out.cmd_preempt = p_ring_in.cmd_preempt; p_ring_out.cmd_w = p_ring_in.cmd_w; //p_ring_in.cmd_preempt; p_ring_out.cmd_data = p_ring_in.cmd_data; } break; } // end switch p_ring_out.cmd_header = p_ring_in.cmd_header; p_ring_out.cmd_r = p_ring_in.cmd_r; p_ring_out.rsp_w = p_ring_in.rsp_w; p_ring_out.rsp_data = p_ring_in.rsp_data; p_ring_out.rsp_grant = p_ring_in.rsp_grant; p_ring_out.rsp_preempt = p_ring_in.rsp_preempt; p_ring_out.rsp_header = p_ring_in.rsp_header; p_ring_out.rsp_palloc = p_ring_in.rsp_palloc; switch( r_ring_rsp_fsm ) { case RSP_IDLE: { uint32_t rsrcid = (uint32_t) ((sc_dt::sc_uint) ((p_ring_in.rsp_data >> (ring_rsp_data_size-m_x_width-m_y_width - 1)) << (vci_param::S-m_x_width-m_y_width))); bool islocal = m_lt[rsrcid] && (m_rt[rsrcid] == m_srcid); if(p_ring_in.rsp_w && islocal) p_ring_out.rsp_r = m_rsp_fifo.wok(); else p_ring_out.rsp_r = p_ring_in.rsp_r; } break; case ALLOC: p_ring_out.rsp_r = m_rsp_fifo.wok(); break; case NALLOC: { uint32_t rsrcid = (uint32_t) ((sc_dt::sc_uint) ((p_ring_in.rsp_data >> ring_rsp_data_size-m_x_width-m_y_width) << (vci_param::S-m_x_width-m_y_width))); bool islocal = m_lt[rsrcid] && (m_rt[rsrcid] == m_srcid); if (p_ring_in.rsp_preempt && p_ring_in.rsp_header && islocal) p_ring_out.rsp_r = m_rsp_fifo.wok(); else p_ring_out.rsp_r = p_ring_in.rsp_r; } break; case PALLOC2: if(p_ring_in.rsp_preempt) p_ring_out.rsp_r = m_rsp_fifo.wok(); else p_ring_out.rsp_r = p_ring_in.rsp_r; break; case PALLOC1: p_ring_out.rsp_r = m_rsp_fifo.wok(); break; } // end switch } // end update_ring_signals #ifdef I_STATS void print_stats() { std::cout << m_name << " , " << m_cpt << " , " << flits_sent << " , " << tok_wait << " , " << fifo_full << " , " << preempt << " , " << palloc_wait << std::endl; } #endif }; }} // end namespace #endif // DSPIN_LOCAL_RING_INITIATOR_FAST_H