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