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/RippleAdder.h"
23
24#include <cmath>
25
26#include "model/PortInfo.h"
27#include "model/TransitionInfo.h"
28#include "model/EventInfo.h"
29#include "model/std_cells/StdCell.h"
30#include "model/std_cells/StdCellLib.h"
31
32namespace DSENT
33{
34    RippleAdder::RippleAdder(const String& instance_name_, const TechModel* tech_model_)
35        : ElectricalModel(instance_name_, tech_model_)
36    {
37        initParameters();
38        initProperties();
39    }
40
41    RippleAdder::~RippleAdder()
42    {}
43
44    void RippleAdder::initParameters()
45    {
46        addParameterName("NumberBits");
47        return;
48    }
49
50    void RippleAdder::initProperties()
51    {
52        return;
53    }
54
55    void RippleAdder::constructModel()
56    {
57        // Get properties
58        unsigned int number_bits = (unsigned int) getParameter("NumberBits");
59
60        //Construct electrical ports and nets
61        createInputPort("CI");
62        createOutputPort("CO");
63        for(unsigned int i = 0; i < number_bits; ++i)
64        {
65            createInputPort("A" + String(i));
66            createInputPort("B" + String(i));
67            createOutputPort("S" + String(i));
68            createNet("C" + String(i));
69        }
70        createNet("C" + String(number_bits));
71
72        //Create energy, power, and area results
73        createElectricalResults();
74        getEventInfo("Idle")->setStaticTransitionInfos();
75        createElectricalEventResult("Add");
76        Result* add_event = getEventResult("Add");
77
78        // Connect all nets
79        assign("C0", "CI");
80        assign("CO", "C" + String(number_bits));
81        for (unsigned int i = 0; i < number_bits; ++i)
82        {
83            String n = (String) i;
84            StdCell* adder = getTechModel()->getStdCellLib()->createStdCell("ADDF", "ADDF_" + n);
85            adder->construct();
86
87            //Build electrical connectivity
88            portConnect(adder, "A", "A" + String(i));
89            portConnect(adder, "B", "B" + String(i));
90            portConnect(adder, "CI", "C" + String(i));
91            portConnect(adder, "S", "S" + String(i));
92            portConnect(adder, "CO", "C" + String(i + 1));
93
94            //Add ADDF instance, leakage power, energy, and add event results
95            addSubInstances(adder, 1.0);
96            addElectricalSubResults(adder, 1.0);
97            add_event->addSubResult(adder->getEventResult("ADDF"), "ADDF_" + n, 1.0);
98        }
99
100        return;
101    }
102
103    void RippleAdder::propagateTransitionInfo()
104    {
105        unsigned int number_bits = getParameter("NumberBits").toUInt();
106
107        TransitionInfo current_trans_CI = getInputPort("CI")->getTransitionInfo();
108        for(unsigned int i = 0; i < number_bits; ++i)
109        {
110            ElectricalModel* adder = (ElectricalModel*)getSubInstance("ADDF_" + String(i));
111
112            // Propagate input transition info
113            propagatePortTransitionInfo(adder, "A", "A" + String(i));
114            propagatePortTransitionInfo(adder, "B", "B" + String(i));
115            assignPortTransitionInfo(adder, "CI", current_trans_CI);
116            adder->use();
117
118            // Assign output transition info
119            propagatePortTransitionInfo("S" + String(i), adder, "S");
120            current_trans_CI = adder->getOutputPort("CO")->getTransitionInfo();
121        }
122        getOutputPort("CO")->setTransitionInfo(current_trans_CI);
123        return;
124    }
125
126} // namespace DSENT
127
128