DFFRAM.cc revision 10447:a465576671d4
1#include "model/electrical/DFFRAM.h"
2
3#include <cmath>
4
5#include "model/PortInfo.h"
6#include "model/EventInfo.h"
7#include "model/TransitionInfo.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#include "model/electrical/Decoder.h"
13#include "model/electrical/Multiplexer.h"
14
15namespace DSENT
16{
17    using std::ceil;
18
19    DFFRAM::DFFRAM(const String& instance_name_, const TechModel* tech_model_)
20        : ElectricalModel(instance_name_, tech_model_)
21    {
22        initParameters();
23        initProperties();
24    }
25
26    DFFRAM::~DFFRAM()
27    {}
28
29    void DFFRAM::initParameters()
30    {
31        addParameterName("NumberEntries");
32        addParameterName("NumberBits");
33        return;
34    }
35
36    void DFFRAM::initProperties()
37    {
38        return;
39    }
40
41    DFFRAM* DFFRAM::clone() const
42    {
43        // TODO
44        return NULL;
45    }
46
47    void DFFRAM::constructModel()
48    {
49        // Get parameters
50        unsigned int number_bits = getParameter("NumberBits").toUInt();
51        unsigned int number_entries = getParameter("NumberEntries").toUInt();
52
53        ASSERT(number_bits > 0, "[Error] " + getInstanceName() +
54            " -> Number of bits must be > 0!");
55        ASSERT(number_entries > 0, "[Error] " + getInstanceName() +
56            " -> Number of entries must be > 0!");
57
58        unsigned int number_addr_bits = (unsigned int)ceil(log2(number_entries));
59
60        // Create ports
61        createInputPort("In", makeNetIndex(0, number_bits-1));
62        for(unsigned int i = 0; i < number_addr_bits; ++i)
63        {
64            createInputPort("WRAddr" + (String)i);
65            createInputPort("RDAddr" + (String)i);
66        }
67        createInputPort("WE");
68        createInputPort("CK");
69        createOutputPort("Out", makeNetIndex(0, number_bits-1));
70
71        // Create energy, power, and area results
72        createElectricalResults();
73        getEventInfo("Idle")->setStaticTransitionInfos();
74        getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
75        getEventInfo("Idle")->setTransitionInfo("WE", TransitionInfo(1.0, 0.0, 0.0));
76
77        createElectricalEventResult("Read");
78        getEventInfo("Read")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
79        getEventInfo("Read")->setTransitionInfo("WE", TransitionInfo(1.0, 0.0, 0.0));
80        for(unsigned int i = 0; i < number_addr_bits; ++i)
81        {
82            getEventInfo("Read")->setTransitionInfo("WRAddr" + (String)i, TransitionInfo(0.5, 0.0, 0.5));
83        }
84        createElectricalEventResult("Write");
85        getEventInfo("Write")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0));
86        getEventInfo("Write")->setTransitionInfo("WE", TransitionInfo(0.0, 0.0, 1.0));
87        for(unsigned int i = 0; i < number_addr_bits; ++i)
88        {
89            getEventInfo("Write")->setTransitionInfo("RDAddr" + (String)i, TransitionInfo(0.5, 0.0, 0.5));
90        }
91
92        // Init components - DFF array, Dec, Mux
93        vector<String> dff_names(number_entries, "");
94        vector<StdCell*> dffs(number_entries, NULL);
95        for(unsigned int i = 0; i < number_entries; ++i)
96        {
97            dff_names[i] = "DFF_" + (String)i;
98            dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", dff_names[i]);
99            dffs[i]->construct();
100        }
101
102        const String& dec_name = "Dec";
103        Decoder* dec = new Decoder(dec_name, getTechModel());
104        dec->setParameter("NumberOutputs", number_entries);
105        dec->construct();
106
107        const String& mux_name = "Mux";
108        Multiplexer* mux = new Multiplexer(mux_name, getTechModel());
109        mux->setParameter("NumberInputs", number_entries);
110        mux->setParameter("NumberBits", 1);
111        mux->setParameter("BitDuplicate", "TRUE");
112        mux->construct();
113
114        // Init components - CK & WE
115        const String& nand2cg0_name = "NAND2_CKGate0";
116        StdCell* nand2cg0 = getTechModel()->getStdCellLib()->createStdCell("NAND2", nand2cg0_name);
117        nand2cg0->construct();
118        const String& invcg0_name = "INV_CKGate0";
119        StdCell* invcg0 = getTechModel()->getStdCellLib()->createStdCell("INV", invcg0_name);
120        invcg0->construct();
121
122        // Init components - (CK & WE) & DecOut[i]
123        vector<String> nand2cg1_names(number_entries, "");
124        vector<StdCell*> nand2cg1s(number_entries, NULL);
125        vector<String> invcg1_names(number_entries, "");
126        vector<StdCell*> invcg1s(number_entries, NULL);
127        for(unsigned int i = 0; i < number_entries; ++i)
128        {
129            nand2cg1_names[i] = "NAND2_CKGate1_" + (String)i;
130            nand2cg1s[i] = getTechModel()->getStdCellLib()->createStdCell("NAND2", nand2cg1_names[i]);
131            nand2cg1s[i]->construct();
132
133            invcg1_names[i] = "INV_CKGate1_" + (String)i;
134            invcg1s[i] = getTechModel()->getStdCellLib()->createStdCell("INV", invcg1_names[i]);
135            invcg1s[i]->construct();
136        }
137
138        // Connect Decoder
139        for(unsigned int i = 0; i < number_addr_bits; ++i)
140        {
141            portConnect(dec, "Addr" + (String)i, "WRAddr" + (String)i);
142        }
143        for(unsigned int i = 0; i < number_entries; ++i)
144        {
145            createNet("Dec_Out" + (String)i);
146            portConnect(dec, "Out" + (String)i, "Dec_Out" + (String)i);
147        }
148
149        // Connect CKGate0 - CK, WE
150        createNet("NAND2_CKGate0_Out");
151        createNet("CKGate0_Out");
152        portConnect(nand2cg0, "A", "CK");
153        portConnect(nand2cg0, "B", "WE");
154        portConnect(nand2cg0, "Y", "NAND2_CKGate0_Out");
155        portConnect(invcg0, "A", "NAND2_CKGate0_Out");
156        portConnect(invcg0, "Y", "CKGate0_Out");
157
158        // Connect CKGate1 - CKGate0, Dec_Out
159        for(unsigned int i = 0; i < number_entries; ++i)
160        {
161            createNet("NAND2_CKGate1_Outs" + (String)i);
162            createNet("CKGate1_Outs" + (String)i);
163            portConnect(nand2cg1s[i], "A", "CKGate0_Out");
164            portConnect(nand2cg1s[i], "B", "Dec_Out" + (String)i);
165            portConnect(nand2cg1s[i], "Y", "NAND2_CKGate1_Outs" + (String)i);
166            portConnect(invcg1s[i], "A", "NAND2_CKGate1_Outs" + (String)i);
167            portConnect(invcg1s[i], "Y", "CKGate1_Outs" + (String)i);
168        }
169
170        // Connect DFF array
171        for(unsigned int i = 0; i < number_entries; ++i)
172        {
173            createNet("DFF_Out" + (String)i);
174            for(unsigned int n = 0; n < number_bits; ++n)
175            {
176                portConnect(dffs[i], "D", "In", makeNetIndex(n));
177                portConnect(dffs[i], "CK", "CKGate1_Outs" + (String)i);
178            }
179            portConnect(dffs[i], "Q", "DFF_Out" + (String)i);
180        }
181
182        // Connect Multiplexer
183        createNet("Mux_Out");
184        for(unsigned int i = 0; i < number_entries; ++i)
185        {
186            portConnect(mux, "In" + (String)i, "DFF_Out" + (String)i);
187        }
188        for(unsigned int i = 0; i < number_addr_bits; ++i)
189        {
190            portConnect(mux, "Sel" + (String)i, "RDAddr" + (String)i);
191        }
192        portConnect(mux, "Out", "Mux_Out");
193
194        // Use driver multiplier to connect Mux_Out to Out
195        createDriverMultiplier("OutMult");
196        ElectricalDriverMultiplier* drive_mult = getDriverMultiplier("OutMult");
197        getNet("Mux_Out")->addDownstreamNode(drive_mult);
198        for(unsigned int n = 0; n < number_bits; ++n)
199        {
200            drive_mult->addDownstreamNode(getNet("Out", makeNetIndex(n)));
201        }
202
203        // Add area and power results
204        for(unsigned int i = 0; i < number_entries; ++i)
205        {
206            addSubInstances(dffs[i], number_bits);
207            addElectricalSubResults(dffs[i], number_bits);
208        }
209
210        addSubInstances(dec, 1.0);
211        addElectricalSubResults(dec, 1.0);
212
213        addSubInstances(mux, number_bits);
214        addElectricalSubResults(mux, number_bits);
215
216        addSubInstances(nand2cg0, 1.0);
217        addElectricalSubResults(nand2cg0, 1.0);
218
219        addSubInstances(invcg0, 1);
220        addElectricalSubResults(invcg0, 1.0);
221
222        for(unsigned int i = 0; i < number_entries; ++i)
223        {
224            addSubInstances(nand2cg1s[i], 1);
225            addElectricalSubResults(nand2cg1s[i], 1.0);
226
227            addSubInstances(invcg1s[i], 1);
228            addElectricalSubResults(invcg1s[i], 1.0);
229        }
230
231        // Add write event
232        Result* write_event = getEventResult("Write");
233        write_event->addSubResult(nand2cg0->getEventResult("NAND2"), nand2cg0_name, 1.0);
234        write_event->addSubResult(invcg0->getEventResult("INV"), invcg0_name, 1.0);
235        write_event->addSubResult(dec->getEventResult("Decode"), dec_name, 1.0);
236        for(unsigned int i = 0; i < number_entries; ++i)
237        {
238            write_event->addSubResult(nand2cg1s[i]->getEventResult("NAND2"), nand2cg1_names[i], 1.0);
239            write_event->addSubResult(invcg1s[i]->getEventResult("INV"), invcg1_names[i], 1.0);
240            write_event->addSubResult(dffs[i]->getEventResult("DFFD"), dff_names[i], number_bits);
241            write_event->addSubResult(dffs[i]->getEventResult("DFFQ"), dff_names[i], number_bits);
242            write_event->addSubResult(dffs[i]->getEventResult("CK"), dff_names[i], number_bits);
243        }
244
245        // Add read event
246        Result* read_event = getEventResult("Read");
247        //for(unsigned int i = 0; i < number_entries; ++i)
248        //{
249        //    read_event->addSubResult(dffs[i]->getEventResult("DFFQ"), dff_names[i], number_bits);
250        //}
251        read_event->addSubResult(mux->getEventResult("Mux"), mux_name, number_bits);
252
253        return;
254    }
255
256    void DFFRAM::propagateTransitionInfo()
257    {
258        // Update probability
259        unsigned int number_entries = (unsigned int)getParameter("NumberEntries");
260        unsigned int number_addr_bits = (unsigned int)ceil(log2(number_entries));
261
262        // Update decoder
263        ElectricalModel* dec = (ElectricalModel*)getSubInstance("Dec");
264        for(unsigned int i = 0; i < number_addr_bits; ++i)
265        {
266            propagatePortTransitionInfo(dec, "Addr" + (String)i, "WRAddr" + (String)i);
267        }
268        dec->use();
269
270        // Update CKGate0 nands + invs
271        ElectricalModel* nand2cg0 = (ElectricalModel*)getSubInstance("NAND2_CKGate0");
272        propagatePortTransitionInfo(nand2cg0, "A", "CK");
273        propagatePortTransitionInfo(nand2cg0, "B", "WE");
274        nand2cg0->use();
275        ElectricalModel* invcg0 = (ElectricalModel*)getSubInstance("INV_CKGate0");
276        propagatePortTransitionInfo(invcg0, "A", nand2cg0, "Y");
277        invcg0->use();
278
279        // Update CKGate1 nands + invs
280        vector<ElectricalModel*> nand2cg1s(number_entries, NULL);
281        vector<ElectricalModel*> invcg1s(number_entries, NULL);
282        for(unsigned int i = 0; i < number_entries; ++i)
283        {
284            nand2cg1s[i] = (ElectricalModel*)getSubInstance("NAND2_CKGate1_" + (String)i);
285            propagatePortTransitionInfo(nand2cg1s[i], "A", invcg0, "Y");
286            propagatePortTransitionInfo(nand2cg1s[i], "B", dec, "Out" + (String)i);
287            nand2cg1s[i]->use();
288
289            invcg1s[i] = (ElectricalModel*)getSubInstance("INV_CKGate1_" + (String)i);
290            propagatePortTransitionInfo(invcg1s[i], "A", nand2cg1s[i], "Y");
291            invcg1s[i]->use();
292        }
293
294        // Update DFF
295        vector<ElectricalModel*> dffs(number_entries, NULL);
296        for(unsigned int i = 0; i < number_entries; ++i)
297        {
298            dffs[i] = (ElectricalModel*)getSubInstance("DFF_" + (String)i);
299            propagatePortTransitionInfo(dffs[i], "D", "In");
300            propagatePortTransitionInfo(dffs[i], "CK", invcg1s[i], "Y");
301            dffs[i]->use();
302        }
303
304        // Update Mux
305        ElectricalModel* mux = (ElectricalModel*)getSubInstance("Mux");
306        for(unsigned int i = 0; i < number_entries; ++i)
307        {
308            propagatePortTransitionInfo(mux, "In" + (String)i, dffs[i], "Q");
309        }
310        for(unsigned int i = 0; i < number_addr_bits; ++i)
311        {
312            propagatePortTransitionInfo(mux, "Sel" + (String)i, "RDAddr" + (String)i);
313        }
314        mux->use();
315
316        // Set output probability
317        getOutputPort("Out")->setTransitionInfo(mux->getOutputPort("Out")->getTransitionInfo());
318        return;
319    }
320} // namespace DSENT
321
322