1 /* Copyright (c) 2012 Massachusetts Institute of Technology
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:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
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
22 #include "model/electrical/BarrelShifter.h"
23 #include "model/electrical/Multiplexer.h"
27 #include "model/PortInfo.h"
28 #include "model/TransitionInfo.h"
29 #include "model/EventInfo.h"
30 #include "model/timing_graph/ElectricalDriverMultiplier.h"
31 #include "model/timing_graph/ElectricalNet.h"
32 #include "model/std_cells/StdCell.h"
33 #include "model/std_cells/StdCellLib.h"
37 BarrelShifter::BarrelShifter(const String
& instance_name_
, const TechModel
* tech_model_
)
38 : ElectricalModel(instance_name_
, tech_model_
)
44 BarrelShifter::~BarrelShifter()
47 void BarrelShifter::initParameters()
49 addParameterName("NumberBits");
50 addParameterName("ShiftIndexMin");
51 addParameterName("ShiftIndexMax");
52 addParameterName("BitDuplicate", "TRUE");
56 void BarrelShifter::initProperties()
61 BarrelShifter
* BarrelShifter::clone() const
66 void BarrelShifter::constructModel()
69 unsigned int number_bits
= getParameter("NumberBits");
70 unsigned int number_shift_bits
= (unsigned int)ceil(log2((double) number_bits
));
71 unsigned int shift_index_min
= getParameter("ShiftIndexMin");
72 unsigned int shift_index_max
= getParameter("ShiftIndexMax");
73 bool bit_duplicate
= (bool) getParameter("BitDuplicate");
75 ASSERT(number_bits
> 0, "[Error] " + getInstanceName() + " -> Number of bits must be > 0!");
76 // No need to check these if there arent any shifts
77 if (number_shift_bits
> 0)
79 ASSERT(shift_index_min
<= number_shift_bits
,
80 "[Error] " + getInstanceName() + " -> Min shift index must be >= 0 and <= " +
81 "the total number of shift bits!");
82 ASSERT(shift_index_max
>= shift_index_min
&& shift_index_max
<= number_shift_bits
,
83 "[Error] " + getInstanceName() + " -> Max shift index must be >= minimum shift index and <= " +
84 "the total number of shift bits!");
87 //Construct electrical ports
88 //Create each input port
89 createInputPort( "In", makeNetIndex(0, number_bits
-1));
91 createOutputPort( "Out", makeNetIndex(0, number_bits
-1));
93 //Create shift ports (which only exists if there is something to shift)
94 if (shift_index_min
!= number_shift_bits
)
95 for (unsigned int i
= shift_index_min
; i
<= shift_index_max
; ++i
)
96 createInputPort( "Shift" + (String
) i
);
98 //Create energy, power, and area results
99 createElectricalResults();
100 createElectricalEventResult("BarrelShift");
101 //Set conditions during idle event
102 getEventInfo("Idle")->setStaticTransitionInfos();
104 //If the input is only 1-bit, connect input to output and be done
105 if (number_shift_bits
== 0 || (shift_index_min
== number_shift_bits
))
109 for (unsigned int i
= shift_index_min
; i
<= shift_index_max
; ++i
)
111 //Create internally buffered shift select signals
112 createNet("Shift_b" + (String
) i
);
113 createNet("Shift_i" + (String
) i
);
116 // Create shift and shifted signals
117 for (unsigned int i
= shift_index_min
; i
<= shift_index_max
; ++i
)
119 unsigned int current_shifts
= (unsigned int)pow(2, i
);
120 const String
& n
= (String
) current_shifts
;
121 //Instantiate and connect intermediate nets. In a barrel-shifter, the nets do
122 //all the "shifting" and the muxes just select which to take
123 createNet("R_" + n
, makeNetIndex(0, number_bits
-1)); //wire R_n[number_bits-1:0]
124 createNet("RS_" + n
, makeNetIndex(0, number_bits
-1)); //wire RS_n[number_bits-1:0]
126 //Implements the shifts
127 //assign RS_n[number_bits-1:number_bits-current_shifts] = R_n[current_shifts-1:0];
128 assign("RS_" + n
, makeNetIndex(number_bits
-current_shifts
, number_bits
-1),
129 "R_" + n
, makeNetIndex(0, current_shifts
-1));
130 //assign RS_n[number_bits-current_shifts-1:0] = R_n[current_shifts:number_bits-1];
131 assign("RS_" + n
, makeNetIndex(0, number_bits
-current_shifts
-1),
132 "R_" + n
, makeNetIndex(current_shifts
, number_bits
-1));
135 const String
& n_max
= (String
) pow(2, shift_index_max
+1);
136 const String
& n_min
= (String
) pow(2, shift_index_min
);
137 // Create the R_(max) net
138 createNet("R_" + n_max
, makeNetIndex(0, number_bits
-1));
139 // Set R_1 to be the input
140 assign("R_" + n_min
, "In");
141 // Set R_(max) to be the output
142 assign("Out", "R_" + n_max
, makeNetIndex(0, number_bits
-1));
144 for (unsigned int i
= shift_index_min
; i
<= shift_index_max
; ++i
)
146 unsigned int current_shifts
= (unsigned int)pow(2, i
);
147 const String
& n
= (String
) current_shifts
;
148 const String
& n_next
= (String
) (current_shifts
* 2);
150 const String
& buf_inv_0_name
= "ShiftBufInv0_" + (String
) n
;
151 const String
& buf_inv_1_name
= "ShiftBufInv1_" + (String
) n
;
152 // Create shift buffer inverters
153 StdCell
* buf_inv_0
= getTechModel()->getStdCellLib()->createStdCell("INV", buf_inv_0_name
);
154 buf_inv_0
->construct();
155 StdCell
* buf_inv_1
= getTechModel()->getStdCellLib()->createStdCell("INV", buf_inv_1_name
);
156 buf_inv_1
->construct();
158 // Connect up shift buffer inverters
159 portConnect(buf_inv_0
, "A", "Shift" + (String
) i
);
160 portConnect(buf_inv_0
, "Y", "Shift_b" + (String
) i
);
161 portConnect(buf_inv_1
, "A", "Shift_b" + (String
) i
);
162 portConnect(buf_inv_1
, "Y", "Shift_i" + (String
) i
);
164 // Add area, power, and event results for inverters
165 addSubInstances(buf_inv_0
, 1.0);
166 addSubInstances(buf_inv_1
, 1.0);
167 addElectricalSubResults(buf_inv_0
, 1.0);
168 addElectricalSubResults(buf_inv_1
, 1.0);
169 getEventResult("BarrelShift")->addSubResult(buf_inv_0
->getEventResult("INV"), buf_inv_0_name
, 1.0);
170 getEventResult("BarrelShift")->addSubResult(buf_inv_1
->getEventResult("INV"), buf_inv_1_name
, 1.0);
172 //Instantiate 2:1 multiplexers, one for each shift bit.
173 const String
& mux_name
= "SRL" + n
;
174 Multiplexer
* mux
= new Multiplexer(mux_name
, getTechModel());
175 mux
->setParameter("NumberInputs", 2);
176 mux
->setParameter("NumberBits", number_bits
);
177 mux
->setParameter("BitDuplicate", bit_duplicate
);
180 //Just have to connect the In0 and In1 inputs of the mux to the
181 //non-shifted and shifted intermediate signals, respectively.
182 portConnect(mux
, "In0", "R_" + n
);
183 portConnect(mux
, "In1", "RS_" + n
);
184 //Selector connects to the shift signal for that index
185 portConnect(mux
, "Sel0", "Shift_i" + (String
) i
);
187 portConnect(mux
, "Out", "R_" + n_next
);
189 //Add area, power, and event results for each mux
190 addSubInstances(mux
, 1.0);
191 addElectricalSubResults(mux
, 1.0);
192 getEventResult("BarrelShift")->addSubResult(mux
->getEventResult("Mux"), mux_name
, 1.0);
198 void BarrelShifter::propagateTransitionInfo()
200 // The only thing can be updated are the input probabilities...so we will update them
201 unsigned int number_bits
= (unsigned int) getParameter("NumberBits");
202 unsigned int number_shift_bits
= (unsigned int) ceil(log2((double) number_bits
));
203 unsigned int shift_index_min
= getParameter("ShiftIndexMin");
204 unsigned int shift_index_max
= getParameter("ShiftIndexMax");
206 // Keep track of the multiplexer of the last stage
207 ElectricalModel
* last_mux
= NULL
;
208 // We only need to update stuff if we are not shifting by exact multiples
209 // of number of input bits
210 if (shift_index_min
< number_shift_bits
)
212 for (unsigned int i
= shift_index_min
; i
<= shift_index_max
; ++i
)
214 unsigned int current_shifts
= (unsigned int)pow(2, i
);
215 String n
= (String
) current_shifts
;
218 const String
& buf_inv_0_name
= "ShiftBufInv0_" + (String
) n
;
219 const String
& buf_inv_1_name
= "ShiftBufInv1_" + (String
) n
;
220 const String
& mux_name
= "SRL" + n
;
222 // Set the transition infos for the inverter buffers
223 ElectricalModel
* buf_inv_0
= (ElectricalModel
*) getSubInstance(buf_inv_0_name
);
224 propagatePortTransitionInfo(buf_inv_0
, "A", "Shift" + (String
) i
);
227 ElectricalModel
* buf_inv_1
= (ElectricalModel
*) getSubInstance(buf_inv_1_name
);
228 propagatePortTransitionInfo(buf_inv_1
, "A", buf_inv_0
, "Y");
231 // Set the transition infos for the shift multiplexers
232 ElectricalModel
* mux
= (ElectricalModel
*) getSubInstance(mux_name
);
233 propagatePortTransitionInfo(mux
, "Sel0", buf_inv_1
, "Y");
234 if (last_mux
== NULL
)
236 propagatePortTransitionInfo(mux
, "In0", "In");
237 propagatePortTransitionInfo(mux
, "In1", "In");
241 propagatePortTransitionInfo(mux
, "In0", last_mux
, "Out");
242 propagatePortTransitionInfo(mux
, "In1", last_mux
, "Out");
246 // Set this to be the last mux visted
251 // If there isn't anything to shift
252 if (last_mux
== NULL
)
253 propagatePortTransitionInfo("Out", "In");
254 // Take the transition info of the last mux
256 propagatePortTransitionInfo("Out", last_mux
, "Out");