sim, kvm: make KvmVM a System parameter
[gem5.git] / ext / dsent / model / electrical / MultiplexerCrossbar.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/MultiplexerCrossbar.h"
23
24 #include <vector>
25 #include <cmath>
26
27 #include "model/PortInfo.h"
28 #include "model/EventInfo.h"
29 #include "model/TransitionInfo.h"
30 #include "model/timing_graph/ElectricalNet.h"
31 #include "model/electrical/Multiplexer.h"
32
33 namespace DSENT
34 {
35 using std::ceil;
36 using std::vector;
37
38 MultiplexerCrossbar::MultiplexerCrossbar(const String& instance_name_, const TechModel* tech_model_)
39 : ElectricalModel(instance_name_, tech_model_)
40 {
41 initParameters();
42 initProperties();
43 }
44
45 MultiplexerCrossbar::~MultiplexerCrossbar()
46 {}
47
48 void MultiplexerCrossbar::initParameters()
49 {
50 addParameterName("NumberInputs");
51 addParameterName("NumberOutputs");
52 addParameterName("NumberBits");
53 addParameterName("BitDuplicate", "TRUE");
54 return;
55 }
56
57 void MultiplexerCrossbar::initProperties()
58 {
59 return;
60 }
61
62 MultiplexerCrossbar* MultiplexerCrossbar::clone() const
63 {
64 // TODO
65 return NULL;
66 }
67
68 void MultiplexerCrossbar::constructModel()
69 {
70 // Get Parameters
71 unsigned int number_inputs = getParameter("NumberInputs").toUInt();
72 unsigned int number_outputs = getParameter("NumberOutputs").toUInt();
73 unsigned int number_bits = getParameter("NumberBits").toUInt();
74 bool bit_duplicate = getParameter("BitDuplicate").toBool();
75
76 ASSERT(number_inputs > 0, "[Error] " + getInstanceName() + " -> Number of inputs must be > 0!");
77 ASSERT(number_outputs > 0, "[Error] " + getInstanceName() + " -> Number of outputs must be > 0!");
78 ASSERT(number_bits > 0, "[Error] " + getInstanceName() + " -> Number of bits must be > 0!");
79
80 unsigned int number_selects = (unsigned int)ceil(log2((double)number_inputs));
81 getGenProperties()->set("NumberSelectsPerPort", number_selects);
82
83 // Construct electrical ports and nets
84 // Create input ports
85 for(unsigned int i = 0; i < number_inputs; ++i)
86 {
87 createInputPort("In" + (String)i, makeNetIndex(0, number_bits-1));
88 }
89 // Create select signals
90 for(unsigned int i = 0; i < number_outputs; ++i)
91 {
92 for(unsigned int j = 0; j < number_selects; ++j)
93 {
94 createInputPort(String::format("Sel%d_%d", i, j));
95 }
96 }
97 // Create output ports
98 for(unsigned int i = 0; i < number_outputs; ++i)
99 {
100 createOutputPort("Out" + (String)i, makeNetIndex(0, number_bits-1));
101 }
102
103 // Create energy, power, and area results
104 addAreaResult(new AtomicResult("CrossbarWire"));
105 addAreaResult(new AtomicResult("CrossbarFill"));
106 createElectricalResults();
107 getEventInfo("Idle")->setStaticTransitionInfos();
108 createElectricalEventResult("Multicast0");
109 getEventInfo("Multicast0")->setStaticTransitionInfos();
110 for(unsigned int i = 1; i <= number_outputs; ++i)
111 {
112 createElectricalEventResult("Multicast" + (String)i);
113 EventInfo* event_info = getEventInfo("Multicast" + (String)i);
114 // Assuming that In0 is sending to Out0, Out1, ..., Outi
115 // and other input ports are static
116 for(unsigned int j = 1; j < number_inputs; ++j)
117 {
118 event_info->setStaticTransitionInfo("In" + (String)j);
119 }
120 for(unsigned int j = i; j < number_outputs; ++j)
121 {
122 for(unsigned int k = 0; k < number_selects; ++k)
123 {
124 event_info->setStaticTransitionInfo(String::format("Sel%d_%d", j, k));
125 }
126 }
127 }
128 createElectricalEventResult("Crossbar");
129
130 // Initiate multiplexers
131 vector<String> mux_names(number_outputs, "");
132 vector<Multiplexer*> muxs(number_outputs, NULL);
133 for(unsigned int i = 0; i < number_outputs; ++i)
134 {
135 mux_names[i] = "Mux" + (String)i;
136 muxs[i] = new Multiplexer(mux_names[i], getTechModel());
137 muxs[i]->setParameter("NumberInputs", number_inputs);
138 muxs[i]->setParameter("NumberBits", number_bits);
139 muxs[i]->setParameter("BitDuplicate", bit_duplicate);
140 muxs[i]->construct();
141 }
142
143 // Connect inputs and outputs to multiplexers
144 for(unsigned int i = 0; i < number_outputs; ++i)
145 {
146 // Connect inputs
147 for(unsigned int j = 0; j < number_inputs; ++j)
148 {
149 portConnect(muxs[i], "In" + (String)j, "In" + (String)j, makeNetIndex(0, number_bits-1));
150 }
151
152 // Connect select signals
153 for(unsigned int j = 0; j < number_selects; ++j)
154 {
155 portConnect(muxs[i], "Sel" + (String)j, String::format("Sel%d_%d", i, j));
156 }
157
158 // Connect outputs
159 portConnect(muxs[i], "Out", "Out" + (String)i, makeNetIndex(0, number_bits-1));
160 }
161
162 // Add area, power, and event results for each mux
163 for(unsigned int i = 0; i < number_outputs; ++i)
164 {
165 addSubInstances(muxs[i], 1.0);
166 addElectricalSubResults(muxs[i], 1.0);
167 for(unsigned int j = 0; j <= number_outputs; ++j)
168 {
169 getEventResult("Multicast" + (String)j)->addSubResult(muxs[i]->getEventResult("Mux"), mux_names[i], 1.0);
170 }
171 getEventResult("Crossbar")->addSubResult(muxs[i]->getEventResult("Mux"), mux_names[i], 1.0);
172 }
173
174 // Estimate wiring area
175 const String& crossbar_wire_layer = "Intermediate";
176 addElectricalWireSubResult(crossbar_wire_layer, getAreaResult("CrossbarWire"), "Self", 1.0);
177 double wire_width = getTechModel()->get("Wire->" + crossbar_wire_layer + "->MinWidth").toDouble();
178 double wire_spacing = getTechModel()->get("Wire->" + crossbar_wire_layer + "->MinSpacing").toDouble();
179 double wire_pitch = wire_width + wire_spacing;
180 double wire_area = (number_bits * number_inputs * wire_pitch) * (number_bits * number_outputs * wire_pitch);
181 getAreaResult("CrossbarWire")->setValue(wire_area);
182
183 // Add filler area
184 getAreaResult("Active")->addSubResult(getAreaResult("CrossbarFill"), "Self", 1.0);
185 return;
186 }
187
188 void MultiplexerCrossbar::updateModel()
189 {
190 // Update all sub instances
191 Model::updateModel();
192
193 // Update filler area
194 // Total Active area = max(stdcell active area, wiring area);
195 double wire_area = getAreaResult("CrossbarWire")->calculateSum();
196 double active_area = getAreaResult("Active")->calculateSum();
197 double fill_area = 0.0;
198 if(active_area < wire_area)
199 {
200 fill_area = wire_area - active_area;
201 }
202 getAreaResult("CrossbarFill")->setValue(fill_area);
203 return;
204 }
205
206 void MultiplexerCrossbar::propagateTransitionInfo()
207 {
208 // The only thing can be updated are the input probabilities
209 const unsigned int number_inputs = getParameter("NumberInputs").toUInt();
210 const unsigned int number_outputs = getParameter("NumberOutputs").toUInt();
211
212 const unsigned int number_selects = getGenProperties()->get("NumberSelectsPerPort").toUInt();
213
214 for(unsigned int i = 0; i < number_outputs; ++i)
215 {
216 ElectricalModel* muxi = (ElectricalModel*)getSubInstance("Mux" + (String)i);
217 for(unsigned int j = 0; j < number_inputs; ++j)
218 {
219 propagatePortTransitionInfo(muxi, "In" + (String)j, "In" + (String)j);
220 }
221 for(unsigned int j = 0; j < number_selects; ++j)
222 {
223 propagatePortTransitionInfo(muxi, "Sel" + (String)j, String::format("Sel%d_%d", i, j));
224 }
225 muxi->use();
226
227 // Set output probability
228 propagatePortTransitionInfo("Out" + (String)i, muxi, "Out");
229 }
230
231 return;
232 }
233
234 } // namespace DSENT
235