| /* Copyright (c) 2012 Massachusetts Institute of Technology |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to deal |
| * in the Software without restriction, including without limitation the rights |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| * THE SOFTWARE. |
| */ |
| |
| #include "model/electrical/MultiplexerCrossbar.h" |
| |
| #include <vector> |
| #include <cmath> |
| |
| #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<String> mux_names(number_outputs, ""); |
| vector<Multiplexer*> 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 |
| |