Decoder.cc revision 10447
1#include "model/electrical/Decoder.h" 2 3#include <cmath> 4 5#include "model/PortInfo.h" 6#include "model/EventInfo.h" 7#include "model/TransitionInfo.h" 8#include "model/std_cells/StdCellLib.h" 9#include "model/std_cells/StdCell.h" 10 11namespace DSENT 12{ 13 using std::ceil; 14 15 Decoder::Decoder(const String& instance_name_, const TechModel* tech_model_) 16 : ElectricalModel(instance_name_, tech_model_) 17 { 18 initParameters(); 19 initProperties(); 20 } 21 22 Decoder::~Decoder() 23 {} 24 25 void Decoder::initParameters() 26 { 27 addParameterName("NumberOutputs"); 28 } 29 30 void Decoder::initProperties() 31 { 32 return; 33 } 34 35 Decoder* Decoder::clone() const 36 { 37 // TODO 38 return NULL; 39 } 40 41 void Decoder::constructModel() 42 { 43 // Get parameters 44 unsigned int number_outputs = getParameter("NumberOutputs").toUInt(); 45 46 ASSERT(number_outputs > 0, "[Error] " + getInstanceName() + " -> Number of outputs must be > 0!"); 47 48 unsigned int number_addr_bits = (unsigned int)ceil(log2(number_outputs)); 49 50 // Create ports 51 for(unsigned int i = 0; i < number_addr_bits; ++i) 52 { 53 createInputPort("Addr" + (String)i); 54 } 55 for(unsigned int i = 0; i < number_outputs; ++i) 56 { 57 createOutputPort("Out" + (String)i); 58 } 59 60 // Create energy, power, and area results 61 createElectricalResults(); 62 createElectricalEventResult("Decode"); 63 Result* decode_event = getEventResult("Decode"); 64 65 getEventInfo("Idle")->setStaticTransitionInfos(); 66 67 if(number_addr_bits == 0) 68 { 69 // Do not need a decoder 70 } 71 else if(number_addr_bits == 1) 72 { 73 const String& inv0_name = "Inv0"; 74 75 StdCell* inv0 = getTechModel()->getStdCellLib()->createStdCell("INV", inv0_name); 76 inv0->construct(); 77 78 // Connect inputs and outputs 79 portConnect(inv0, "A", "Addr0"); 80 portConnect(inv0, "Y", "Out0"); 81 assign("Out1", "Addr0"); 82 83 // Add area, power, and event results 84 addSubInstances(inv0, 1.0); 85 addElectricalSubResults(inv0, 1.0); 86 decode_event->addSubResult(inv0->getEventResult("INV"), inv0_name, 1.0); 87 } 88 else 89 { 90 unsigned int number_addr_bits_0 = (unsigned int)ceil((double)number_addr_bits / 2.0); 91 unsigned int number_addr_bits_1 = (unsigned int)floor((double)number_addr_bits / 2.0); 92 93 unsigned int number_outputs_0 = (unsigned int)pow(2.0, number_addr_bits_0); 94 unsigned int number_outputs_1 = (unsigned int)ceil((double)number_outputs / (double)number_outputs_0); 95 96 const String& dec0_name = "Dec_way0"; 97 const String& dec1_name = "Dec_way1"; 98 vector<String> nand2_names(number_outputs, ""); 99 vector<String> inv_names(number_outputs, ""); 100 for(unsigned int i = 0; i < number_outputs; ++i) 101 { 102 nand2_names[i] = "NAND2_" + (String)i; 103 inv_names[i] = "INV_" + (String)i; 104 } 105 106 Decoder* dec0 = new Decoder(dec0_name, getTechModel()); 107 dec0->setParameter("NumberOutputs", number_outputs_0); 108 dec0->construct(); 109 110 Decoder* dec1 = new Decoder(dec1_name, getTechModel()); 111 dec1->setParameter("NumberOutputs", number_outputs_1); 112 dec1->construct(); 113 114 vector<StdCell*> nand2s(number_outputs, NULL); 115 vector<StdCell*> invs(number_outputs, NULL); 116 for(unsigned int i = 0; i < number_outputs; ++i) 117 { 118 nand2s[i] = getTechModel()->getStdCellLib()->createStdCell("NAND2", nand2_names[i]); 119 nand2s[i]->construct(); 120 invs[i] = getTechModel()->getStdCellLib()->createStdCell("INV", inv_names[i]); 121 invs[i]->construct(); 122 } 123 124 // Connect inputs and outputs 125 for(unsigned int i = 0; i < number_addr_bits_0; ++i) 126 { 127 portConnect(dec0, "Addr" + (String)i, "Addr" + (String)i); 128 } 129 for(unsigned int i = 0; i < number_addr_bits_1; ++i) 130 { 131 portConnect(dec1, "Addr" + (String)i, "Addr" + (String)(i + number_addr_bits_0)); 132 } 133 for(unsigned int i = 0; i < number_outputs_0; ++i) 134 { 135 createNet("way0Out" + (String)i); 136 portConnect(dec0, "Out" + (String)i, "way0Out" + (String)i); 137 } 138 for(unsigned int i = 0; i < number_outputs_1; ++i) 139 { 140 createNet("way1Out" + (String)i); 141 portConnect(dec1, "Out" + (String)i, "way1Out" + (String)i); 142 } 143 144 for(unsigned int i = 0; i < number_outputs; ++i) 145 { 146 createNet("nand" + (String)i + "Out"); 147 portConnect(nand2s[i], "A", "way0Out" + (String)(i%number_outputs_0)); 148 portConnect(nand2s[i], "B", "way1Out" + (String)((unsigned int)floor(i/number_outputs_0))); 149 portConnect(nand2s[i], "Y", "nand" + (String)i + "Out"); 150 portConnect(invs[i], "A", "nand" + (String)i + "Out"); 151 portConnect(invs[i], "Y", "Out" + (String)i); 152 } 153 154 // Add area, power, and event results 155 addSubInstances(dec0, 1.0); 156 addElectricalSubResults(dec0, 1.0); 157 decode_event->addSubResult(dec0->getEventResult("Decode"), dec0_name, 1.0); 158 addSubInstances(dec1, 1.0); 159 addElectricalSubResults(dec1, 1.0); 160 decode_event->addSubResult(dec1->getEventResult("Decode"), dec1_name, 1.0); 161 for(unsigned int i = 0; i < number_outputs; ++i) 162 { 163 addSubInstances(nand2s[i], 1.0); 164 addElectricalSubResults(nand2s[i], 1.0); 165 decode_event->addSubResult(nand2s[i]->getEventResult("NAND2"), nand2_names[i], 1.0); 166 167 addSubInstances(invs[i], 1.0); 168 addElectricalSubResults(invs[i], 1.0); 169 decode_event->addSubResult(invs[i]->getEventResult("INV"), inv_names[i], 1.0); 170 } 171 } 172 return; 173 } 174 175 void Decoder::propagateTransitionInfo() 176 { 177 // The only thing can be updated are the input probabilities 178 unsigned int number_outputs = getParameter("NumberOutputs").toUInt(); 179 180 unsigned int number_addr_bits = (unsigned int)ceil(log2(number_outputs)); 181 182 if(number_addr_bits == 0) 183 { 184 // Do not need a decoder 185 } 186 else if(number_addr_bits == 1) 187 { 188 ElectricalModel* inv0 = (ElectricalModel*)getSubInstance("Inv0"); 189 propagatePortTransitionInfo(inv0, "A", "Addr0"); 190 inv0->use(); 191 192 // Since # addr bits is 1, the output 0 is directly connected 193 propagatePortTransitionInfo("Out0", inv0, "Y"); 194 propagatePortTransitionInfo("Out1", "Addr0"); 195 } 196 else 197 { 198 unsigned int number_addr_bits_0 = (unsigned int)ceil((double)number_addr_bits / 2.0); 199 unsigned int number_addr_bits_1 = (unsigned int)floor((double)number_addr_bits / 2.0); 200 201 unsigned int number_outputs_0 = (unsigned int)pow(2.0, number_addr_bits_0); 202 203 // Update decoders with probabilities 204 ElectricalModel* dec0 = (ElectricalModel*)getSubInstance("Dec_way0"); 205 for(unsigned int i = 0; i < number_addr_bits_0; ++i) 206 { 207 propagatePortTransitionInfo(dec0, "Addr" + (String)i, "Addr" + (String)i); 208 } 209 dec0->use(); 210 ElectricalModel* dec1 = (ElectricalModel*)getSubInstance("Dec_way1"); 211 for(unsigned int i = 0; i < number_addr_bits_1; ++i) 212 { 213 propagatePortTransitionInfo(dec1, "Addr" + (String)i, "Addr" + (String)(i + number_addr_bits_0)); 214 } 215 dec1->use(); 216 217 for(unsigned int i = 0; i < number_outputs; ++i) 218 { 219 ElectricalModel* nand2 = (ElectricalModel*)getSubInstance("NAND2_" + (String)i); 220 propagatePortTransitionInfo(nand2, "A", dec0, "Out" + (String)(i%number_outputs_0)); 221 propagatePortTransitionInfo(nand2, "B", dec1, "Out" + (String)((unsigned int)floor(i/number_outputs_0))); 222 nand2->use(); 223 224 ElectricalModel* inv = (ElectricalModel*)getSubInstance("INV_" + (String)i); 225 propagatePortTransitionInfo(inv, "A", nand2, "Y"); 226 inv->use(); 227 228 propagatePortTransitionInfo("Out" + (String)i, inv, "Y"); 229 } 230 } 231 return; 232 } 233 234} // namespace DSENT 235 236