sim, kvm: make KvmVM a System parameter
[gem5.git] / ext / dsent / model / electrical / BarrelShifter.cc
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/electrical/BarrelShifter.h"
23 #include "model/electrical/Multiplexer.h"
24
25 #include <cmath>
26
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"
34
35 namespace DSENT
36 {
37 BarrelShifter::BarrelShifter(const String& instance_name_, const TechModel* tech_model_)
38 : ElectricalModel(instance_name_, tech_model_)
39 {
40 initParameters();
41 initProperties();
42 }
43
44 BarrelShifter::~BarrelShifter()
45 {}
46
47 void BarrelShifter::initParameters()
48 {
49 addParameterName("NumberBits");
50 addParameterName("ShiftIndexMin");
51 addParameterName("ShiftIndexMax");
52 addParameterName("BitDuplicate", "TRUE");
53 return;
54 }
55
56 void BarrelShifter::initProperties()
57 {
58 return;
59 }
60
61 BarrelShifter* BarrelShifter::clone() const
62 {
63 return NULL;
64 }
65
66 void BarrelShifter::constructModel()
67 {
68 // Get parameters
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");
74
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)
78 {
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!");
85 }
86
87 //Construct electrical ports
88 //Create each input port
89 createInputPort( "In", makeNetIndex(0, number_bits-1));
90 //Create output
91 createOutputPort( "Out", makeNetIndex(0, number_bits-1));
92
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);
97
98 //Create energy, power, and area results
99 createElectricalResults();
100 createElectricalEventResult("BarrelShift");
101 //Set conditions during idle event
102 getEventInfo("Idle")->setStaticTransitionInfos();
103
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))
106 assign("Out", "In");
107 else
108 {
109 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i)
110 {
111 //Create internally buffered shift select signals
112 createNet("Shift_b" + (String) i);
113 createNet("Shift_i" + (String) i);
114 }
115
116 // Create shift and shifted signals
117 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i)
118 {
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]
125
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));
133 }
134
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));
143
144 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i)
145 {
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);
149
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();
157
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);
163
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);
171
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);
178 mux->construct();
179
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);
186 //Connect mux output
187 portConnect(mux, "Out", "R_" + n_next);
188
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);
193 }
194 }
195 return;
196 }
197
198 void BarrelShifter::propagateTransitionInfo()
199 {
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");
205
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)
211 {
212 for (unsigned int i = shift_index_min; i <= shift_index_max; ++i)
213 {
214 unsigned int current_shifts = (unsigned int)pow(2, i);
215 String n = (String) current_shifts;
216
217 // Set the
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;
221
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);
225 buf_inv_0->use();
226
227 ElectricalModel* buf_inv_1 = (ElectricalModel*) getSubInstance(buf_inv_1_name);
228 propagatePortTransitionInfo(buf_inv_1, "A", buf_inv_0, "Y");
229 buf_inv_1->use();
230
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)
235 {
236 propagatePortTransitionInfo(mux, "In0", "In");
237 propagatePortTransitionInfo(mux, "In1", "In");
238 }
239 else
240 {
241 propagatePortTransitionInfo(mux, "In0", last_mux, "Out");
242 propagatePortTransitionInfo(mux, "In1", last_mux, "Out");
243 }
244 mux->use();
245
246 // Set this to be the last mux visted
247 last_mux = mux;
248 }
249 }
250
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
255 else
256 propagatePortTransitionInfo("Out", last_mux, "Out");
257
258 return;
259 }
260
261 } // namespace DSENT
262