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