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