1 /* Copyright (c) 2012 Massachusetts Institute of Technology
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:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
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
22 #include "model/electrical/Multiplexer.h"
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"
36 Multiplexer::Multiplexer(const String
& instance_name_
, const TechModel
* tech_model_
)
37 : ElectricalModel(instance_name_
, tech_model_
)
43 Multiplexer::~Multiplexer()
46 void Multiplexer::initParameters()
48 addParameterName("NumberInputs");
49 addParameterName("NumberBits");
50 addParameterName("BitDuplicate", "TRUE");
51 addParameterName("IsTopLevel", "TRUE");
55 void Multiplexer::initProperties()
60 Multiplexer
* Multiplexer::clone() const
65 void Multiplexer::constructModel()
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();
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!");
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
)
84 createInputPort( "Sel" + (String
)i
);
87 createOutputPort( "Out", makeNetIndex(0, number_bits
-1));
89 //Create energy, power, and area results
90 createElectricalResults();
91 getEventInfo("Idle")->setStaticTransitionInfos();
92 createElectricalEventResult("Mux");
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
));
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)
106 //If it is just a 1-input multiplexer, just connect output to input and be done
107 if (number_inputs
== 1)
109 assign("Out", "In0");
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
;
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");
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");
133 StdCell
* muxf
= getTechModel()->getStdCellLib()->createStdCell("MUX2", muxf_name
);
137 // create selector driver at the top level
140 for(unsigned int i
= 0; i
< number_selects
; ++i
)
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();
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);
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");
165 // Connect selector bits
168 for(unsigned int i
= 0; i
< number_selects
; ++i
)
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
);
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
)
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
));
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));
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));
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");
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
)));
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
);
244 //Instantiate a bunch of 1-bit multiplexers
245 for (unsigned int n
= 0; n
< number_bits
; ++n
)
247 String mux_name
= "Mux_bit" + (String
) n
;
249 Multiplexer
* mux
= new Multiplexer(mux_name
, getTechModel());
250 mux
->setParameter("NumberInputs", number_inputs
);
251 mux
->setParameter("NumberBits", 1);
252 mux
->setParameter("BitDuplicate", "TRUE");
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
));
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);
272 void Multiplexer::propagateTransitionInfo()
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();
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
));
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
));
289 if (bit_duplicate
|| number_bits
== 1)
291 if (number_inputs
== 1)
293 //If theres only 1 input, output transition = input transition
294 propagatePortTransitionInfo("Out", "In0");
298 // Update sub muxes with appropriate probabilities
299 ElectricalModel
* mux0
= (ElectricalModel
*)getSubInstance("Mux_way0");
300 for(unsigned int i
= 0; i
< inputs_0
; ++i
)
302 propagatePortTransitionInfo(mux0
, "In" + (String
)i
, "In" + (String
)i
);
304 for(unsigned int i
= 0; i
< selects_0
; ++i
)
306 propagatePortTransitionInfo(mux0
, "Sel" + (String
)i
, "Sel" + (String
)i
);
309 ElectricalModel
* mux1
= (ElectricalModel
*)getSubInstance("Mux_way1");
310 for(unsigned int i
= 0; i
< inputs_1
; ++i
)
312 propagatePortTransitionInfo(mux1
, "In" + (String
)i
, "In" + (String
)(i
+ inputs_0
));
314 for(unsigned int i
= 0; i
< selects_1
; ++i
)
316 propagatePortTransitionInfo(mux1
, "Sel" + (String
)i
, "Sel" + (String
)i
);
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));
328 for(unsigned int i
= 0; i
< number_selects
; ++i
)
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
);
334 propagatePortTransitionInfo(selinv1
, "A", selinv0
, "Y");
339 // Set output transition
340 propagatePortTransitionInfo("Out", muxf
, "Y");
345 // Go through each bit and set the appropriate probability
346 for (unsigned int n
= 0; n
< number_bits
; ++n
)
348 ElectricalModel
* mux_bit
= (ElectricalModel
*)getSubInstance("Mux_bit" + (String
) n
);
349 for(unsigned int i
= 0; i
< number_inputs
; ++i
)
351 propagatePortTransitionInfo(mux_bit
, "In" + (String
)i
, "In" + (String
)i
);
353 for(unsigned int i
= 0; i
< number_selects
; ++i
)
355 propagatePortTransitionInfo(mux_bit
, "Sel" + (String
)i
, "Sel" + (String
)i
);
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");