/* -*- 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 : Cesar Armando Fuguet Tortolero * Date : jul 2015 * Copyright: UPMC - LIP6 */ #include #include "synthetic_dspin_network.h" #include "dspin_router_config.h" #include "alloc_elems.h" namespace soclib { namespace caba { using namespace soclib::common; SyntheticDspinNetwork::SyntheticDspinNetwork(sc_module_name name, const size_t x_size, const size_t y_size, const size_t load) : BaseModule(name), p_clk("p_clk"), p_resetn("p_resetn"), m_x_size(x_size), m_y_size(y_size) { // DSPIN packet generator instantiation dspinGenerator = (DspinNetworkGenerator**) malloc(sizeof(DspinNetworkGenerator*) * m_x_size); for (size_t x = 0; x < m_x_size; ++x) { dspinGenerator[x] = (DspinNetworkGenerator*) malloc(sizeof(DspinNetworkGenerator) * m_y_size); for (size_t y = 0; y < m_y_size; ++y) { std::ostringstream generator_name; const int SRCID = (x << Y_WIDTH) | y; generator_name << "generator[" << x << "][" << y << "]"; #if UNICAST const size_t PACKET_LENGTH = 8; new(&dspinGenerator[x][y]) DspinNetworkGenerator(generator_name.str().c_str(), (size_t)SRCID, PACKET_LENGTH, load, (size_t)DSPIN_GENERATOR_FIFO_DEPTH, 0 ); #else new(&dspinGenerator[x][y]) DspinNetworkGenerator(generator_name.str().c_str(), m_x_size, m_y_size, SRCID, load, DSPIN_GENERATOR_FIFO_DEPTH); #endif } } // DSPIN router instantiation dspinRouter = (DspinNetworkRouter**) malloc(sizeof(DspinNetworkRouter*) * m_x_size); for (size_t x = 0; x < m_x_size; ++x) { dspinRouter[x] = (DspinNetworkRouter*) malloc(sizeof(DspinNetworkRouter) * m_y_size); for (size_t y = 0; y < m_y_size; ++y) { std::ostringstream router_name; const bool BROADCAST_SUPPORTED = true; const bool CONFIGURATION_SUPPORTED = true; router_name << "router[" << x << "][" << y << "]"; new(&dspinRouter[x][y]) DspinNetworkRouter(router_name.str().c_str(), x, y, X_WIDTH, Y_WIDTH, DSPIN_ROUTER_FIFO_DEPTH, DSPIN_ROUTER_FIFO_DEPTH, BROADCAST_SUPPORTED, CONFIGURATION_SUPPORTED); } } // signals instantiation sL = alloc_elems("sL", m_x_size, m_y_size, 2); sH = alloc_elems("sH", m_x_size + 1, m_y_size, 2); sV = alloc_elems("sV", m_x_size, m_y_size + 1, 2); sConfigRouter = alloc_elems >("sConfigRouter", m_x_size, m_y_size); // netlist for (size_t x = 0; x < m_x_size; ++x) { for (size_t y = 0; y < m_y_size; ++y) { dspinRouter[x][y].p_clk(p_clk); dspinRouter[x][y].p_resetn(p_resetn); dspinRouter[x][y].p_in[DspinNetworkRouter::N](sV[x][y + 1][1]); dspinRouter[x][y].p_out[DspinNetworkRouter::N](sV[x][y + 1][0]); dspinRouter[x][y].p_in[DspinNetworkRouter::S](sV[x][y][0]); dspinRouter[x][y].p_out[DspinNetworkRouter::S](sV[x][y][1]); dspinRouter[x][y].p_in[DspinNetworkRouter::E](sH[x + 1][y][1]); dspinRouter[x][y].p_out[DspinNetworkRouter::E](sH[x + 1][y][0]); dspinRouter[x][y].p_in[DspinNetworkRouter::W](sH[x][y][0]); dspinRouter[x][y].p_out[DspinNetworkRouter::W](sH[x][y][1]); dspinRouter[x][y].p_in[DspinNetworkRouter::L](sL[x][y][0]); dspinRouter[x][y].p_out[DspinNetworkRouter::L](sL[x][y][1]); dspinRouter[x][y].bind_recovery_port(sConfigRouter[x][y]); dspinGenerator[x][y].p_clk(p_clk); dspinGenerator[x][y].p_resetn(p_resetn); dspinGenerator[x][y].p_out(sL[x][y][0]); dspinGenerator[x][y].p_in(sL[x][y][1]); } } } // end constructor() SyntheticDspinNetwork::~SyntheticDspinNetwork() { for (size_t x = 0; x < m_x_size; ++x) { for (size_t y = 0; y < m_y_size; ++y) { #if UNICAST dspinGenerator[x][y].~DspinPacketGenerator(); #else dspinGenerator[x][y].~DspinBroadcastGenerator(); #endif dspinRouter[x][y].~DspinRouter(); } free(dspinGenerator[x]); free(dspinRouter[x]); } free(dspinGenerator); free(dspinRouter); dealloc_elems(sL, m_x_size, m_y_size, 2); dealloc_elems(sH, m_x_size + 1, m_y_size, 2); dealloc_elems(sV, m_x_size, m_y_size + 1, 2); dealloc_elems >(sConfigRouter, m_x_size, m_y_size); } static inline uint32_t configRouter(int reallocation_dir, int recovery_mode, int blackhole_pos) { return ((reallocation_dir & 0x7) << 5) | ((recovery_mode & 0x1) << 4) | (blackhole_pos & 0xF); } void SyntheticDspinNetwork::reset() { // initialize routers' configuration signals for (size_t x = 0; x < m_x_size; ++x) { for (size_t y = 0; y < m_y_size; ++y) { const uint32_t CONFIG_NONE = configRouter(0, 0, NORMAL); sConfigRouter[x][y].write(CONFIG_NONE); } } // initialize mesh's boundary signals for (size_t x = 0; x < m_x_size; ++x) { sV[x][0][0].write = false; sV[x][0][1].read = true; sV[x][m_y_size][0].read = true; sV[x][m_y_size][1].write = false; } for (size_t y = 0; y < m_y_size; ++y) { sH[0][y][0].write = false; sH[0][y][1].read = true; sH[m_x_size][y][0].read = true; sH[m_x_size][y][1].write = false; } } // end reset() void SyntheticDspinNetwork::set_faulty_router(const size_t faulty_x, const size_t faulty_y) { assert(faulty_x < m_x_size); assert(faulty_y < m_y_size); // transform the faulty router in a black-hole dspinRouter[faulty_x][faulty_y].set_disable_mask(0x1F); // reconfigure the faulty router's contour if (faulty_y < (m_y_size - 1)) { const uint32_t CONFIG_N = configRouter(REQ_SOUTH, 1, N_OF_X); sConfigRouter[faulty_x][faulty_y + 1].write(CONFIG_N); if (faulty_x > 0) { const uint32_t CONFIG_NW = configRouter(REQ_EAST, 1, NW_OF_X); sConfigRouter[faulty_x - 1][faulty_y + 1].write(CONFIG_NW); } if (faulty_x < (m_x_size - 1)) { const uint32_t CONFIG_NE = configRouter(REQ_WEST, 1, NE_OF_X); sConfigRouter[faulty_x + 1][faulty_y + 1].write(CONFIG_NE); } } if (faulty_y > 0) { const uint32_t CONFIG_S = configRouter(REQ_NORTH, 1, S_OF_X); sConfigRouter[faulty_x][faulty_y - 1].write(CONFIG_S); if (faulty_x > 0) { const uint32_t CONFIG_SW = configRouter(REQ_EAST, 1, SW_OF_X); sConfigRouter[faulty_x - 1][faulty_y - 1].write(CONFIG_SW); } if (faulty_x < (m_x_size - 1)) { const uint32_t CONFIG_SE = configRouter(REQ_WEST, 1, SE_OF_X); sConfigRouter[faulty_x + 1][faulty_y - 1].write(CONFIG_SE); } } if (faulty_x > 0) { const uint32_t CONFIG_W = configRouter(REQ_EAST, 1, W_OF_X); sConfigRouter[faulty_x - 1][faulty_y].write(CONFIG_W); } if (faulty_x < (m_x_size - 1)) { const uint32_t CONFIG_E = configRouter(REQ_WEST, 1, E_OF_X); sConfigRouter[faulty_x + 1][faulty_y].write(CONFIG_E); } } // end set_faulty_router() void SyntheticDspinNetwork::print_stats(const size_t x, const size_t y) { assert(x < m_x_size); assert(y < m_y_size); dspinGenerator[x][y].print_stats(); } } // end namespace caba } // end namespace soclib // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: ts=4 : sts=4 : sw=4 : et