#include "model/electrical/MultiplexerCrossbar.h" #include #include #include "model/PortInfo.h" #include "model/EventInfo.h" #include "model/TransitionInfo.h" #include "model/timing_graph/ElectricalNet.h" #include "model/electrical/Multiplexer.h" namespace DSENT { using std::ceil; using std::vector; MultiplexerCrossbar::MultiplexerCrossbar(const String& instance_name_, const TechModel* tech_model_) : ElectricalModel(instance_name_, tech_model_) { initParameters(); initProperties(); } MultiplexerCrossbar::~MultiplexerCrossbar() {} void MultiplexerCrossbar::initParameters() { addParameterName("NumberInputs"); addParameterName("NumberOutputs"); addParameterName("NumberBits"); addParameterName("BitDuplicate", "TRUE"); return; } void MultiplexerCrossbar::initProperties() { return; } MultiplexerCrossbar* MultiplexerCrossbar::clone() const { // TODO return NULL; } void MultiplexerCrossbar::constructModel() { // Get Parameters unsigned int number_inputs = getParameter("NumberInputs").toUInt(); unsigned int number_outputs = getParameter("NumberOutputs").toUInt(); unsigned int number_bits = getParameter("NumberBits").toUInt(); bool bit_duplicate = getParameter("BitDuplicate").toBool(); ASSERT(number_inputs > 0, "[Error] " + getInstanceName() + " -> Number of inputs must be > 0!"); ASSERT(number_outputs > 0, "[Error] " + getInstanceName() + " -> Number of outputs must be > 0!"); ASSERT(number_bits > 0, "[Error] " + getInstanceName() + " -> Number of bits must be > 0!"); unsigned int number_selects = (unsigned int)ceil(log2((double)number_inputs)); getGenProperties()->set("NumberSelectsPerPort", number_selects); // Construct electrical ports and nets // Create input ports for(unsigned int i = 0; i < number_inputs; ++i) { createInputPort("In" + (String)i, makeNetIndex(0, number_bits-1)); } // Create select signals for(unsigned int i = 0; i < number_outputs; ++i) { for(unsigned int j = 0; j < number_selects; ++j) { createInputPort(String::format("Sel%d_%d", i, j)); } } // Create output ports for(unsigned int i = 0; i < number_outputs; ++i) { createOutputPort("Out" + (String)i, makeNetIndex(0, number_bits-1)); } // Create energy, power, and area results addAreaResult(new AtomicResult("CrossbarWire")); addAreaResult(new AtomicResult("CrossbarFill")); createElectricalResults(); getEventInfo("Idle")->setStaticTransitionInfos(); createElectricalEventResult("Multicast0"); getEventInfo("Multicast0")->setStaticTransitionInfos(); for(unsigned int i = 1; i <= number_outputs; ++i) { createElectricalEventResult("Multicast" + (String)i); EventInfo* event_info = getEventInfo("Multicast" + (String)i); // Assuming that In0 is sending to Out0, Out1, ..., Outi // and other input ports are static for(unsigned int j = 1; j < number_inputs; ++j) { event_info->setStaticTransitionInfo("In" + (String)j); } for(unsigned int j = i; j < number_outputs; ++j) { for(unsigned int k = 0; k < number_selects; ++k) { event_info->setStaticTransitionInfo(String::format("Sel%d_%d", j, k)); } } } createElectricalEventResult("Crossbar"); // Initiate multiplexers vector mux_names(number_outputs, ""); vector muxs(number_outputs, NULL); for(unsigned int i = 0; i < number_outputs; ++i) { mux_names[i] = "Mux" + (String)i; muxs[i] = new Multiplexer(mux_names[i], getTechModel()); muxs[i]->setParameter("NumberInputs", number_inputs); muxs[i]->setParameter("NumberBits", number_bits); muxs[i]->setParameter("BitDuplicate", bit_duplicate); muxs[i]->construct(); } // Connect inputs and outputs to multiplexers for(unsigned int i = 0; i < number_outputs; ++i) { // Connect inputs for(unsigned int j = 0; j < number_inputs; ++j) { portConnect(muxs[i], "In" + (String)j, "In" + (String)j, makeNetIndex(0, number_bits-1)); } // Connect select signals for(unsigned int j = 0; j < number_selects; ++j) { portConnect(muxs[i], "Sel" + (String)j, String::format("Sel%d_%d", i, j)); } // Connect outputs portConnect(muxs[i], "Out", "Out" + (String)i, makeNetIndex(0, number_bits-1)); } // Add area, power, and event results for each mux for(unsigned int i = 0; i < number_outputs; ++i) { addSubInstances(muxs[i], 1.0); addElectricalSubResults(muxs[i], 1.0); for(unsigned int j = 0; j <= number_outputs; ++j) { getEventResult("Multicast" + (String)j)->addSubResult(muxs[i]->getEventResult("Mux"), mux_names[i], 1.0); } getEventResult("Crossbar")->addSubResult(muxs[i]->getEventResult("Mux"), mux_names[i], 1.0); } // Estimate wiring area const String& crossbar_wire_layer = "Intermediate"; addElectricalWireSubResult(crossbar_wire_layer, getAreaResult("CrossbarWire"), "Self", 1.0); double wire_width = getTechModel()->get("Wire->" + crossbar_wire_layer + "->MinWidth").toDouble(); double wire_spacing = getTechModel()->get("Wire->" + crossbar_wire_layer + "->MinSpacing").toDouble(); double wire_pitch = wire_width + wire_spacing; double wire_area = (number_bits * number_inputs * wire_pitch) * (number_bits * number_outputs * wire_pitch); getAreaResult("CrossbarWire")->setValue(wire_area); // Add filler area getAreaResult("Active")->addSubResult(getAreaResult("CrossbarFill"), "Self", 1.0); return; } void MultiplexerCrossbar::updateModel() { // Update all sub instances Model::updateModel(); // Update filler area // Total Active area = max(stdcell active area, wiring area); double wire_area = getAreaResult("CrossbarWire")->calculateSum(); double active_area = getAreaResult("Active")->calculateSum(); double fill_area = 0.0; if(active_area < wire_area) { fill_area = wire_area - active_area; } getAreaResult("CrossbarFill")->setValue(fill_area); return; } void MultiplexerCrossbar::propagateTransitionInfo() { // The only thing can be updated are the input probabilities const unsigned int number_inputs = getParameter("NumberInputs").toUInt(); const unsigned int number_outputs = getParameter("NumberOutputs").toUInt(); const unsigned int number_selects = getGenProperties()->get("NumberSelectsPerPort").toUInt(); for(unsigned int i = 0; i < number_outputs; ++i) { ElectricalModel* muxi = (ElectricalModel*)getSubInstance("Mux" + (String)i); for(unsigned int j = 0; j < number_inputs; ++j) { propagatePortTransitionInfo(muxi, "In" + (String)j, "In" + (String)j); } for(unsigned int j = 0; j < number_selects; ++j) { propagatePortTransitionInfo(muxi, "Sel" + (String)j, String::format("Sel%d_%d", i, j)); } muxi->use(); // Set output probability propagatePortTransitionInfo("Out" + (String)i, muxi, "Out"); } return; } } // namespace DSENT