RepeatedLink.cc revision 10447:a465576671d4
1#include "model/electrical/RepeatedLink.h"
2
3#include "model/PortInfo.h"
4#include "model/EventInfo.h"
5#include "model/TransitionInfo.h"
6#include "model/std_cells/StdCellLib.h"
7#include "model/std_cells/StdCell.h"
8#include "model/timing_graph/ElectricalTimingTree.h"
9#include "model/timing_graph/ElectricalTimingNode.h"
10#include "model/timing_graph/ElectricalNet.h"
11#include "model/timing_graph/ElectricalDriver.h"
12#include "model/timing_graph/ElectricalDelay.h"
13#include "model/timing_graph/ElectricalLoad.h"
14
15namespace DSENT
16{
17    RepeatedLink::RepeatedLink(const String& instance_name_, const TechModel* tech_model_)
18        : ElectricalModel(instance_name_, tech_model_)
19    {
20        m_repeater_ = NULL;
21        m_repeater_load_ = NULL;
22        m_timing_tree_ = NULL;
23
24        initParameters();
25        initProperties();
26    }
27
28    RepeatedLink::~RepeatedLink()
29    {
30        delete m_repeater_;
31        delete m_repeater_load_;
32        delete m_timing_tree_;
33    }
34
35    void RepeatedLink::initParameters()
36    {
37        addParameterName("NumberBits");
38        addParameterName("WireLayer");
39        addParameterName("WireWidthMultiplier", 1.0);
40        addParameterName("WireSpacingMultiplier", 1.0);
41        return;
42    }
43
44    void RepeatedLink::initProperties()
45    {
46        addPropertyName("WireLength");
47        addPropertyName("Delay");
48        addPropertyName("IsKeepParity", "TRUE");
49        return;
50    }
51
52    RepeatedLink* RepeatedLink::clone() const
53    {
54        // TODO
55        return NULL;
56    }
57
58    void RepeatedLink::constructModel()
59    {
60        // Get parameters
61        unsigned int number_bits = getParameter("NumberBits").toUInt();
62        const String& wire_layer = getParameter("WireLayer");
63        double wire_width_multiplier = getParameter("WireWidthMultiplier").toDouble();
64        double wire_spacing_multiplier = getParameter("WireSpacingMultiplier").toDouble();
65
66        ASSERT(number_bits > 0, "[Error] " + getInstanceName() +
67                " -> Number of bits must be > 0!");
68        ASSERT(getTechModel()->isWireLayerExist(wire_layer), "[Error] " + getInstanceName() +
69                " -> Wire layer does not exist!");
70        ASSERT(wire_width_multiplier >= 1.0, "[Error] " + getInstanceName() +
71                " -> Wire width multiplier must be >= 1.0!");
72        ASSERT(wire_spacing_multiplier >= 1.0, "[Error] " + getInstanceName() +
73                " -> Wire spacing multiplier must be >= 1.0!");
74
75        double wire_min_width = getTechModel()->get("Wire->" + wire_layer + "->MinWidth").toDouble();
76        double wire_min_spacing = getTechModel()->get("Wire->" + wire_layer + "->MinSpacing").toDouble();
77
78        double wire_width = wire_min_width * wire_width_multiplier;
79        double wire_spacing = wire_min_spacing * wire_spacing_multiplier;
80
81        double wire_cap_per_len = getTechModel()->calculateWireCapacitance(wire_layer, wire_width, wire_spacing, 1.0);
82        double wire_res_per_len = getTechModel()->calculateWireResistance(wire_layer, wire_width, 1.0);
83
84        getGenProperties()->set("WireWidth", wire_width);
85        getGenProperties()->set("WireSpacing", wire_spacing);
86        getGenProperties()->set("WireCapacitancePerLength", wire_cap_per_len);
87        getGenProperties()->set("WireResistancePerLength", wire_res_per_len);
88
89        // Create ports
90        createInputPort("In", makeNetIndex(0, number_bits-1));
91        createOutputPort("Out", makeNetIndex(0, number_bits-1));
92
93        // Create area, power, and event results
94        createElectricalAtomicResults();
95        createElectricalEventAtomicResult("Send");
96
97        // Create connections
98        // Since the length is not set yet, we only to virtual fan-in and virtual fan-out
99        createNet("InTmp");
100        createNet("OutTmp");
101        assignVirtualFanin("InTmp", "In");
102        assignVirtualFanout("Out", "OutTmp");
103
104        // Build Electrical Connectivity
105        createLoad("In_Cap");
106        createDelay("In_to_Out_delay");
107        createDriver("Out_Ron", false); // Indicate this driver is not sizable
108
109        ElectricalLoad* in_cap = getLoad("In_Cap");
110        ElectricalDelay* in_to_out_delay = getDelay("In_to_Out_delay");
111        ElectricalDriver* out_ron = getDriver("Out_Ron");
112
113        getNet("InTmp")->addDownstreamNode(in_cap);
114        in_cap->addDownstreamNode(in_to_out_delay);
115        in_to_out_delay->addDownstreamNode(out_ron);
116        out_ron->addDownstreamNode(getNet("OutTmp"));
117
118        // Init a repeater and a load to mimic a segment of a repeated link
119        m_repeater_ = getTechModel()->getStdCellLib()->createStdCell("INV", "Repeater");
120        m_repeater_->construct();
121        m_repeater_load_ = new ElectricalLoad("RepeaterIn_Cap", this);
122        // Make path repeater_ -> repeater_load_
123        // to catch the repeater's input/output cap and ensure only one inverter delay
124        // is added
125        m_repeater_->getNet("Y")->addDownstreamNode(m_repeater_load_);
126        // Init a timing object to calculate delay
127        m_timing_tree_ = new ElectricalTimingTree("RepeatedLink", this);
128        m_timing_tree_->performCritPathExtract(m_repeater_->getNet("A"));
129        return;
130    }
131
132    void RepeatedLink::updateModel()
133    {
134        unsigned int number_bits = getParameter("NumberBits").toUInt();
135
136        // Get properties
137        double wire_length = getProperty("WireLength").toDouble();
138        double required_delay = getProperty("Delay").toDouble();
139        bool isKeepParity = getProperty("IsKeepParity").toBool();
140
141        ASSERT(wire_length >= 0, "[Error] " + getInstanceName() +
142                " -> Wire length must be >= 0!");
143        ASSERT(required_delay >= 0, "[Error] " + getInstanceName() +
144                " -> Required delay must be >= 0!");
145
146        const String& wire_layer = getParameter("WireLayer");
147        double wire_width = getGenProperties()->get("WireWidth").toDouble();
148        double wire_spacing = getGenProperties()->get("WireSpacing").toDouble();
149
150        // Calculate the total wire cap and total wire res
151        double wire_cap_per_len = getGenProperties()->get("WireCapacitancePerLength").toDouble();
152        double wire_res_per_len = getGenProperties()->get("WireResistancePerLength").toDouble();
153        double total_wire_cap = wire_cap_per_len * wire_length;
154        double total_wire_res = wire_res_per_len * wire_length;
155
156        m_repeater_->update();
157
158        unsigned int increment_segments = (isKeepParity)? 2:1;
159        unsigned int number_segments = increment_segments;
160        double delay;
161        m_repeater_->setMinDrivingStrength();
162        m_repeater_->getNet("Y")->setDistributedCap(total_wire_cap / number_segments);
163        m_repeater_->getNet("Y")->setDistributedRes(total_wire_res / number_segments);
164        m_repeater_load_->setLoadCap(m_repeater_->getNet("A")->getTotalDownstreamCap());
165        m_timing_tree_->performCritPathExtract(m_repeater_->getNet("A"));
166        delay = m_timing_tree_->calculateCritPathDelay(m_repeater_->getNet("A")) * number_segments;
167
168        // If everything is 0, use number_segments min-sized repeater
169        if(wire_length != 0)
170        {
171            // Set the initial number of segments based on isKeepParity
172            double last_min_size_delay = 0;
173            unsigned int iteration = 0;
174
175            // First set the repeater to the minimum driving strength
176            last_min_size_delay = delay;
177
178            Log::printLine(getInstanceName() + " -> Beginning Repeater Insertion");
179
180            while(required_delay < delay)
181            {
182                Log::printLine(getInstanceName() + " -> Repeater Insertion Iteration " + (String)iteration +
183                        ": Required delay = " + (String)required_delay +
184                        ", Delay = " + (String)delay +
185                        ", Slack = " + (String)(required_delay - delay) +
186                        ", Number of repeaters = " + (String)number_segments);
187
188                // Size up if timing is not met
189                while(required_delay < delay)
190                {
191                    if(m_repeater_->hasMaxDrivingStrength())
192                    {
193                        break;
194                    }
195                    m_repeater_->increaseDrivingStrength();
196                    m_repeater_load_->setLoadCap(m_repeater_->getNet("A")->getTotalDownstreamCap());
197                    m_timing_tree_->performCritPathExtract(m_repeater_->getNet("A"));
198                    delay = m_timing_tree_->calculateCritPathDelay(m_repeater_->getNet("A")) * number_segments;
199
200                    iteration++;
201                    Log::printLine(getInstanceName() + " -> Slack: " + (String)(required_delay - delay));
202                }
203                // Increase number of segments if timing is not met
204                if(required_delay < delay)
205                {
206                    number_segments += increment_segments;
207                    m_repeater_->setMinDrivingStrength();
208                    m_repeater_->getNet("Y")->setDistributedCap(total_wire_cap / number_segments);
209                    m_repeater_->getNet("Y")->setDistributedRes(total_wire_res / number_segments);
210                    m_repeater_load_->setLoadCap(m_repeater_->getNet("A")->getTotalDownstreamCap());
211                    m_timing_tree_->performCritPathExtract(m_repeater_->getNet("A"));
212                    delay = m_timing_tree_->calculateCritPathDelay(m_repeater_->getNet("A")) * number_segments;
213
214                    // Abort if adding more min sized repeaters does not decrease the delay
215                    if(delay > last_min_size_delay)
216                    {
217                        break;
218                    }
219                    last_min_size_delay = delay;
220                }
221            }
222            Log::printLine(getInstanceName() + " -> Repeater Insertion Ended after Iteration: " + (String)iteration +
223                    ": Required delay = " + (String)required_delay +
224                    ", Delay = " + (String)delay +
225                    ", Slack = " + (String)(required_delay - delay) +
226                    ", Number of repeaters = " + (String)number_segments);
227
228            // Print a warning if the timing is not met
229            if(required_delay < delay)
230            {
231                const String& warning_msg = "[Warning] " + getInstanceName() + " -> Timing not met" +
232                    ": Required delay = " + (String)required_delay +
233                    ", Delay = " + (String)delay +
234                    ", Slack = " + (String)(required_delay - delay) +
235                    ", Number of repeaters = " + (String)number_segments;
236                Log::printLine(std::cerr, warning_msg);
237            }
238        }
239
240        // Update electrical interfaces
241        getLoad("In_Cap")->setLoadCap(m_repeater_->getNet("A")->getTotalDownstreamCap());
242        getDelay("In_to_Out_delay")->setDelay(delay);
243        getDriver("Out_Ron")->setOutputRes(m_repeater_->getDriver("Y_Ron")->getOutputRes() + (total_wire_res / number_segments));
244
245        getGenProperties()->set("NumberSegments", number_segments);
246
247        // Update area, power results
248        resetElectricalAtomicResults();
249        addElecticalAtomicResultValues(m_repeater_, number_segments * number_bits);
250        double wire_area = wire_length * (wire_width + wire_spacing) * number_bits;
251        addElecticalWireAtomicResultValue(wire_layer, wire_area);
252
253        return;
254    }
255
256    void RepeatedLink::useModel()
257    {
258        // Update the transition information for the modeled repeater
259        // Since we only modeled one repeater. So the transition information for 0->0 and 1->1
260        // is averaged out
261        const TransitionInfo& trans_In = getInputPort("In")->getTransitionInfo();
262        double average_static_transition = (trans_In.getNumberTransitions00() + trans_In.getNumberTransitions11()) / 2.0;
263        TransitionInfo mod_trans_In(average_static_transition, trans_In.getNumberTransitions01(), average_static_transition);
264        m_repeater_->getInputPort("A")->setTransitionInfo(mod_trans_In);
265        m_repeater_->use();
266
267        // Get parameters
268        unsigned int number_bits = getParameter("NumberBits").toUInt();
269        unsigned int number_segments = getGenProperties()->get("NumberSegments").toUInt();
270
271        // Propagate the transition information
272        propagateTransitionInfo();
273
274        // Update leakage power
275        double power = 0.0;
276        power += m_repeater_->getNddPowerResult("Leakage")->calculateSum() * number_segments * number_bits;
277        getNddPowerResult("Leakage")->setValue(power);
278
279        // Update event result
280        double energy = 0.0;
281        energy += m_repeater_->getEventResult("INV")->calculateSum() * number_segments * number_bits;
282        getEventResult("Send")->setValue(energy);
283
284        return;
285    }
286
287    void RepeatedLink::propagateTransitionInfo()
288    {
289        unsigned int number_segments = getGenProperties()->get("NumberSegments");
290
291        if((number_segments % 2) == 0)
292        {
293            propagatePortTransitionInfo("Out", "In");
294        }
295        else
296        {
297            const TransitionInfo& trans_In = getInputPort("In")->getTransitionInfo();
298            TransitionInfo trans_Out(trans_In.getNumberTransitions11(), trans_In.getNumberTransitions01(), trans_In.getNumberTransitions00());
299            getOutputPort("Out")->setTransitionInfo(trans_Out);
300        }
301        return;
302    }
303
304} // namespace DSENT
305
306