1/* Copyright (c) 2012 Massachusetts Institute of Technology 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to deal 5 * in the Software without restriction, including without limitation the rights 6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 * copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 * THE SOFTWARE. 20 */ 21 22#include "model/electrical/MultiplexerCrossbar.h" 23 24#include <vector> 25#include <cmath> 26 27#include "model/PortInfo.h" 28#include "model/EventInfo.h" 29#include "model/TransitionInfo.h" 30#include "model/timing_graph/ElectricalNet.h" 31#include "model/electrical/Multiplexer.h" 32 33namespace DSENT 34{ 35 using std::ceil; 36 using std::vector; 37 38 MultiplexerCrossbar::MultiplexerCrossbar(const String& instance_name_, const TechModel* tech_model_) 39 : ElectricalModel(instance_name_, tech_model_) 40 { 41 initParameters(); 42 initProperties(); 43 } 44 45 MultiplexerCrossbar::~MultiplexerCrossbar() 46 {} 47 48 void MultiplexerCrossbar::initParameters() 49 { 50 addParameterName("NumberInputs"); 51 addParameterName("NumberOutputs"); 52 addParameterName("NumberBits"); 53 addParameterName("BitDuplicate", "TRUE"); 54 return; 55 } 56 57 void MultiplexerCrossbar::initProperties() 58 { 59 return; 60 } 61 62 MultiplexerCrossbar* MultiplexerCrossbar::clone() const 63 { 64 // TODO 65 return NULL; 66 } 67 68 void MultiplexerCrossbar::constructModel() 69 { 70 // Get Parameters 71 unsigned int number_inputs = getParameter("NumberInputs").toUInt(); 72 unsigned int number_outputs = getParameter("NumberOutputs").toUInt(); 73 unsigned int number_bits = getParameter("NumberBits").toUInt(); 74 bool bit_duplicate = getParameter("BitDuplicate").toBool(); 75 76 ASSERT(number_inputs > 0, "[Error] " + getInstanceName() + " -> Number of inputs must be > 0!"); 77 ASSERT(number_outputs > 0, "[Error] " + getInstanceName() + " -> Number of outputs must be > 0!"); 78 ASSERT(number_bits > 0, "[Error] " + getInstanceName() + " -> Number of bits must be > 0!"); 79 80 unsigned int number_selects = (unsigned int)ceil(log2((double)number_inputs)); 81 getGenProperties()->set("NumberSelectsPerPort", number_selects); 82 83 // Construct electrical ports and nets 84 // Create input ports 85 for(unsigned int i = 0; i < number_inputs; ++i) 86 { 87 createInputPort("In" + (String)i, makeNetIndex(0, number_bits-1)); 88 } 89 // Create select signals 90 for(unsigned int i = 0; i < number_outputs; ++i) 91 { 92 for(unsigned int j = 0; j < number_selects; ++j) 93 { 94 createInputPort(String::format("Sel%d_%d", i, j)); 95 } 96 } 97 // Create output ports 98 for(unsigned int i = 0; i < number_outputs; ++i) 99 { 100 createOutputPort("Out" + (String)i, makeNetIndex(0, number_bits-1)); 101 } 102 103 // Create energy, power, and area results 104 addAreaResult(new AtomicResult("CrossbarWire")); 105 addAreaResult(new AtomicResult("CrossbarFill")); 106 createElectricalResults(); 107 getEventInfo("Idle")->setStaticTransitionInfos(); 108 createElectricalEventResult("Multicast0"); 109 getEventInfo("Multicast0")->setStaticTransitionInfos(); 110 for(unsigned int i = 1; i <= number_outputs; ++i) 111 { 112 createElectricalEventResult("Multicast" + (String)i); 113 EventInfo* event_info = getEventInfo("Multicast" + (String)i); 114 // Assuming that In0 is sending to Out0, Out1, ..., Outi 115 // and other input ports are static 116 for(unsigned int j = 1; j < number_inputs; ++j) 117 { 118 event_info->setStaticTransitionInfo("In" + (String)j); 119 } 120 for(unsigned int j = i; j < number_outputs; ++j) 121 { 122 for(unsigned int k = 0; k < number_selects; ++k) 123 { 124 event_info->setStaticTransitionInfo(String::format("Sel%d_%d", j, k)); 125 } 126 } 127 } 128 createElectricalEventResult("Crossbar"); 129 130 // Initiate multiplexers 131 vector<String> mux_names(number_outputs, ""); 132 vector<Multiplexer*> muxs(number_outputs, NULL); 133 for(unsigned int i = 0; i < number_outputs; ++i) 134 { 135 mux_names[i] = "Mux" + (String)i; 136 muxs[i] = new Multiplexer(mux_names[i], getTechModel()); 137 muxs[i]->setParameter("NumberInputs", number_inputs); 138 muxs[i]->setParameter("NumberBits", number_bits); 139 muxs[i]->setParameter("BitDuplicate", bit_duplicate); 140 muxs[i]->construct(); 141 } 142 143 // Connect inputs and outputs to multiplexers 144 for(unsigned int i = 0; i < number_outputs; ++i) 145 { 146 // Connect inputs 147 for(unsigned int j = 0; j < number_inputs; ++j) 148 { 149 portConnect(muxs[i], "In" + (String)j, "In" + (String)j, makeNetIndex(0, number_bits-1)); 150 } 151 152 // Connect select signals 153 for(unsigned int j = 0; j < number_selects; ++j) 154 { 155 portConnect(muxs[i], "Sel" + (String)j, String::format("Sel%d_%d", i, j)); 156 } 157 158 // Connect outputs 159 portConnect(muxs[i], "Out", "Out" + (String)i, makeNetIndex(0, number_bits-1)); 160 } 161 162 // Add area, power, and event results for each mux 163 for(unsigned int i = 0; i < number_outputs; ++i) 164 { 165 addSubInstances(muxs[i], 1.0); 166 addElectricalSubResults(muxs[i], 1.0); 167 for(unsigned int j = 0; j <= number_outputs; ++j) 168 { 169 getEventResult("Multicast" + (String)j)->addSubResult(muxs[i]->getEventResult("Mux"), mux_names[i], 1.0); 170 } 171 getEventResult("Crossbar")->addSubResult(muxs[i]->getEventResult("Mux"), mux_names[i], 1.0); 172 } 173 174 // Estimate wiring area 175 const String& crossbar_wire_layer = "Intermediate"; 176 addElectricalWireSubResult(crossbar_wire_layer, getAreaResult("CrossbarWire"), "Self", 1.0); 177 double wire_width = getTechModel()->get("Wire->" + crossbar_wire_layer + "->MinWidth").toDouble(); 178 double wire_spacing = getTechModel()->get("Wire->" + crossbar_wire_layer + "->MinSpacing").toDouble(); 179 double wire_pitch = wire_width + wire_spacing; 180 double wire_area = (number_bits * number_inputs * wire_pitch) * (number_bits * number_outputs * wire_pitch); 181 getAreaResult("CrossbarWire")->setValue(wire_area); 182 183 // Add filler area 184 getAreaResult("Active")->addSubResult(getAreaResult("CrossbarFill"), "Self", 1.0); 185 return; 186 } 187 188 void MultiplexerCrossbar::updateModel() 189 { 190 // Update all sub instances 191 Model::updateModel(); 192 193 // Update filler area 194 // Total Active area = max(stdcell active area, wiring area); 195 double wire_area = getAreaResult("CrossbarWire")->calculateSum(); 196 double active_area = getAreaResult("Active")->calculateSum(); 197 double fill_area = 0.0; 198 if(active_area < wire_area) 199 { 200 fill_area = wire_area - active_area; 201 } 202 getAreaResult("CrossbarFill")->setValue(fill_area); 203 return; 204 } 205 206 void MultiplexerCrossbar::propagateTransitionInfo() 207 { 208 // The only thing can be updated are the input probabilities 209 const unsigned int number_inputs = getParameter("NumberInputs").toUInt(); 210 const unsigned int number_outputs = getParameter("NumberOutputs").toUInt(); 211 212 const unsigned int number_selects = getGenProperties()->get("NumberSelectsPerPort").toUInt(); 213 214 for(unsigned int i = 0; i < number_outputs; ++i) 215 { 216 ElectricalModel* muxi = (ElectricalModel*)getSubInstance("Mux" + (String)i); 217 for(unsigned int j = 0; j < number_inputs; ++j) 218 { 219 propagatePortTransitionInfo(muxi, "In" + (String)j, "In" + (String)j); 220 } 221 for(unsigned int j = 0; j < number_selects; ++j) 222 { 223 propagatePortTransitionInfo(muxi, "Sel" + (String)j, String::format("Sel%d_%d", i, j)); 224 } 225 muxi->use(); 226 227 // Set output probability 228 propagatePortTransitionInfo("Out" + (String)i, muxi, "Out"); 229 } 230 231 return; 232 } 233 234} // namespace DSENT 235 236