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/std_cells/BUF.h" 23 24#include <cmath> 25 26#include "model/PortInfo.h" 27#include "model/TransitionInfo.h" 28#include "model/EventInfo.h" 29#include "model/std_cells/StdCellLib.h" 30#include "model/std_cells/CellMacros.h" 31#include "model/timing_graph/ElectricalNet.h" 32#include "model/timing_graph/ElectricalDriver.h" 33#include "model/timing_graph/ElectricalLoad.h" 34#include "model/timing_graph/ElectricalDelay.h" 35 36namespace DSENT 37{ 38 using std::max; 39 40 BUF::BUF(const String& instance_name_, const TechModel* tech_model_) 41 : StdCell(instance_name_, tech_model_) 42 { 43 initProperties(); 44 } 45 46 BUF::~BUF() 47 {} 48 49 void BUF::initProperties() 50 { 51 return; 52 } 53 54 void BUF::constructModel() 55 { 56 createInputPort("A"); 57 createOutputPort("Y"); 58 59 createLoad("A_Cap"); 60 createDelay("A_to_Y_delay"); 61 createDriver("Y_Ron", true); 62 63 ElectricalLoad* a_cap = getLoad("A_Cap"); 64 ElectricalDelay* a_to_y_delay = getDelay("A_to_Y_delay"); 65 ElectricalDriver* y_ron = getDriver("Y_Ron"); 66 67 getNet("A")->addDownstreamNode(a_cap); 68 a_cap->addDownstreamNode(a_to_y_delay); 69 a_to_y_delay->addDownstreamNode(y_ron); 70 y_ron->addDownstreamNode(getNet("Y")); 71 72 // Create Area result 73 // Create NDD Power result 74 createElectricalAtomicResults(); 75 // Create OR Event Energy Result 76 createElectricalEventAtomicResult("BUF"); 77 78 getEventInfo("Idle")->setStaticTransitionInfos(); 79 80 return; 81 } 82 83 void BUF::updateModel() 84 { 85 // Get parameters 86 double drive_strength = getDrivingStrength(); 87 Map<double>* cache = getTechModel()->getStdCellLib()->getStdCellCache(); 88 89 // Standard cell cache string 90 const String& cell_name = "BUF_X" + (String) drive_strength; 91 92 // Get timing parameters 93 getLoad("A_Cap")->setLoadCap(cache->get(cell_name + "->Cap->A")); 94 getDelay("A_to_Y_delay")->setDelay(cache->get(cell_name + "->Delay->A_to_Y")); 95 getDriver("Y_Ron")->setOutputRes(cache->get(cell_name + "->DriveRes->Y")); 96 97 // Set the cell area 98 getAreaResult("Active")->setValue(cache->get(cell_name + "->ActiveArea")); 99 getAreaResult("Metal1Wire")->setValue(cache->get(cell_name + "->ActiveArea")); 100 101 return; 102 } 103 104 void BUF::evaluateModel() 105 { 106 return; 107 } 108 109 void BUF::useModel() 110 { 111 // Get parameters 112 double drive_strength = getDrivingStrength(); 113 Map<double>* cache = getTechModel()->getStdCellLib()->getStdCellCache(); 114 115 // Stadard cell cache string 116 const String& cell_name = "BUF_X" + (String) drive_strength; 117 118 // Propagate the transition info and get the 0->1 transtion count 119 propagateTransitionInfo(); 120 double P_A = getInputPort("A")->getTransitionInfo().getProbability1(); 121 double Y_num_trans_01 = getOutputPort("Y")->getTransitionInfo().getNumberTransitions01(); 122 123 // Calculate leakage 124 double leakage = 0; 125 leakage += cache->get(cell_name + "->Leakage->!A") * (1 - P_A); 126 leakage += cache->get(cell_name + "->Leakage->A") * P_A; 127 getNddPowerResult("Leakage")->setValue(leakage); 128 129 // Get VDD 130 double vdd = getTechModel()->get("Vdd"); 131 132 // Get capacitances 133 double y_b_cap = cache->get(cell_name + "->Cap->Y_b"); 134 double y_cap = cache->get(cell_name + "->Cap->Y"); 135 double y_load_cap = getNet("Y")->getTotalDownstreamCap(); 136 137 // Calculate BUFEvent energy 138 double energy_per_trans_01 = (y_b_cap + y_cap + y_load_cap) * vdd * vdd; 139 getEventResult("BUF")->setValue(energy_per_trans_01 * Y_num_trans_01); 140 141 return; 142 } 143 144 void BUF::propagateTransitionInfo() 145 { 146 // Get input signal transition info 147 const TransitionInfo& trans_A = getInputPort("A")->getTransitionInfo(); 148 149 getOutputPort("Y")->setTransitionInfo(trans_A); 150 return; 151 } 152 153 // Creates the standard cell, characterizes and abstracts away the details 154 void BUF::cacheStdCell(StdCellLib* cell_lib_, double drive_strength_) 155 { 156 // Get parameters 157 double gate_pitch = cell_lib_->getTechModel()->get("Gate->PitchContacted"); 158 Map<double>* cache = cell_lib_->getStdCellCache(); 159 160 // Stadard cell cache string 161 const String& cell_name = "BUF_X" + (String) drive_strength_; 162 163 Log::printLine("=== " + cell_name + " ==="); 164 165 // Now actually build the full standard cell model 166 createInputPort("A"); 167 createOutputPort("Y"); 168 169 createNet("Y_b"); 170 171 // Adds macros 172 CellMacros::addInverter(this, "INV0", false, true, "A", "Y_b"); 173 CellMacros::addInverter(this, "INV1", false, true, "Y_b", "Y"); 174 175 // Update macros 176 CellMacros::updateInverter(this, "INV0", drive_strength_ * 0.367); 177 CellMacros::updateInverter(this, "INV1", drive_strength_ * 1.0); 178 179 // Cache area result 180 double area = 0.0; 181 area += gate_pitch * getTotalHeight() * 1; 182 area += gate_pitch * getTotalHeight() * getGenProperties()->get("INV0_GatePitches").toDouble(); 183 area += gate_pitch * getTotalHeight() * getGenProperties()->get("INV1_GatePitches").toDouble(); 184 cache->set(cell_name + "->ActiveArea", area); 185 Log::printLine(cell_name + "->ActiveArea=" + (String)area); 186 187 // -------------------------------------------------------------------- 188 // Leakage Model Calculation 189 // -------------------------------------------------------------------- 190 // Cache leakage power results (for every single signal combination) 191 double leakage_0 = 0.0; // !A 192 double leakage_1 = 0.0; // A 193 194 leakage_0 += getGenProperties()->get("INV0_LeakagePower_0").toDouble(); 195 leakage_0 += getGenProperties()->get("INV1_LeakagePower_1").toDouble(); 196 197 leakage_1 += getGenProperties()->get("INV0_LeakagePower_1").toDouble(); 198 leakage_1 += getGenProperties()->get("INV1_LeakagePower_0").toDouble(); 199 200 cache->set(cell_name + "->Leakage->!A", leakage_0); 201 cache->set(cell_name + "->Leakage->A", leakage_1); 202 Log::printLine(cell_name + "->Leakage->!A=" + (String) leakage_0); 203 Log::printLine(cell_name + "->Leakage->A=" + (String) leakage_1); 204 // -------------------------------------------------------------------- 205 206 // -------------------------------------------------------------------- 207 // Get Node Capacitances 208 // -------------------------------------------------------------------- 209 double a_cap = getNet("A")->getTotalDownstreamCap(); 210 double y_b_cap = getNet("Y_b")->getTotalDownstreamCap(); 211 double y_cap = getNet("Y")->getTotalDownstreamCap(); 212 213 cache->set(cell_name + "->Cap->A", a_cap); 214 cache->set(cell_name + "->Cap->Y_b", y_b_cap); 215 cache->set(cell_name + "->Cap->Y", y_cap); 216 Log::printLine(cell_name + "->Cap->A_Cap=" + (String) a_cap); 217 Log::printLine(cell_name + "->Cap->Y_b_Cap=" + (String) y_b_cap); 218 Log::printLine(cell_name + "->Cap->Y_Cap=" + (String) y_cap); 219 // -------------------------------------------------------------------- 220 221 // -------------------------------------------------------------------- 222 // Build Internal Delay Model 223 // -------------------------------------------------------------------- 224 double y_ron = getDriver("INV1_RonZN")->getOutputRes(); 225 double a_to_y_delay = getDriver("INV0_RonZN")->calculateDelay() + 226 getDriver("INV1_RonZN")->calculateDelay(); 227 228 cache->set(cell_name + "->DriveRes->Y", y_ron); 229 cache->set(cell_name + "->Delay->A_to_Y", a_to_y_delay); 230 Log::printLine(cell_name + "->DriveRes->Y=" + (String) y_ron); 231 Log::printLine(cell_name + "->Delay->A_to_Y=" + (String) a_to_y_delay); 232 // -------------------------------------------------------------------- 233 234 return; 235 } 236} // namespace DSENT 237 238