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 36namespace 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 343