sim, kvm: make KvmVM a System parameter
[gem5.git] / ext / dsent / model / electrical / Multiplexer.cc
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
34 namespace 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