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/Multiplexer.h" 23 24#include <cmath> 25 26#include "model/PortInfo.h" 27#include "model/TransitionInfo.h" 28#include "model/EventInfo.h" 29#include "model/timing_graph/ElectricalDriverMultiplier.h" 30#include "model/timing_graph/ElectricalNet.h" 31#include "model/std_cells/StdCell.h" 32#include "model/std_cells/StdCellLib.h" 33 34namespace DSENT 35{ 36 Multiplexer::Multiplexer(const String& instance_name_, const TechModel* tech_model_) 37 : ElectricalModel(instance_name_, tech_model_) 38 { 39 initParameters(); 40 initProperties(); 41 } 42 43 Multiplexer::~Multiplexer() 44 {} 45 46 void Multiplexer::initParameters() 47 { 48 addParameterName("NumberInputs"); 49 addParameterName("NumberBits"); 50 addParameterName("BitDuplicate", "TRUE"); 51 addParameterName("IsTopLevel", "TRUE"); 52 return; 53 } 54 55 void Multiplexer::initProperties() 56 { 57 return; 58 } 59 60 Multiplexer* Multiplexer::clone() const 61 { 62 return NULL; 63 } 64 65 void Multiplexer::constructModel() 66 { 67 // Get parameters 68 unsigned int number_bits = (unsigned int) getParameter("NumberBits"); 69 unsigned int number_inputs = (unsigned int) getParameter("NumberInputs"); 70 unsigned int number_selects = (unsigned int) ceil(log2((double) number_inputs)); 71 bool bit_duplicate = (bool) getParameter("BitDuplicate"); 72 bool is_top_level = getParameter("IsTopLevel").toBool(); 73 74 ASSERT(number_inputs > 0, "[Error] " + getInstanceName() + " -> Number of inputs must be > 0!"); 75 ASSERT(number_bits > 0, "[Error] " + getInstanceName() + " -> Number of bits must be > 0!"); 76 77 //Construct electrical ports and nets 78 //Create each input port 79 for(unsigned int i = 0; i < number_inputs; ++i) 80 createInputPort( "In" + (String) i, makeNetIndex(0, number_bits-1)); 81 //Create select signals 82 for(unsigned int i = 0; i < number_selects; ++i) 83 { 84 createInputPort( "Sel" + (String)i); 85 } 86 //Create output 87 createOutputPort( "Out", makeNetIndex(0, number_bits-1)); 88 89 //Create energy, power, and area results 90 createElectricalResults(); 91 getEventInfo("Idle")->setStaticTransitionInfos(); 92 createElectricalEventResult("Mux"); 93 94 //Number of inputs on the 0 side 95 unsigned int inputs_0 = (unsigned int) ceil((double) number_inputs / 2.0); 96 unsigned int selects_0 = (unsigned int) ceil(log2((double) inputs_0)); 97 //Number of inputs on the 1 side 98 unsigned int inputs_1 = (unsigned int) floor((double) number_inputs / 2.0); 99 unsigned int selects_1 = (unsigned int) ceil(log2((double) inputs_1)); 100 101 //Depending on whether we want to create a 1-bit instance and have it multiplied 102 //up by number of bits or actually instantiate number_bits of 1-bit instances. 103 //Recursively instantiates smaller multiplexers 104 if (bit_duplicate || number_bits == 1) 105 { 106 //If it is just a 1-input multiplexer, just connect output to input and be done 107 if (number_inputs == 1) 108 { 109 assign("Out", "In0"); 110 } 111 else 112 { 113 //If it is more than 1 input, instantiate two sub multiplexers (Mux_way0 and Mux_way1) 114 //and create a final 2:1 mux (muxf) to select between them 115 String mux0_name = "Mux_way0"; 116 String mux1_name = "Mux_way1"; 117 String muxf_name = "Mux2_i" + (String)number_inputs; 118 119 Multiplexer* mux0 = new Multiplexer(mux0_name, getTechModel()); 120 mux0->setParameter("NumberInputs", inputs_0); 121 mux0->setParameter("NumberBits", 1); 122 mux0->setParameter("BitDuplicate", "TRUE"); 123 mux0->setParameter("IsTopLevel", "FALSE"); 124 mux0->construct(); 125 126 Multiplexer* mux1 = new Multiplexer(mux1_name, getTechModel()); 127 mux1->setParameter("NumberInputs", inputs_1); 128 mux1->setParameter("NumberBits", 1); 129 mux1->setParameter("BitDuplicate", "TRUE"); 130 mux1->setParameter("IsTopLevel", "FALSE"); 131 mux1->construct(); 132 133 StdCell* muxf = getTechModel()->getStdCellLib()->createStdCell("MUX2", muxf_name); 134 muxf->construct(); 135 136 // TODO hack 137 // create selector driver at the top level 138 if(is_top_level) 139 { 140 for(unsigned int i = 0; i < number_selects; ++i) 141 { 142 StdCell* selinv0 = getTechModel()->getStdCellLib()->createStdCell("INV", String::format("Sel%dInv0", i)); 143 StdCell* selinv1 = getTechModel()->getStdCellLib()->createStdCell("INV", String::format("Sel%dInv1", i)); 144 selinv0->construct(); 145 selinv1->construct(); 146 147 addSubInstances(selinv0, 1.0); 148 addElectricalSubResults(selinv0, 1.0); 149 addSubInstances(selinv1, 1.0); 150 addElectricalSubResults(selinv1, 1.0); 151 getEventResult("Mux")->addSubResult(selinv0->getEventResult("INV"), String::format("Sel%dInv0", i), 1.0); 152 getEventResult("Mux")->addSubResult(selinv1->getEventResult("INV"), String::format("Sel%dInv1", i), 1.0); 153 } 154 } 155 156 //Create outputs of way0 and way1 multiplexers with final mux 157 createNet("way0Out"); 158 createNet("way1Out"); 159 portConnect(mux0, "Out", "way0Out"); 160 portConnect(mux1, "Out", "way1Out"); 161 portConnect(muxf, "A", "way0Out"); 162 portConnect(muxf, "B", "way1Out"); 163 164 // TODO hack 165 // Connect selector bits 166 if(is_top_level) 167 { 168 for(unsigned int i = 0; i < number_selects; ++i) 169 { 170 ElectricalModel* selinv0 = (ElectricalModel*)getSubInstance(String::format("Sel%dInv0", i)); 171 ElectricalModel* selinv1 = (ElectricalModel*)getSubInstance(String::format("Sel%dInv1", i)); 172 createNet("SelInv" + (String)i); 173 createNet("SelBuf" + (String)i); 174 portConnect(selinv0, "A", "Sel" + (String)i); 175 portConnect(selinv0, "Y", "SelInv" + (String)i); 176 portConnect(selinv1, "A", "SelInv" + (String)i); 177 portConnect(selinv1, "Y", "SelBuf" + (String)i); 178 } 179 } 180 //Connect inputs to the sub multiplexers. 181 //Note that multiple inputs are connected to the mux0 and mux1 input and the 182 //selector signals are connected multiple times. This is just so that everything 183 //is loaded appropriately since bit duplication is applied 184 for (unsigned int n = 0; n < number_bits; ++n) 185 { 186 //Connect inputs 187 for (unsigned int i = 0; i < inputs_0; ++i) 188 portConnect(mux0, "In" + (String) i, "In" + (String) i, makeNetIndex(n)); 189 for (unsigned int i = 0; i < inputs_1; ++i) 190 portConnect(mux1, "In" + (String) i, "In" + (String) (i + inputs_0), makeNetIndex(n)); 191 // TODO hack 192 if(is_top_level) 193 { 194 //Connect selector bits 195 for (unsigned int i = 0; i < selects_0; ++i) 196 portConnect(mux0, "Sel" + (String)i, "SelBuf" + (String)i); 197 for (unsigned int i = 0; i < selects_1; ++i) 198 portConnect(mux1, "Sel" + (String)i, "SelBuf" + (String)i); 199 portConnect(muxf, "S0", "SelBuf" + (String)(number_selects - 1)); 200 } 201 else 202 { 203 //Connect selector bits 204 for (unsigned int i = 0; i < selects_0; ++i) 205 portConnect(mux0, "Sel" + (String)i, "Sel" + (String)i); 206 for (unsigned int i = 0; i < selects_1; ++i) 207 portConnect(mux1, "Sel" + (String)i, "Sel" + (String)i); 208 portConnect(muxf, "S0", "Sel" + (String)(number_selects - 1)); 209 } 210 } 211 212 //Connect final mux to outputs 213 //Because we use bit duplication and so there is only only one multiplexer 214 //instance, we must use driver multiplier to drive each output appropriately 215 if (number_bits == 1) 216 portConnect(muxf, "Y", "Out"); 217 else 218 { 219 createNet("OutTemp"); 220 createDriverMultiplier("OutMult"); 221 ElectricalDriverMultiplier* drive_mult = getDriverMultiplier("OutMult"); 222 portConnect(muxf, "Y", "OutTemp"); 223 getNet("OutTemp")->addDownstreamNode(drive_mult); 224 for (unsigned int n = 0; n < number_bits; ++n) 225 drive_mult->addDownstreamNode(getNet("Out", makeNetIndex(n))); 226 } 227 228 //Add area, power, and event results for each mux 229 addSubInstances(mux0, number_bits); 230 addElectricalSubResults(mux0, number_bits); 231 addSubInstances(mux1, number_bits); 232 addElectricalSubResults(mux1, number_bits); 233 addSubInstances(muxf, number_bits); 234 addElectricalSubResults(muxf, number_bits); 235 getEventResult("Mux")->addSubResult(mux0->getEventResult("Mux"), mux0_name, number_bits); 236 getEventResult("Mux")->addSubResult(mux1->getEventResult("Mux"), mux1_name, number_bits); 237 getEventResult("Mux")->addSubResult(muxf->getEventResult("MUX2"), muxf_name, number_bits); 238 239 } 240 241 } 242 else 243 { 244 //Instantiate a bunch of 1-bit multiplexers 245 for (unsigned int n = 0; n < number_bits; ++n) 246 { 247 String mux_name = "Mux_bit" + (String) n; 248 249 Multiplexer* mux = new Multiplexer(mux_name, getTechModel()); 250 mux->setParameter("NumberInputs", number_inputs); 251 mux->setParameter("NumberBits", 1); 252 mux->setParameter("BitDuplicate", "TRUE"); 253 mux->construct(); 254 255 // Connect inputs 256 for (unsigned int i = 0; i < number_inputs; ++i) 257 portConnect(mux, "In" + (String) i, "In" + (String) i, makeNetIndex(n)); 258 for(unsigned int i = 0; i < number_selects; ++i) 259 portConnect(mux, "Sel" + (String)i, "Sel" + (String)i); 260 portConnect(mux, "Out", "Out", makeNetIndex(n)); 261 262 //Add area, power, and event results for each mux 263 addSubInstances(mux, 1.0); 264 addElectricalSubResults(mux, 1.0); 265 getEventResult("Mux")->addSubResult(mux->getEventResult("Mux"), mux_name, 1.0); 266 } 267 } 268 269 return; 270 } 271 272 void Multiplexer::propagateTransitionInfo() 273 { 274 // The only thing can be updated are the input probabilities...so we will update them 275 unsigned int number_bits = (unsigned int) getParameter("NumberBits"); 276 unsigned int number_inputs = (unsigned int) getParameter("NumberInputs"); 277 unsigned int number_selects = (unsigned int) ceil(log2((double) number_inputs)); 278 bool bit_duplicate = (bool) getParameter("BitDuplicate"); 279 bool is_top_level = getParameter("IsTopLevel").toBool(); 280 281 //Number of inputs on the 0 side 282 unsigned int inputs_0 = (unsigned int) ceil((double) number_inputs / 2.0); 283 unsigned int selects_0 = (unsigned int) ceil(log2((double) inputs_0)); 284 285 //Number of inputs on the 1 side 286 unsigned int inputs_1 = (unsigned int) floor((double) number_inputs / 2.0); 287 unsigned int selects_1 = (unsigned int) ceil(log2((double) inputs_1)); 288 289 if (bit_duplicate || number_bits == 1) 290 { 291 if (number_inputs == 1) 292 { 293 //If theres only 1 input, output transition = input transition 294 propagatePortTransitionInfo("Out", "In0"); 295 } 296 else 297 { 298 // Update sub muxes with appropriate probabilities 299 ElectricalModel* mux0 = (ElectricalModel*)getSubInstance("Mux_way0"); 300 for(unsigned int i = 0; i < inputs_0; ++i) 301 { 302 propagatePortTransitionInfo(mux0, "In" + (String)i, "In" + (String)i); 303 } 304 for(unsigned int i = 0; i < selects_0; ++i) 305 { 306 propagatePortTransitionInfo(mux0, "Sel" + (String)i, "Sel" + (String)i); 307 } 308 mux0->use(); 309 ElectricalModel* mux1 = (ElectricalModel*)getSubInstance("Mux_way1"); 310 for(unsigned int i = 0; i < inputs_1; ++i) 311 { 312 propagatePortTransitionInfo(mux1, "In" + (String)i, "In" + (String)(i + inputs_0)); 313 } 314 for(unsigned int i = 0; i < selects_1; ++i) 315 { 316 propagatePortTransitionInfo(mux1, "Sel" + (String)i, "Sel" + (String)i); 317 } 318 mux1->use(); 319 ElectricalModel* muxf = (ElectricalModel*)getSubInstance("Mux2_i" + (String)number_inputs); 320 propagatePortTransitionInfo(muxf, "A", mux0, "Out"); 321 propagatePortTransitionInfo(muxf, "B", mux1, "Out"); 322 propagatePortTransitionInfo(muxf, "S0", "Sel" + (String)(number_selects-1)); 323 muxf->use(); 324 325 // TODO hack 326 if(is_top_level) 327 { 328 for(unsigned int i = 0; i < number_selects; ++i) 329 { 330 ElectricalModel* selinv0 = (ElectricalModel*)getSubInstance(String::format("Sel%dInv0", i)); 331 ElectricalModel* selinv1 = (ElectricalModel*)getSubInstance(String::format("Sel%dInv1", i)); 332 propagatePortTransitionInfo(selinv0, "A", "Sel" + (String)i); 333 selinv0->use(); 334 propagatePortTransitionInfo(selinv1, "A", selinv0, "Y"); 335 selinv1->use(); 336 } 337 } 338 339 // Set output transition 340 propagatePortTransitionInfo("Out", muxf, "Y"); 341 } 342 } 343 else 344 { 345 // Go through each bit and set the appropriate probability 346 for (unsigned int n = 0; n < number_bits; ++n) 347 { 348 ElectricalModel* mux_bit = (ElectricalModel*)getSubInstance("Mux_bit" + (String) n); 349 for(unsigned int i = 0; i < number_inputs; ++i) 350 { 351 propagatePortTransitionInfo(mux_bit, "In" + (String)i, "In" + (String)i); 352 } 353 for(unsigned int i = 0; i < number_selects; ++i) 354 { 355 propagatePortTransitionInfo(mux_bit, "Sel" + (String)i, "Sel" + (String)i); 356 } 357 mux_bit->use(); 358 } 359 360 // Set output probability to be average that of probabilties of each output bit 361 ElectricalModel* mux_bit = (ElectricalModel*)getSubInstance("Mux_bit0"); 362 propagatePortTransitionInfo("Out", mux_bit, "Out"); 363 } 364 return; 365 } 366 367} // namespace DSENT 368 369