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/MatrixArbiter.h"
23
24#include <cmath>
25#include <vector>
26
27#include "model/PortInfo.h"
28#include "model/EventInfo.h"
29#include "model/TransitionInfo.h"
30#include "model/ModelGen.h"
31#include "model/std_cells/StdCell.h"
32#include "model/std_cells/StdCellLib.h"
33
34namespace DSENT
35{
36    using std::abs;
37    using std::vector;
38
39    MatrixArbiter::MatrixArbiter(const String& instance_name_, const TechModel* tech_model_)
40        : ElectricalModel(instance_name_, tech_model_)
41    {
42        initParameters();
43        initProperties();
44    }
45
46    MatrixArbiter::~MatrixArbiter()
47    {}
48
49    void MatrixArbiter::initParameters()
50    {
51        addParameterName("NumberRequests");
52        return;
53    }
54
55    void MatrixArbiter::initProperties()
56    {
57        return;
58    }
59
60    MatrixArbiter* MatrixArbiter::clone() const
61    {
62        // TODO
63        return NULL;
64    }
65
66    void MatrixArbiter::constructModel()
67    {
68        // Get parameters
69        unsigned int number_requests = getParameter("NumberRequests").toUInt();
70
71        ASSERT(number_requests > 0, "[Error] " + getInstanceName() +
72                " -> Number of requests must be > 0!");
73
74        // Connect ports
75        createInputPort("CK");
76        for(unsigned int i = 0; i < number_requests; ++i)
77        {
78            createInputPort("Request" + (String)i);
79            createOutputPort("Grant" + (String)i);
80        }
81
82        // Create area, power, event results
83        createElectricalResults();
84        getEventInfo("Idle")->setStaticTransitionInfos();
85        getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
86//        for(unsigned int i = 0; i <= number_requests; ++i)
87//        {
88//            // Create arbitrate event with i requests
89//            createElectricalEventResult("Arbitrate" + (String)i);
90//            EventInfo* event_info = getEventInfo("Arbitrate" + (String)i);
91//            event_info->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
92//
93//            for(unsigned int j = 0; j < i; ++j)
94//            {
95//                event_info->setTransitionInfo("Request" + (String)j, TransitionInfo(0.0, 0.0, 1.0));
96//            }
97//            for(unsigned int j = i; j < number_requests; ++j)
98//            {
99//                event_info->setTransitionInfo("Request" + (String)j, TransitionInfo(1.0, 0.0, 0.0));
100//
101//            }
102//            //double P_0 = (double)(number_requests - i) / (double)(number_requests);
103//            //double P_1 = (double)(i) / (double)(number_requests);
104//            //TransitionInfo trans(P_0 * P_0, P_0 * P_1, P_1 * P_1);
105//
106//            //for(unsigned int j = 0; j < number_requests; ++j)
107//            //{
108//            //    event_info->setTransitionInfo("Request" + (String)j, trans);
109//            //}
110//        }
111        createElectricalEventResult("Arbitrate");
112        getEventInfo("Arbitrate")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
113        for(unsigned int i = 0; i < number_requests; ++i)
114        {
115            getEventInfo("Arbitrate")->setTransitionInfo("Request" + (String)i, TransitionInfo(0.25, 0.25, 0.25));
116        }
117
118        if(number_requests == 1)
119        {
120            assign("Grant0", "Request0");
121        }
122        else
123        {
124            // Init components
125            vector<String> g_inv_names(number_requests, "");
126            vector<StdCell*> g_invs(number_requests, NULL);
127            vector<String> g_and2_names(number_requests, "");
128            vector<StdCell*> g_and2s(number_requests, NULL);
129            for(unsigned int i = 0; i < number_requests; ++i)
130            {
131                g_inv_names[i] = "G_INV" + (String)i;
132                g_and2_names[i] = "G_AND2" + (String)i;
133                g_invs[i] = getTechModel()->getStdCellLib()->createStdCell("INV", g_inv_names[i]);
134                g_invs[i]->construct();
135                g_and2s[i] = getTechModel()->getStdCellLib()->createStdCell("AND2", g_and2_names[i]);
136                g_and2s[i]->construct();
137            }
138
139            unsigned int number_states = (number_requests - 1) * number_requests / 2;
140
141            vector<String> w_or2_names(number_states, "");
142            vector<StdCell*> w_or2s(number_states, NULL);
143            vector<String> w_and2_names(number_states, "");
144            vector<StdCell*> w_and2s(number_states, NULL);
145            vector<String> w_inv_names(number_states, "");
146            vector<StdCell*> w_invs(number_states, NULL);
147            vector<String> w_dff_names(number_states, "");
148            vector<StdCell*> w_dffs(number_states, NULL);
149            vector<String> dis_and2_names(number_states * 2, "");
150            vector<StdCell*> dis_and2s(number_states * 2, NULL);
151            vector<String> dis_inv_names(number_states, "");
152            vector<StdCell*> dis_invs(number_states, NULL);
153            unsigned int state_count = 0;
154            for(unsigned int i = 0; i < number_requests; ++i)
155            {
156                for(unsigned int j = i + 1; j < number_requests; ++j)
157                {
158                    w_or2_names[state_count] = String::format("W_OR2_%d_%d", i, j);
159                    w_and2_names[state_count] = String::format("W_AND2_%d_%d", i, j);
160                    w_inv_names[state_count] = String::format("W_INV_%d_%d", i, j);
161                    w_dff_names[state_count] = String::format("W_DFF_%d_%d", i, j);
162                    w_or2s[state_count] = getTechModel()->getStdCellLib()->createStdCell("OR2", w_or2_names[state_count]);
163                    w_or2s[state_count]->construct();
164                    w_and2s[state_count] = getTechModel()->getStdCellLib()->createStdCell("AND2", w_and2_names[state_count]);
165                    w_and2s[state_count]->construct();
166                    w_invs[state_count] = getTechModel()->getStdCellLib()->createStdCell("INV", w_inv_names[state_count]);
167                    w_invs[state_count]->construct();
168                    w_dffs[state_count] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", w_dff_names[state_count]);
169                    w_dffs[state_count]->construct();
170
171                    dis_inv_names[state_count] = String::format("Dis_INV_%d_%d", i, j);
172                    dis_and2_names[state_count] = String::format("Dis_AND2_%d_%d", i, j);
173                    dis_and2_names[state_count + number_states] = String::format("Dis_AND2_%d_%d", j, i);
174                    dis_invs[state_count] = getTechModel()->getStdCellLib()->createStdCell("INV", dis_inv_names[state_count]);
175                    dis_invs[state_count]->construct();
176                    dis_and2s[state_count] = getTechModel()->getStdCellLib()->createStdCell("AND2", dis_and2_names[state_count]);
177                    dis_and2s[state_count]->construct();
178                    dis_and2s[state_count + number_states] = getTechModel()->getStdCellLib()->createStdCell("AND2", dis_and2_names[state_count + number_states]);
179                    dis_and2s[state_count + number_states]->construct();
180                    state_count++;
181                }
182            }
183
184            vector<String> dis_or_names(number_requests, "");
185            vector<ElectricalModel*> dis_ors(number_requests, NULL);
186            for(unsigned int i = 0; i < number_requests; ++i)
187            {
188                dis_or_names[i] = "Dis_OR" + (String)i;
189                dis_ors[i] = (ElectricalModel*)ModelGen::createModel("OR", dis_or_names[i], getTechModel());
190                dis_ors[i]->setParameter("NumberInputs", number_requests-1);
191                dis_ors[i]->setParameter("NumberBits", 1);
192                dis_ors[i]->construct();
193            }
194
195            state_count = 0;
196            for(unsigned int i = 0; i < number_requests; ++i)
197            {
198                createNet("Dis_OR_Out" + (String)i);
199                createNet("G_INV_Out" + (String)i);
200                portConnect(g_invs[i], "A", "Dis_OR_Out" + (String)i);
201                portConnect(g_invs[i], "Y", "G_INV_Out" + (String)i);
202                portConnect(g_and2s[i], "A", "Request" + (String)i);
203                portConnect(g_and2s[i], "B", "G_INV_Out" + (String)i);
204                portConnect(g_and2s[i], "Y", "Grant" + (String)i);
205
206                for(unsigned int j = i + 1; j < number_requests; ++j)
207                {
208                    createNet(String::format("W_INV_Out_%d_%d", i, j));
209                    createNet(String::format("W_OR2_Out_%d_%d", i, j));
210                    createNet(String::format("W_AND2_Out_%d_%d", i, j));
211                    createNet(String::format("W_DFF_Out_%d_%d", i, j));
212                    portConnect(w_invs[state_count], "A", "Grant" + (String)i);
213                    portConnect(w_invs[state_count], "Y", String::format("W_INV_Out_%d_%d", i, j));
214                    portConnect(w_or2s[state_count], "A", String::format("W_DFF_Out_%d_%d", i, j));
215                    portConnect(w_or2s[state_count], "B", "Grant" + (String)j);
216                    portConnect(w_or2s[state_count], "Y", String::format("W_OR2_Out_%d_%d", i, j));
217                    portConnect(w_and2s[state_count], "A", String::format("W_OR2_Out_%d_%d", i, j));
218                    portConnect(w_and2s[state_count], "B", String::format("W_INV_Out_%d_%d", i, j));
219                    portConnect(w_and2s[state_count], "Y", String::format("W_AND2_Out_%d_%d", i, j));
220                    portConnect(w_dffs[state_count], "D", String::format("W_AND2_Out_%d_%d", i, j));
221                    portConnect(w_dffs[state_count], "CK", "CK");
222                    portConnect(w_dffs[state_count], "Q", String::format("W_DFF_Out_%d_%d", i, j));
223
224                    createNet(String::format("Dis_AND2_Out_%d_%d", i, j));
225                    createNet(String::format("Dis_AND2_Out_%d_%d", j, i));
226                    createNet(String::format("Dis_INV_Out_%d_%d", j, i));
227                    portConnect(dis_and2s[state_count], "A", "Request" + (String)i);
228                    portConnect(dis_and2s[state_count], "B", String::format("W_DFF_Out_%d_%d", i, j));
229                    portConnect(dis_and2s[state_count], "Y", String::format("Dis_AND2_Out_%d_%d", i, j));
230
231                    portConnect(dis_invs[state_count], "A", String::format("W_DFF_Out_%d_%d", i, j));
232                    portConnect(dis_invs[state_count], "Y", String::format("Dis_INV_Out_%d_%d", j, i));
233                    portConnect(dis_and2s[state_count + number_states], "A", "Request" + (String)j);
234                    portConnect(dis_and2s[state_count + number_states], "B", String::format("Dis_INV_Out_%d_%d", j, i));
235                    portConnect(dis_and2s[state_count + number_states], "Y", String::format("Dis_AND2_Out_%d_%d", j, i));
236
237                    state_count++;
238                }
239            }
240            for(unsigned int i = 0; i < number_requests; ++i)
241            {
242                unsigned int k = 0;
243                for(unsigned int j = 0; j < number_requests; ++j)
244                {
245                    if(i != j)
246                    {
247                        portConnect(dis_ors[i], "In" + (String)k, String::format("Dis_AND2_Out_%d_%d", j, i));
248                        k++;
249                    }
250                }
251                portConnect(dis_ors[i], "Out", "Dis_OR_Out" + (String)i);
252            }
253
254            // Add instances
255            for(unsigned int i = 0; i < number_requests; ++i)
256            {
257                addSubInstances(g_invs[i], 1.0);
258                addElectricalSubResults(g_invs[i], 1.0);
259                addSubInstances(g_and2s[i], 1.0);
260                addElectricalSubResults(g_and2s[i], 1.0);
261                addSubInstances(dis_ors[i], 1.0);
262                addElectricalSubResults(dis_ors[i], 1.0);
263            }
264            for(unsigned int i = 0; i < number_states; ++i)
265            {
266                addSubInstances(w_or2s[i], 1.0);
267                addElectricalSubResults(w_or2s[i], 1.0);
268                addSubInstances(w_and2s[i], 1.0);
269                addElectricalSubResults(w_and2s[i], 1.0);
270                addSubInstances(w_invs[i], 1.0);
271                addElectricalSubResults(w_invs[i], 1.0);
272                addSubInstances(w_dffs[i], 1.0);
273                addElectricalSubResults(w_dffs[i], 1.0);
274                addSubInstances(dis_and2s[i], 1.0);
275                addElectricalSubResults(dis_and2s[i], 1.0);
276                addSubInstances(dis_and2s[i + number_states], 1.0);
277                addElectricalSubResults(dis_and2s[i + number_states], 1.0);
278                addSubInstances(dis_invs[i], 1.0);
279                addElectricalSubResults(dis_invs[i], 1.0);
280            }
281
282            // Update event
283            //for(unsigned int i = 0; i <= number_requests; ++i)
284            //{
285            //Result* arb_event = getEventResult("Arbitrate" + (String)i);
286            Result* arb_event = getEventResult("Arbitrate");
287            for(unsigned int j = 0; j < number_requests; ++j)
288            {
289                arb_event->addSubResult(g_invs[j]->getEventResult("INV"), g_inv_names[j], 1.0);
290                arb_event->addSubResult(g_and2s[j]->getEventResult("AND2"), g_and2_names[j], 1.0);
291                arb_event->addSubResult(dis_ors[j]->getEventResult("OR"), dis_or_names[j], 1.0);
292            }
293            for(unsigned int j = 0; j < number_states; ++j)
294            {
295                arb_event->addSubResult(w_or2s[j]->getEventResult("OR2"), w_or2_names[j], 1.0);
296                arb_event->addSubResult(w_and2s[j]->getEventResult("AND2"), w_and2_names[j], 1.0);
297                arb_event->addSubResult(w_invs[j]->getEventResult("INV"), w_inv_names[j], 1.0);
298                arb_event->addSubResult(w_dffs[j]->getEventResult("DFFD"), w_dff_names[j], 1.0);
299                arb_event->addSubResult(w_dffs[j]->getEventResult("DFFQ"), w_dff_names[j], 1.0);
300                arb_event->addSubResult(w_dffs[j]->getEventResult("CK"), w_dff_names[j], 1.0);
301                arb_event->addSubResult(dis_and2s[j]->getEventResult("AND2"), dis_and2_names[j], 1.0);
302                arb_event->addSubResult(dis_and2s[j + number_states]->getEventResult("AND2"), dis_and2_names[j + number_states], 1.0);
303                arb_event->addSubResult(dis_invs[j]->getEventResult("INV"), dis_inv_names[j], 1.0);
304            }
305            //}
306        }
307        return;
308    }
309
310    void MatrixArbiter::propagateTransitionInfo()
311    {
312        // Get parameters
313        unsigned int number_requests = getParameter("NumberRequests").toUInt();
314
315        if(number_requests == 1)
316        {
317            propagatePortTransitionInfo("Grant0", "Request0");
318        }
319        else
320        {
321            unsigned int number_states = (number_requests - 1) * number_requests / 2;
322
323            vector<ElectricalModel*> g_and2s(number_requests, NULL);
324            vector<ElectricalModel*> g_invs(number_requests, NULL);
325            vector<ElectricalModel*> w_invs(number_states, NULL);
326            vector<ElectricalModel*> w_or2s(number_states, NULL);
327            vector<ElectricalModel*> w_and2s(number_states, NULL);
328            vector<ElectricalModel*> w_dffs(number_states, NULL);
329            vector<ElectricalModel*> dis_invs(number_states, NULL);
330            vector<ElectricalModel*> dis_and2s(number_requests * number_requests, NULL);
331            vector<ElectricalModel*> dis_ors(number_requests, NULL);
332            for(unsigned int i = 0; i < number_requests; ++i)
333            {
334                g_and2s[i] = (ElectricalModel*)getSubInstance("G_AND2" + (String)i);
335                g_invs[i] = (ElectricalModel*)getSubInstance("G_INV" + (String)i);
336                dis_ors[i] = (ElectricalModel*)getSubInstance("Dis_OR" + (String)i);
337            }
338            unsigned int state_count = 0;
339            for(unsigned int i = 0; i < number_requests; ++i)
340            {
341                for(unsigned int j = i + 1; j < number_requests; ++j)
342                {
343                    w_invs[state_count] = (ElectricalModel*)getSubInstance(String::format("W_INV_%d_%d", i, j));
344                    w_or2s[state_count] = (ElectricalModel*)getSubInstance(String::format("W_OR2_%d_%d", i, j));
345                    w_and2s[state_count] = (ElectricalModel*)getSubInstance(String::format("W_AND2_%d_%d", i, j));
346                    w_dffs[state_count] = (ElectricalModel*)getSubInstance(String::format("W_DFF_%d_%d", i, j));
347                    dis_invs[state_count] = (ElectricalModel*)getSubInstance(String::format("Dis_INV_%d_%d", i, j));
348                    dis_and2s[i * number_requests + j] = (ElectricalModel*)getSubInstance(String::format("Dis_AND2_%d_%d", i, j));
349                    dis_and2s[j * number_requests + i] = (ElectricalModel*)getSubInstance(String::format("Dis_AND2_%d_%d", j, i));
350
351                    w_dffs[state_count]->getInputPort("D")->setTransitionInfo(TransitionInfo(0.5, 0.0, 0.5));
352                    propagatePortTransitionInfo(w_dffs[state_count], "CK", "CK");
353                    w_dffs[state_count]->use();
354
355                    state_count++;
356                }
357            }
358
359            unsigned int iteration = 1;
360            unsigned int max_number_iterations = 10;
361            //vector<TransitionInfo> trans_vector(number_states, TransitionInfo(0.0, 0.0, 1.0));
362            //vector<double> total_P_vector(number_states, 0.0);
363            while(iteration < max_number_iterations)
364            {
365//                for(unsigned int i = 0; i < number_states; ++i)
366//                {
367//                    w_dffs[i]->getInputPort("D")->setTransitionInfo(trans_vector[i]);
368//                    propagatePortTransitionInfo(w_dffs[i], "CK", "CK");
369//                    w_dffs[i]->use();
370//                }
371                state_count = 0;
372                for(unsigned int i = 0; i < number_requests; ++i)
373                {
374                    for(unsigned int j = i + 1; j < number_requests; ++j)
375                    {
376                        propagatePortTransitionInfo(dis_and2s[i * number_requests + j], "A", "Request" + (String)i);
377                        propagatePortTransitionInfo(dis_and2s[i * number_requests + j], "B", w_dffs[state_count], "Q");
378                        dis_and2s[i * number_requests + j]->use();
379                        propagatePortTransitionInfo(dis_invs[state_count], "A", w_dffs[state_count], "Q");
380                        dis_invs[state_count]->use();
381                        propagatePortTransitionInfo(dis_and2s[j * number_requests + i], "A", "Request" + (String)j);
382                        propagatePortTransitionInfo(dis_and2s[j * number_requests + i], "B", dis_invs[state_count], "Y");
383                        dis_and2s[j * number_requests + i]->use();
384
385                        state_count++;
386                    }
387                }
388                for(unsigned int i = 0; i < number_requests; ++i)
389                {
390                    unsigned int k = 0;
391                    for(unsigned int j = 0; j < number_requests; ++j)
392                    {
393                        if(i != j)
394                        {
395                            propagatePortTransitionInfo(dis_ors[i], "In" + (String)k, dis_and2s[j * number_requests + i], "Y");
396                            k++;
397                        }
398                    }
399                    dis_ors[i]->use();
400                }
401                for(unsigned int i = 0; i < number_requests; ++i)
402                {
403                    propagatePortTransitionInfo(g_invs[i], "A", dis_ors[i], "Out");
404                    g_invs[i]->use();
405                    propagatePortTransitionInfo(g_and2s[i], "A", "Request" + (String)i);
406                    propagatePortTransitionInfo(g_and2s[i], "B", g_invs[i], "Y");
407                    g_and2s[i]->use();
408                }
409                state_count = 0;
410                for(unsigned int i = 0; i < number_requests; ++i)
411                {
412                    for(unsigned int j = i + 1; j < number_requests; ++j)
413                    {
414                        propagatePortTransitionInfo(w_invs[state_count], "A", g_and2s[i], "Y");
415                        w_invs[state_count]->use();
416                        propagatePortTransitionInfo(w_or2s[state_count], "A", w_dffs[state_count], "Q");
417                        propagatePortTransitionInfo(w_or2s[state_count], "B", g_and2s[j], "Y");
418                        w_or2s[state_count]->use();
419                        propagatePortTransitionInfo(w_and2s[state_count], "A", w_or2s[state_count], "Y");
420                        propagatePortTransitionInfo(w_and2s[state_count], "B", w_invs[state_count], "Y");
421                        w_and2s[state_count]->use();
422                        propagatePortTransitionInfo(w_dffs[state_count], "D", w_and2s[state_count], "Y");
423                        propagatePortTransitionInfo(w_dffs[state_count], "CK", "CK");
424                        w_dffs[state_count]->use();
425                        state_count++;
426                    }
427                }
428
429//                for(unsigned int i = 0; i < number_states; ++i)
430//                {
431//                    const TransitionInfo& new_trans = w_dffs[i]->getOutputPort("Q")->getTransitionInfo();
432//                    total_P_vector[i] += new_trans.getProbability1();
433//                    trans_vector[i] = TransitionInfo((1.0 - total_P_vector[i] / iteration) * (1.0 - total_P_vector[i] / iteration),
434//                            (1.0 - total_P_vector[i] / iteration) * (total_P_vector[i] / iteration),
435//                            (total_P_vector[i] / iteration) * (total_P_vector[i] / iteration));
436//                }
437//
438//                for(unsigned int i = 0; i < number_requests; ++i)
439//                {
440//                    g_and2s[i]->getOutputPort("Y")->getTransitionInfo().print(cout);
441//                }
442//                cout << endl;
443                iteration++;
444            }
445
446            for(unsigned int i = 0; i < number_requests; ++i)
447            {
448                propagatePortTransitionInfo("Grant" + (String)i, g_and2s[i], "Y");
449            }
450        }
451
452        return;
453    }
454} // namespace DSENT
455
456