DemuxTreeDeserializer.cc revision 10447:a465576671d4
1#include "model/electrical/DemuxTreeDeserializer.h" 2 3#include <cmath> 4 5#include "model/PortInfo.h" 6#include "model/TransitionInfo.h" 7#include "model/EventInfo.h" 8#include "model/std_cells/StdCellLib.h" 9#include "model/std_cells/StdCell.h" 10#include "model/electrical/Multiplexer.h" 11#include "model/timing_graph/ElectricalNet.h" 12 13namespace DSENT 14{ 15 using std::ceil; 16 17 DemuxTreeDeserializer::DemuxTreeDeserializer(const String& instance_name_, const TechModel* tech_model_) 18 : ElectricalModel(instance_name_, tech_model_) 19 { 20 initParameters(); 21 initProperties(); 22 } 23 24 DemuxTreeDeserializer::~DemuxTreeDeserializer() 25 {} 26 27 void DemuxTreeDeserializer::initParameters() 28 { 29 addParameterName("InDataRate"); 30 addParameterName("OutDataRate"); 31 addParameterName("OutBits"); //Output width will just be output width / serialization ratio 32 addParameterName("BitDuplicate", "TRUE"); 33 return; 34 } 35 36 void DemuxTreeDeserializer::initProperties() 37 { 38 return; 39 } 40 41 DemuxTreeDeserializer* DemuxTreeDeserializer::clone() const 42 { 43 // TODO 44 return NULL; 45 } 46 47 void DemuxTreeDeserializer::constructModel() 48 { 49 50 // Get parameters 51 double in_data_rate = getParameter("InDataRate"); 52 double out_data_rate = getParameter("OutDataRate"); 53 unsigned int out_bits = getParameter("OutBits"); 54 bool bit_duplicate = getParameter("BitDuplicate"); 55 56 // Calculate deserialization ratio 57 unsigned int deserialization_ratio = (unsigned int) floor(in_data_rate / out_data_rate); 58 ASSERT(deserialization_ratio == in_data_rate / out_data_rate, 59 "[Error] " + getInstanceName() + " -> Cannot have non-integer deserialization ratios!"); 60 ASSERT((deserialization_ratio & (deserialization_ratio - 1)) == 0, 61 "[Error] " + getInstanceName() + " -> Deserialization ratio must be a power of 2"); 62 63 // Calculate output width 64 unsigned int input_bits = out_bits / deserialization_ratio; 65 ASSERT(out_bits >= deserialization_ratio, "[Error] " + getInstanceName() + 66 " -> Output width must be >= deserialization ratio!"); 67 ASSERT(floor((double) out_bits / deserialization_ratio) == input_bits, 68 "[Error] " + getInstanceName() + " -> Output width must be a multiple of the serialization ratio!"); 69 70 // Store calculated numbers 71 getGenProperties()->set("DeserializationRatio", deserialization_ratio); 72 getGenProperties()->set("InputBits", input_bits); 73 74 // Create ports 75 createInputPort("In", makeNetIndex(0, input_bits-1)); 76 createInputPort("InCK"); 77 createOutputPort("Out", makeNetIndex(0, out_bits-1)); 78 79 //Create energy, power, and area results 80 createElectricalResults(); 81 createElectricalEventResult("Deserialize"); 82 getEventInfo("Deserialize")->setTransitionInfo("InCK", TransitionInfo(0.0, (double) deserialization_ratio / 2.0, 0.0)); 83 // Set conditions during idle state 84 getEventInfo("Idle")->setStaticTransitionInfos(); 85 getEventInfo("Idle")->setTransitionInfo("InCK", TransitionInfo(0.0, (double) deserialization_ratio / 2.0, 0.0)); 86 87 // Mark InCK as a false path (since timing tool will do strange stuff due to all the clock divides and stuff) 88 getNet("InCK")->setFalsePath(true); 89 90 // Create deserializer 91 if (deserialization_ratio == 1) 92 { 93 // No need to do anything, hohoho 94 assign("Out", "In"); 95 } 96 else if (input_bits == 1) 97 { 98 //----------------------------------------------------------------- 99 // Create 2:1 demux deserializer 100 //----------------------------------------------------------------- 101 const String& des_dff_way0_name = "DesDFFWay0"; 102 const String& des_dff_way1_name = "DesDFFWay1"; 103 const String& des_latch_name = "DesLatch"; 104 const String& ck_dff_name = "CKDFF"; 105 const String& ck_inv_name = "CKINV"; 106 const String& out_way0_name = "OutWay0"; 107 const String& out_way1_name = "OutWay1"; 108 const String& mid_way0_name = "MidWay0"; 109 const String& ck_div2_name = "CK_div2"; 110 const String& ck_div2_b_name = "CK_div2_b"; 111 112 // Create nets 113 createNet(out_way0_name); 114 createNet(out_way1_name); 115 createNet(mid_way0_name); 116 createNet(ck_div2_name); 117 createNet(ck_div2_b_name); 118 119 // Create the dffs and latch needed on both ways 120 StdCell* des_dff_way0 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", des_dff_way0_name); 121 des_dff_way0->construct(); 122 StdCell* des_dff_way1 = getTechModel()->getStdCellLib()->createStdCell("DFFQ", des_dff_way1_name); 123 des_dff_way1->construct(); 124 StdCell* des_latch = getTechModel()->getStdCellLib()->createStdCell("LATQ", des_latch_name); 125 des_latch->construct(); 126 127 // Create clk divide circuit 128 StdCell* ck_dff = getTechModel()->getStdCellLib()->createStdCell("DFFQ", ck_dff_name); 129 ck_dff->construct(); 130 StdCell* ck_inv = getTechModel()->getStdCellLib()->createStdCell("INV", ck_inv_name); 131 ck_inv->construct(); 132 133 // Connect ports 134 portConnect(des_dff_way0, "CK", "InCK"); 135 portConnect(des_dff_way0, "D", mid_way0_name); 136 portConnect(des_dff_way0, "Q", out_way0_name); 137 portConnect(des_latch, "G", "InCK"); 138 portConnect(des_latch, "D", "In"); 139 portConnect(des_latch, "Q", mid_way0_name); 140 portConnect(des_dff_way1, "CK", "InCK"); 141 portConnect(des_dff_way1, "D", "In"); 142 portConnect(des_dff_way1, "Q", out_way1_name); 143 portConnect(ck_dff, "CK", "InCK"); 144 portConnect(ck_dff, "D", ck_div2_b_name); 145 portConnect(ck_dff, "Q", ck_div2_name); 146 portConnect(ck_inv, "A", ck_div2_name); 147 portConnect(ck_inv, "Y", ck_div2_b_name); 148 149 // Add sub instances 150 addSubInstances(des_dff_way0, 1.0); 151 addElectricalSubResults(des_dff_way0, 1.0); 152 addSubInstances(des_dff_way1, 1.0); 153 addElectricalSubResults(des_dff_way1, 1.0); 154 addSubInstances(des_latch, 1.0); 155 addElectricalSubResults(des_latch, 1.0); 156 addSubInstances(ck_dff, 1.0); 157 addElectricalSubResults(ck_dff, 1.0); 158 addSubInstances(ck_inv, 1.0); 159 addElectricalSubResults(ck_inv, 1.0); 160 161 Result* deserialize = getEventResult("Deserialize"); 162 deserialize->addSubResult(des_dff_way0->getEventResult("CK"), des_dff_way0_name, 1.0); 163 deserialize->addSubResult(des_dff_way0->getEventResult("DFFD"), des_dff_way0_name, 1.0); 164 deserialize->addSubResult(des_dff_way0->getEventResult("DFFQ"), des_dff_way0_name, 1.0); 165 deserialize->addSubResult(des_dff_way1->getEventResult("CK"), des_dff_way1_name, 1.0); 166 deserialize->addSubResult(des_dff_way1->getEventResult("DFFD"), des_dff_way1_name, 1.0); 167 deserialize->addSubResult(des_dff_way1->getEventResult("DFFQ"), des_dff_way1_name, 1.0); 168 deserialize->addSubResult(des_latch->getEventResult("G"), des_latch_name, 1.0); 169 deserialize->addSubResult(des_latch->getEventResult("LATD"), des_latch_name, 1.0); 170 deserialize->addSubResult(des_latch->getEventResult("LATQ"), des_latch_name, 1.0); 171 deserialize->addSubResult(ck_dff->getEventResult("CK"), ck_dff_name, 1.0); 172 deserialize->addSubResult(ck_dff->getEventResult("DFFD"), ck_dff_name, 1.0); 173 deserialize->addSubResult(ck_dff->getEventResult("DFFQ"), ck_dff_name, 1.0); 174 deserialize->addSubResult(ck_inv->getEventResult("INV"), ck_inv_name, 1.0); 175 //----------------------------------------------------------------- 176 177 //----------------------------------------------------------------- 178 // Create Sub-deserializers 179 //----------------------------------------------------------------- 180 // Create sub-deserializers 181 const String& demux_way0_name = "DemuxTree_way0_" + (String) deserialization_ratio + "_to_1"; 182 const String& demux_way1_name = "DemuxTree_way1_" + (String) deserialization_ratio + "_to_1"; 183 184 DemuxTreeDeserializer* demux_way0 = new DemuxTreeDeserializer(demux_way0_name, getTechModel()); 185 demux_way0->setParameter("InDataRate", in_data_rate / 2.0); 186 demux_way0->setParameter("OutDataRate", out_data_rate); 187 demux_way0->setParameter("OutBits", out_bits / 2); 188 demux_way0->setParameter("BitDuplicate", "TRUE"); 189 demux_way0->construct(); 190 191 DemuxTreeDeserializer* demux_way1 = new DemuxTreeDeserializer(demux_way1_name, getTechModel()); 192 demux_way1->setParameter("InDataRate", in_data_rate / 2.0); 193 demux_way1->setParameter("OutDataRate", out_data_rate); 194 demux_way1->setParameter("OutBits", out_bits / 2); 195 demux_way1->setParameter("BitDuplicate", "TRUE"); 196 demux_way1->construct(); 197 198 // Connect ports 199 portConnect(demux_way0, "In", out_way0_name); 200 portConnect(demux_way0, "InCK", ck_div2_name); 201 portConnect(demux_way0, "Out", "Out", makeNetIndex(0, out_bits/2-1)); 202 203 portConnect(demux_way1, "In", out_way1_name); 204 portConnect(demux_way1, "InCK", ck_div2_name); 205 portConnect(demux_way1, "Out", "Out", makeNetIndex(out_bits/2, out_bits-1)); 206 207 // Add subinstances and area results 208 addSubInstances(demux_way0, 1.0); 209 addElectricalSubResults(demux_way0, 1.0); 210 addSubInstances(demux_way1, 1.0); 211 addElectricalSubResults(demux_way1, 1.0); 212 213 deserialize->addSubResult(demux_way0->getEventResult("Deserialize"), demux_way0_name, 1.0); 214 deserialize->addSubResult(demux_way1->getEventResult("Deserialize"), demux_way1_name, 1.0); 215 //----------------------------------------------------------------- 216 217 } 218 else if (bit_duplicate) 219 { 220 const String& demux_name = "DemuxTree_" + (String) deserialization_ratio + "_to_1"; 221 222 DemuxTreeDeserializer* des_bit = new DemuxTreeDeserializer(demux_name, getTechModel()); 223 des_bit->setParameter("InDataRate", in_data_rate); 224 des_bit->setParameter("OutDataRate", out_data_rate); 225 des_bit->setParameter("OutBits", deserialization_ratio); 226 des_bit->setParameter("BitDuplicate", "TRUE"); 227 des_bit->construct(); 228 229 // Create VFI and VFO nets 230 createNet("InVFI"); 231 createNet("OutVFO", makeNetIndex(0, deserialization_ratio-1)); 232 233 // Connect ports 234 portConnect(des_bit, "In", "InVFI"); 235 portConnect(des_bit, "Out", "OutVFO"); 236 237 // Do VFI and VFO 238 assignVirtualFanin("InVFI", "In"); 239 for (unsigned int i = 0; i < input_bits; ++i) 240 { 241 portConnect(des_bit, "InCK", "InCK"); 242 for (unsigned int j = 0; j < deserialization_ratio; ++j) 243 assignVirtualFanout("Out", makeNetIndex(i*deserialization_ratio + j), "OutVFO", makeNetIndex(j)); 244 } 245 // Add subinstances and area results 246 addSubInstances(des_bit, input_bits); 247 addElectricalSubResults(des_bit, input_bits); 248 getEventResult("Deserialize")->addSubResult(des_bit->getEventResult("Deserialize"), demux_name, input_bits); 249 } 250 else 251 { 252 //Instantiate a bunch of 1 input bit deserializers 253 for (unsigned int i = 0; i < input_bits; ++i) 254 { 255 const String& demux_name = "DemuxTree_" + (String) deserialization_ratio + "_to_1_bit" + (String) i; 256 257 DemuxTreeDeserializer* des_bit = new DemuxTreeDeserializer(demux_name, getTechModel()); 258 des_bit->setParameter("InDataRate", in_data_rate); 259 des_bit->setParameter("OutDataRate", out_data_rate); 260 des_bit->setParameter("OutBits", deserialization_ratio); 261 des_bit->setParameter("BitDuplicate", "TRUE"); 262 des_bit->construct(); 263 264 portConnect(des_bit, "In", "In", makeNetIndex(i)); 265 portConnect(des_bit, "InCK", "InCK"); 266 portConnect(des_bit, "Out", "Out", makeNetIndex(i*deserialization_ratio, (i+1)*deserialization_ratio-1)); 267 268 addSubInstances(des_bit, 1.0); 269 addElectricalSubResults(des_bit, 1.0); 270 getEventResult("Deserialize")->addSubResult(des_bit->getEventResult("Deserialize"), demux_name, 1.0); 271 } 272 } 273 274 return; 275 } 276 277 void DemuxTreeDeserializer::propagateTransitionInfo() 278 { 279 // Get parameters 280 bool bit_duplicate = getParameter("BitDuplicate"); 281 // Get generated properties 282 unsigned int deserialization_ratio = getGenProperties()->get("DeserializationRatio"); 283 unsigned int input_bits = getGenProperties()->get("InputBits"); 284 285 // Calculate output transitions and activities 286 if (deserialization_ratio == 1) 287 { 288 // If no deserialization, then just propagate input transition info to output port 289 propagatePortTransitionInfo("Out", "In"); 290 } 291 else if (input_bits == 1) 292 { 293 const String& des_dff_way0_name = "DesDFFWay0"; 294 const String& des_dff_way1_name = "DesDFFWay1"; 295 const String& des_latch_name = "DesLatch"; 296 const String& ck_dff_name = "CKDFF"; 297 const String& ck_inv_name = "CKINV"; 298 299 // Sub-deserializer names 300 const String& demux_way0_name = "DemuxTree_way0_" + (String) deserialization_ratio + "_to_1"; 301 const String& demux_way1_name = "DemuxTree_way1_" + (String) deserialization_ratio + "_to_1"; 302 303 // Update transition info for deserialization registers/latches 304 ElectricalModel* des_latch = (ElectricalModel*) getSubInstance(des_latch_name); 305 propagatePortTransitionInfo(des_latch, "G", "InCK"); 306 propagatePortTransitionInfo(des_latch, "D", "In"); 307 des_latch->use(); 308 309 ElectricalModel* des_dff_way0 = (ElectricalModel*) getSubInstance(des_dff_way0_name); 310 propagatePortTransitionInfo(des_dff_way0, "CK", "InCK"); 311 propagatePortTransitionInfo(des_dff_way0, "D", des_latch, "Q"); 312 des_dff_way0->use(); 313 314 ElectricalModel* des_dff_way1 = (ElectricalModel*) getSubInstance(des_dff_way1_name); 315 propagatePortTransitionInfo(des_dff_way1, "CK", "InCK"); 316 propagatePortTransitionInfo(des_dff_way1, "D", "In"); 317 des_dff_way1->use(); 318 319 // Get input transitions of input clock 320 double P01_CK = getInputPort("InCK")->getTransitionInfo().getNumberTransitions01(); 321 // Update transition info for clk division DFF 322 ElectricalModel* ck_dff = (ElectricalModel*) getSubInstance(ck_dff_name); 323 propagatePortTransitionInfo(ck_dff, "CK", "InCK"); 324 // Since it is a clock divider, P01 is D and Q are simply half the P01 of D and Q of 325 // the input clock 326 if (P01_CK != 0) ck_dff->getInputPort("D")->setTransitionInfo(TransitionInfo(0.0, P01_CK * 0.5, 0.0)); 327 else ck_dff->getInputPort("D")->setTransitionInfo(TransitionInfo(0.5, 0.0, 0.5)); 328 329 ck_dff->use(); 330 // Update transition info of clk divided inverter 331 ElectricalModel* ck_inv = (ElectricalModel*) getSubInstance(ck_inv_name); 332 propagatePortTransitionInfo(ck_inv, "A", ck_dff, "Q"); 333 ck_inv->use(); 334 335 // Update transition info for next demux stages 336 ElectricalModel* demux_way0 = (ElectricalModel*) getSubInstance(demux_way0_name); 337 propagatePortTransitionInfo(demux_way0, "In", des_dff_way0, "Q"); 338 propagatePortTransitionInfo(demux_way0, "InCK", ck_dff, "Q"); 339 demux_way0->use(); 340 ElectricalModel* demux_way1 = (ElectricalModel*) getSubInstance(demux_way1_name); 341 propagatePortTransitionInfo(demux_way1, "In", des_dff_way1, "Q"); 342 propagatePortTransitionInfo(demux_way1, "InCK", ck_dff, "Q"); 343 demux_way1->use(); 344 345 propagatePortTransitionInfo("Out", demux_way0, "Out"); 346 } 347 else if (bit_duplicate) 348 { 349 // Propagate transition info 350 const String& demux_name = "DemuxTree_" + (String) deserialization_ratio + "_to_1"; 351 ElectricalModel* demux = (ElectricalModel*) getSubInstance(demux_name); 352 propagatePortTransitionInfo(demux, "In", "In"); 353 propagatePortTransitionInfo(demux, "InCK", "InCK"); 354 demux->use(); 355 356 propagatePortTransitionInfo("Out", demux, "Out"); 357 } 358 else 359 { 360 // Set output probability to be average that of probabilties of each output bit 361 // Update all 1 bit deserializers 362 for (unsigned int i = 0; i < input_bits; ++i) 363 { 364 const String& demux_name = "DemuxTree_" + (String) deserialization_ratio + "_to_1_bit" + (String) i; 365 ElectricalModel* demux_bit = (ElectricalModel*) getSubInstance(demux_name); 366 propagatePortTransitionInfo(demux_bit, "In", "In"); 367 propagatePortTransitionInfo(demux_bit, "InCK", "InCK"); 368 demux_bit->use(); 369 370 propagatePortTransitionInfo("Out", demux_bit, "Out"); 371 } 372 } 373 374 return; 375 } 376 377} // namespace DSENT 378 379