1 /* Copyright (c) 2012 Massachusetts Institute of Technology
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:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
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
22 #include "model/electrical/DFFRAM.h"
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"
40 DFFRAM::DFFRAM(const String
& instance_name_
, const TechModel
* tech_model_
)
41 : ElectricalModel(instance_name_
, tech_model_
)
50 void DFFRAM::initParameters()
52 addParameterName("NumberEntries");
53 addParameterName("NumberBits");
57 void DFFRAM::initProperties()
62 DFFRAM
* DFFRAM::clone() const
68 void DFFRAM::constructModel()
71 unsigned int number_bits
= getParameter("NumberBits").toUInt();
72 unsigned int number_entries
= getParameter("NumberEntries").toUInt();
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!");
79 unsigned int number_addr_bits
= (unsigned int)ceil(log2(number_entries
));
82 createInputPort("In", makeNetIndex(0, number_bits
-1));
83 for(unsigned int i
= 0; i
< number_addr_bits
; ++i
)
85 createInputPort("WRAddr" + (String
)i
);
86 createInputPort("RDAddr" + (String
)i
);
88 createInputPort("WE");
89 createInputPort("CK");
90 createOutputPort("Out", makeNetIndex(0, number_bits
-1));
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));
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
)
103 getEventInfo("Read")->setTransitionInfo("WRAddr" + (String
)i
, TransitionInfo(0.5, 0.0, 0.5));
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
)
110 getEventInfo("Write")->setTransitionInfo("RDAddr" + (String
)i
, TransitionInfo(0.5, 0.0, 0.5));
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
)
118 dff_names
[i
] = "DFF_" + (String
)i
;
119 dffs
[i
] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", dff_names
[i
]);
120 dffs
[i
]->construct();
123 const String
& dec_name
= "Dec";
124 Decoder
* dec
= new Decoder(dec_name
, getTechModel());
125 dec
->setParameter("NumberOutputs", number_entries
);
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");
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
);
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
)
150 nand2cg1_names
[i
] = "NAND2_CKGate1_" + (String
)i
;
151 nand2cg1s
[i
] = getTechModel()->getStdCellLib()->createStdCell("NAND2", nand2cg1_names
[i
]);
152 nand2cg1s
[i
]->construct();
154 invcg1_names
[i
] = "INV_CKGate1_" + (String
)i
;
155 invcg1s
[i
] = getTechModel()->getStdCellLib()->createStdCell("INV", invcg1_names
[i
]);
156 invcg1s
[i
]->construct();
160 for(unsigned int i
= 0; i
< number_addr_bits
; ++i
)
162 portConnect(dec
, "Addr" + (String
)i
, "WRAddr" + (String
)i
);
164 for(unsigned int i
= 0; i
< number_entries
; ++i
)
166 createNet("Dec_Out" + (String
)i
);
167 portConnect(dec
, "Out" + (String
)i
, "Dec_Out" + (String
)i
);
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");
179 // Connect CKGate1 - CKGate0, Dec_Out
180 for(unsigned int i
= 0; i
< number_entries
; ++i
)
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
);
192 for(unsigned int i
= 0; i
< number_entries
; ++i
)
194 createNet("DFF_Out" + (String
)i
);
195 for(unsigned int n
= 0; n
< number_bits
; ++n
)
197 portConnect(dffs
[i
], "D", "In", makeNetIndex(n
));
198 portConnect(dffs
[i
], "CK", "CKGate1_Outs" + (String
)i
);
200 portConnect(dffs
[i
], "Q", "DFF_Out" + (String
)i
);
203 // Connect Multiplexer
204 createNet("Mux_Out");
205 for(unsigned int i
= 0; i
< number_entries
; ++i
)
207 portConnect(mux
, "In" + (String
)i
, "DFF_Out" + (String
)i
);
209 for(unsigned int i
= 0; i
< number_addr_bits
; ++i
)
211 portConnect(mux
, "Sel" + (String
)i
, "RDAddr" + (String
)i
);
213 portConnect(mux
, "Out", "Mux_Out");
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
)
221 drive_mult
->addDownstreamNode(getNet("Out", makeNetIndex(n
)));
224 // Add area and power results
225 for(unsigned int i
= 0; i
< number_entries
; ++i
)
227 addSubInstances(dffs
[i
], number_bits
);
228 addElectricalSubResults(dffs
[i
], number_bits
);
231 addSubInstances(dec
, 1.0);
232 addElectricalSubResults(dec
, 1.0);
234 addSubInstances(mux
, number_bits
);
235 addElectricalSubResults(mux
, number_bits
);
237 addSubInstances(nand2cg0
, 1.0);
238 addElectricalSubResults(nand2cg0
, 1.0);
240 addSubInstances(invcg0
, 1);
241 addElectricalSubResults(invcg0
, 1.0);
243 for(unsigned int i
= 0; i
< number_entries
; ++i
)
245 addSubInstances(nand2cg1s
[i
], 1);
246 addElectricalSubResults(nand2cg1s
[i
], 1.0);
248 addSubInstances(invcg1s
[i
], 1);
249 addElectricalSubResults(invcg1s
[i
], 1.0);
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
)
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
);
267 Result
* read_event
= getEventResult("Read");
268 //for(unsigned int i = 0; i < number_entries; ++i)
270 // read_event->addSubResult(dffs[i]->getEventResult("DFFQ"), dff_names[i], number_bits);
272 read_event
->addSubResult(mux
->getEventResult("Mux"), mux_name
, number_bits
);
277 void DFFRAM::propagateTransitionInfo()
279 // Update probability
280 unsigned int number_entries
= (unsigned int)getParameter("NumberEntries");
281 unsigned int number_addr_bits
= (unsigned int)ceil(log2(number_entries
));
284 ElectricalModel
* dec
= (ElectricalModel
*)getSubInstance("Dec");
285 for(unsigned int i
= 0; i
< number_addr_bits
; ++i
)
287 propagatePortTransitionInfo(dec
, "Addr" + (String
)i
, "WRAddr" + (String
)i
);
291 // Update CKGate0 nands + invs
292 ElectricalModel
* nand2cg0
= (ElectricalModel
*)getSubInstance("NAND2_CKGate0");
293 propagatePortTransitionInfo(nand2cg0
, "A", "CK");
294 propagatePortTransitionInfo(nand2cg0
, "B", "WE");
296 ElectricalModel
* invcg0
= (ElectricalModel
*)getSubInstance("INV_CKGate0");
297 propagatePortTransitionInfo(invcg0
, "A", nand2cg0
, "Y");
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
)
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
);
310 invcg1s
[i
] = (ElectricalModel
*)getSubInstance("INV_CKGate1_" + (String
)i
);
311 propagatePortTransitionInfo(invcg1s
[i
], "A", nand2cg1s
[i
], "Y");
316 vector
<ElectricalModel
*> dffs(number_entries
, NULL
);
317 for(unsigned int i
= 0; i
< number_entries
; ++i
)
319 dffs
[i
] = (ElectricalModel
*)getSubInstance("DFF_" + (String
)i
);
320 propagatePortTransitionInfo(dffs
[i
], "D", "In");
321 propagatePortTransitionInfo(dffs
[i
], "CK", invcg1s
[i
], "Y");
326 ElectricalModel
* mux
= (ElectricalModel
*)getSubInstance("Mux");
327 for(unsigned int i
= 0; i
< number_entries
; ++i
)
329 propagatePortTransitionInfo(mux
, "In" + (String
)i
, dffs
[i
], "Q");
331 for(unsigned int i
= 0; i
< number_addr_bits
; ++i
)
333 propagatePortTransitionInfo(mux
, "Sel" + (String
)i
, "RDAddr" + (String
)i
);
337 // Set output probability
338 getOutputPort("Out")->setTransitionInfo(mux
->getOutputPort("Out")->getTransitionInfo());