BarrelShifter.cc revision 10447:a465576671d4
1#include "model/electrical/BarrelShifter.h" 2#include "model/electrical/Multiplexer.h" 3 4#include <cmath> 5 6#include "model/PortInfo.h" 7#include "model/TransitionInfo.h" 8#include "model/EventInfo.h" 9#include "model/timing_graph/ElectricalDriverMultiplier.h" 10#include "model/timing_graph/ElectricalNet.h" 11#include "model/std_cells/StdCell.h" 12#include "model/std_cells/StdCellLib.h" 13 14namespace DSENT 15{ 16 BarrelShifter::BarrelShifter(const String& instance_name_, const TechModel* tech_model_) 17 : ElectricalModel(instance_name_, tech_model_) 18 { 19 initParameters(); 20 initProperties(); 21 } 22 23 BarrelShifter::~BarrelShifter() 24 {} 25 26 void BarrelShifter::initParameters() 27 { 28 addParameterName("NumberBits"); 29 addParameterName("ShiftIndexMin"); 30 addParameterName("ShiftIndexMax"); 31 addParameterName("BitDuplicate", "TRUE"); 32 return; 33 } 34 35 void BarrelShifter::initProperties() 36 { 37 return; 38 } 39 40 BarrelShifter* BarrelShifter::clone() const 41 { 42 return NULL; 43 } 44 45 void BarrelShifter::constructModel() 46 { 47 // Get parameters 48 unsigned int number_bits = getParameter("NumberBits"); 49 unsigned int number_shift_bits = (unsigned int)ceil(log2((double) number_bits)); 50 unsigned int shift_index_min = getParameter("ShiftIndexMin"); 51 unsigned int shift_index_max = getParameter("ShiftIndexMax"); 52 bool bit_duplicate = (bool) getParameter("BitDuplicate"); 53 54 ASSERT(number_bits > 0, "[Error] " + getInstanceName() + " -> Number of bits must be > 0!"); 55 // No need to check these if there arent any shifts 56 if (number_shift_bits > 0) 57 { 58 ASSERT(shift_index_min <= number_shift_bits, 59 "[Error] " + getInstanceName() + " -> Min shift index must be >= 0 and <= " + 60 "the total number of shift bits!"); 61 ASSERT(shift_index_max >= shift_index_min && shift_index_max <= number_shift_bits, 62 "[Error] " + getInstanceName() + " -> Max shift index must be >= minimum shift index and <= " + 63 "the total number of shift bits!"); 64 } 65 66 //Construct electrical ports 67 //Create each input port 68 createInputPort( "In", makeNetIndex(0, number_bits-1)); 69 //Create output 70 createOutputPort( "Out", makeNetIndex(0, number_bits-1)); 71 72 //Create shift ports (which only exists if there is something to shift) 73 if (shift_index_min != number_shift_bits) 74 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) 75 createInputPort( "Shift" + (String) i); 76 77 //Create energy, power, and area results 78 createElectricalResults(); 79 createElectricalEventResult("BarrelShift"); 80 //Set conditions during idle event 81 getEventInfo("Idle")->setStaticTransitionInfos(); 82 83 //If the input is only 1-bit, connect input to output and be done 84 if (number_shift_bits == 0 || (shift_index_min == number_shift_bits)) 85 assign("Out", "In"); 86 else 87 { 88 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) 89 { 90 //Create internally buffered shift select signals 91 createNet("Shift_b" + (String) i); 92 createNet("Shift_i" + (String) i); 93 } 94 95 // Create shift and shifted signals 96 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) 97 { 98 unsigned int current_shifts = (unsigned int)pow(2, i); 99 const String& n = (String) current_shifts; 100 //Instantiate and connect intermediate nets. In a barrel-shifter, the nets do 101 //all the "shifting" and the muxes just select which to take 102 createNet("R_" + n, makeNetIndex(0, number_bits-1)); //wire R_n[number_bits-1:0] 103 createNet("RS_" + n, makeNetIndex(0, number_bits-1)); //wire RS_n[number_bits-1:0] 104 105 //Implements the shifts 106 //assign RS_n[number_bits-1:number_bits-current_shifts] = R_n[current_shifts-1:0]; 107 assign("RS_" + n, makeNetIndex(number_bits-current_shifts, number_bits-1), 108 "R_" + n, makeNetIndex(0, current_shifts-1)); 109 //assign RS_n[number_bits-current_shifts-1:0] = R_n[current_shifts:number_bits-1]; 110 assign("RS_" + n, makeNetIndex(0, number_bits-current_shifts-1), 111 "R_" + n, makeNetIndex(current_shifts, number_bits-1)); 112 } 113 114 const String& n_max = (String) pow(2, shift_index_max+1); 115 const String& n_min = (String) pow(2, shift_index_min); 116 // Create the R_(max) net 117 createNet("R_" + n_max, makeNetIndex(0, number_bits-1)); 118 // Set R_1 to be the input 119 assign("R_" + n_min, "In"); 120 // Set R_(max) to be the output 121 assign("Out", "R_" + n_max, makeNetIndex(0, number_bits-1)); 122 123 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) 124 { 125 unsigned int current_shifts = (unsigned int)pow(2, i); 126 const String& n = (String) current_shifts; 127 const String& n_next = (String) (current_shifts * 2); 128 129 const String& buf_inv_0_name = "ShiftBufInv0_" + (String) n; 130 const String& buf_inv_1_name = "ShiftBufInv1_" + (String) n; 131 // Create shift buffer inverters 132 StdCell* buf_inv_0 = getTechModel()->getStdCellLib()->createStdCell("INV", buf_inv_0_name); 133 buf_inv_0->construct(); 134 StdCell* buf_inv_1 = getTechModel()->getStdCellLib()->createStdCell("INV", buf_inv_1_name); 135 buf_inv_1->construct(); 136 137 // Connect up shift buffer inverters 138 portConnect(buf_inv_0, "A", "Shift" + (String) i); 139 portConnect(buf_inv_0, "Y", "Shift_b" + (String) i); 140 portConnect(buf_inv_1, "A", "Shift_b" + (String) i); 141 portConnect(buf_inv_1, "Y", "Shift_i" + (String) i); 142 143 // Add area, power, and event results for inverters 144 addSubInstances(buf_inv_0, 1.0); 145 addSubInstances(buf_inv_1, 1.0); 146 addElectricalSubResults(buf_inv_0, 1.0); 147 addElectricalSubResults(buf_inv_1, 1.0); 148 getEventResult("BarrelShift")->addSubResult(buf_inv_0->getEventResult("INV"), buf_inv_0_name, 1.0); 149 getEventResult("BarrelShift")->addSubResult(buf_inv_1->getEventResult("INV"), buf_inv_1_name, 1.0); 150 151 //Instantiate 2:1 multiplexers, one for each shift bit. 152 const String& mux_name = "SRL" + n; 153 Multiplexer* mux = new Multiplexer(mux_name, getTechModel()); 154 mux->setParameter("NumberInputs", 2); 155 mux->setParameter("NumberBits", number_bits); 156 mux->setParameter("BitDuplicate", bit_duplicate); 157 mux->construct(); 158 159 //Just have to connect the In0 and In1 inputs of the mux to the 160 //non-shifted and shifted intermediate signals, respectively. 161 portConnect(mux, "In0", "R_" + n); 162 portConnect(mux, "In1", "RS_" + n); 163 //Selector connects to the shift signal for that index 164 portConnect(mux, "Sel0", "Shift_i" + (String) i); 165 //Connect mux output 166 portConnect(mux, "Out", "R_" + n_next); 167 168 //Add area, power, and event results for each mux 169 addSubInstances(mux, 1.0); 170 addElectricalSubResults(mux, 1.0); 171 getEventResult("BarrelShift")->addSubResult(mux->getEventResult("Mux"), mux_name, 1.0); 172 } 173 } 174 return; 175 } 176 177 void BarrelShifter::propagateTransitionInfo() 178 { 179 // The only thing can be updated are the input probabilities...so we will update them 180 unsigned int number_bits = (unsigned int) getParameter("NumberBits"); 181 unsigned int number_shift_bits = (unsigned int) ceil(log2((double) number_bits)); 182 unsigned int shift_index_min = getParameter("ShiftIndexMin"); 183 unsigned int shift_index_max = getParameter("ShiftIndexMax"); 184 185 // Keep track of the multiplexer of the last stage 186 ElectricalModel* last_mux = NULL; 187 // We only need to update stuff if we are not shifting by exact multiples 188 // of number of input bits 189 if (shift_index_min < number_shift_bits) 190 { 191 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i) 192 { 193 unsigned int current_shifts = (unsigned int)pow(2, i); 194 String n = (String) current_shifts; 195 196 // Set the 197 const String& buf_inv_0_name = "ShiftBufInv0_" + (String) n; 198 const String& buf_inv_1_name = "ShiftBufInv1_" + (String) n; 199 const String& mux_name = "SRL" + n; 200 201 // Set the transition infos for the inverter buffers 202 ElectricalModel* buf_inv_0 = (ElectricalModel*) getSubInstance(buf_inv_0_name); 203 propagatePortTransitionInfo(buf_inv_0, "A", "Shift" + (String) i); 204 buf_inv_0->use(); 205 206 ElectricalModel* buf_inv_1 = (ElectricalModel*) getSubInstance(buf_inv_1_name); 207 propagatePortTransitionInfo(buf_inv_1, "A", buf_inv_0, "Y"); 208 buf_inv_1->use(); 209 210 // Set the transition infos for the shift multiplexers 211 ElectricalModel* mux = (ElectricalModel*) getSubInstance(mux_name); 212 propagatePortTransitionInfo(mux, "Sel0", buf_inv_1, "Y"); 213 if (last_mux == NULL) 214 { 215 propagatePortTransitionInfo(mux, "In0", "In"); 216 propagatePortTransitionInfo(mux, "In1", "In"); 217 } 218 else 219 { 220 propagatePortTransitionInfo(mux, "In0", last_mux, "Out"); 221 propagatePortTransitionInfo(mux, "In1", last_mux, "Out"); 222 } 223 mux->use(); 224 225 // Set this to be the last mux visted 226 last_mux = mux; 227 } 228 } 229 230 // If there isn't anything to shift 231 if (last_mux == NULL) 232 propagatePortTransitionInfo("Out", "In"); 233 // Take the transition info of the last mux 234 else 235 propagatePortTransitionInfo("Out", last_mux, "Out"); 236 237 return; 238 } 239 240} // namespace DSENT 241 242