sim, kvm: make KvmVM a System parameter
[gem5.git] / ext / dsent / model / electrical / SeparableAllocator.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/SeparableAllocator.h"
23
24 #include "model/ModelGen.h"
25 #include "model/timing_graph/ElectricalNet.h"
26
27 namespace DSENT
28 {
29 SeparableAllocator::SeparableAllocator(const String& instance_name_, const TechModel* tech_model_)
30 : ElectricalModel(instance_name_, tech_model_)
31 {
32 initParameters();
33 initProperties();
34 }
35
36 SeparableAllocator::~SeparableAllocator()
37 {}
38
39 void SeparableAllocator::initParameters()
40 {
41 addParameterName("NumberRequesters");
42 addParameterName("NumberResources");
43 addParameterName("IsRequesterFirst", true);
44 addParameterName("Stage1->ArbiterModel");
45 addParameterName("Stage2->ArbiterModel");
46 return;
47 }
48
49 void SeparableAllocator::initProperties()
50 {
51 addPropertyName("P(Request)");
52 addPropertyName("Act(Request)");
53 addPropertyName("P(CK)");
54 addPropertyName("Act(CK)");
55 return;
56 }
57
58 SeparableAllocator* SeparableAllocator::clone() const
59 {
60 // TODO
61 return NULL;
62 }
63
64 void SeparableAllocator::constructModel()
65 {
66 // Get parameters
67 unsigned int number_requesters = getParameter("NumberRequesters").toUInt();
68 unsigned int number_resources = getParameter("NumberResources").toUInt();
69 bool is_requester_first = getParameter("IsRequesterFirst").toBool();
70 const String& stage1_arbiter_model = getParameter("Stage1->ArbiterModel");
71 const String& stage2_arbiter_model = getParameter("Stage2->ArbiterModel");
72
73 ASSERT(number_requesters > 0, "[Error] " + getInstanceName() +
74 " -> Number of requesters must be > 0!");
75 ASSERT(number_resources > 0, "[Error] " + getInstanceName() +
76 " -> Number of resources must be > 0!");
77
78 // Create area, power, and event results
79 createElectricalResults();
80 addEventResult(new Result("Allocate"));
81
82 // Create ports
83 createInputPort("CK");
84 for(unsigned int i = 0; i < number_requesters; ++i)
85 {
86 createInputPort("Request" + (String)i, makeNetIndex(0, number_resources-1));
87 createOutputPort("Grant" + (String)i, makeNetIndex(0, number_resources-1));
88 }
89
90 // If is_requester_first is set, requests from the same requester will be arbitrate
91 // on stage 1
92 if(is_requester_first)
93 {
94 // Init stage 1 arbiters
95 for(unsigned int i = 0; i < number_requesters; ++i)
96 {
97 ElectricalModel* arb = (ElectricalModel*)ModelGen::createModel(stage1_arbiter_model, "Stage1Arb" + (String)i, getTechModel());
98 arb->setParameter("NumberRequests", number_resources);
99 arb->construct();
100
101 addSubInstances(arb, 1.0);
102 addElectricalSubResults(arb, 1.0);
103
104 getEventResult("Allocate")->addSubResult(arb->getEventResult("Arbitrate"), arb->getInstanceName(), 1.0);
105
106 createNet("Stage1Arb_In" + (String)i, makeNetIndex(0, number_resources-1));
107 createNet("Stage1Arb_Out" + (String)i, makeNetIndex(0, number_resources-1));
108
109 portConnect(arb, "CK", "CK");
110 assign("Stage1Arb_In" + (String)i, "Request" + (String)i);
111 for(unsigned int j = 0; j < number_resources; ++j)
112 {
113 portConnect(arb, "Request" + (String)j, "Stage1Arb_In" + (String)i, makeNetIndex(j));
114 portConnect(arb, "Grant" + (String)j, "Stage1Arb_Out" + (String)i, makeNetIndex(j));
115 }
116 }
117
118 // Init stage 2 arbiters
119 for(unsigned int i = 0; i < number_resources; ++i)
120 {
121 ElectricalModel* arb = (ElectricalModel*)ModelGen::createModel(stage2_arbiter_model, "Stage2Arb" + (String)i, getTechModel());
122 arb->setParameter("NumberRequests", number_requesters);
123 arb->construct();
124
125 addSubInstances(arb, 1.0);
126 addElectricalSubResults(arb, 1.0);
127
128 getEventResult("Allocate")->addSubResult(arb->getEventResult("Arbitrate"), arb->getInstanceName(), 1.0);
129
130 createNet("Stage2Arb_In" + (String)i, makeNetIndex(0, number_requesters-1));
131 createNet("Stage2Arb_Out" + (String)i, makeNetIndex(0, number_requesters-1));
132
133 portConnect(arb, "CK", "CK");
134 for(unsigned int j = 0; j < number_requesters; ++j)
135 {
136 assign("Stage2Arb_In" + (String)i, makeNetIndex(j), "Stage1Arb_Out" + (String)j, makeNetIndex(i));
137 portConnect(arb, "Request" + (String)j, "Stage2Arb_In" + (String)i, makeNetIndex(j));
138 portConnect(arb, "Grant" + (String)j, "Stage2Arb_Out" + (String)i, makeNetIndex(j));
139 assign("Grant" + (String)j, makeNetIndex(i), "Stage2Arb_Out" + (String)i, makeNetIndex(j));
140 }
141 }
142 }
143 else
144 {
145 // Init stage 1 arbiters
146 for(unsigned int i = 0; i < number_resources; ++i)
147 {
148 ElectricalModel* arb = (ElectricalModel*)ModelGen::createModel(stage1_arbiter_model, "Stage1Arb" + (String)i, getTechModel());
149 arb->setParameter("NumberRequests", number_requesters);
150 arb->construct();
151
152 addSubInstances(arb, 1.0);
153 addElectricalSubResults(arb, 1.0);
154
155 getEventResult("Allocate")->addSubResult(arb->getEventResult("Arbitrate"), arb->getInstanceName(), 1.0);
156
157 createNet("Stage1Arb_In" + (String)i, makeNetIndex(0, number_requesters-1));
158 createNet("Stage1Arb_Out" + (String)i, makeNetIndex(0, number_requesters-1));
159
160 portConnect(arb, "CK", "CK");
161 for(unsigned int j = 0; j < number_requesters; ++j)
162 {
163 assign("Stage1Arb_In" + (String)i, makeNetIndex(j), "Request" + (String)j, makeNetIndex(i));
164 portConnect(arb, "Request" + (String)j, "Stage1Arb_In" + (String)i, makeNetIndex(j));
165 portConnect(arb, "Grant" + (String)j, "Stage1Arb_Out" + (String)i, makeNetIndex(j));
166 }
167 }
168
169 // Init stage 2 arbiters
170 for(unsigned int i = 0; i < number_requesters; ++i)
171 {
172 ElectricalModel* arb = (ElectricalModel*)ModelGen::createModel(stage2_arbiter_model, "Stage2Arb" + (String)i, getTechModel());
173 arb->setParameter("NumberRequests", number_requesters);
174 arb->construct();
175
176 addSubInstances(arb, 1.0);
177 addElectricalSubResults(arb, 1.0);
178
179 getEventResult("Allocate")->addSubResult(arb->getEventResult("Arbitrate"), arb->getInstanceName(), 1.0);
180
181 createNet("Stage2Arb_In" + (String)i, makeNetIndex(0, number_resources-1));
182 createNet("Stage2Arb_Out" + (String)i, makeNetIndex(0, number_resources-1));
183
184 portConnect(arb, "CK", "CK");
185 for(unsigned int j = 0; j < number_resources; ++j)
186 {
187 assign("Stage2Arb_In" + (String)i, makeNetIndex(j), "Stage1Arb_Out" + (String)j, makeNetIndex(i));
188 portConnect(arb, "Request" + (String)j, "Stage2Arb_In", makeNetIndex(j));
189 portConnect(arb, "Grant" + (String)j, "Stage2Arb_Out", makeNetIndex(j));
190 }
191 assign("Grant" + (String)i, "Stage2Arb_Out" + (String)i);
192 }
193 }
194 return;
195 }
196
197 void SeparableAllocator::updateModel()
198 {
199 // Get parameters
200 unsigned int number_requesters = getParameter("NumberRequesters").toUInt();
201 unsigned int number_resources = getParameter("NumberResources").toUInt();
202 bool is_requester_first = getParameter("IsRequesterFirst").toBool();
203
204 // Get probabilities from inputs
205 const String& P_request = getProperty("P(Request)");
206 const String& act_request = getProperty("Act(Request)");
207 const String& P_CK = getProperty("P(CK)");
208 const String& act_CK = getProperty("Act(CK)");
209
210 const vector<double>& P_request_vector = LibUtil::castStringVector<double>(P_request.split("[,]"));
211 const vector<double>& act_request_vector = LibUtil::castStringVector<double>(act_request.split("[,]"));
212
213 ASSERT(P_request_vector.size() == (number_requesters * number_resources), "[Error] " + getInstanceName() +
214 " -> Expecting " + (String)(number_requesters * number_resources) +
215 " request probabilities, but got " + P_request);
216 ASSERT(act_request_vector.size() == (number_requesters * number_resources), "[Error] " + getInstanceName() +
217 " -> Expecting " + (String)(number_requesters * number_resources) +
218 " request actvities multiplier, but got " + act_request);
219
220 vector<double> P_int_request_vector(number_requesters * number_resources, 0.0);
221 vector<double> act_int_request_vector(number_requesters * number_resources, 0.0);
222 vector<double> P_out_request_vector(number_requesters * number_resources, 0.0);
223 vector<double> act_out_request_vector(number_requesters * number_resources, 0.0);
224 if(is_requester_first)
225 {
226 // Update stage1 arbiter
227 for(unsigned int i = 0; i < number_requesters; ++i)
228 {
229 vector<double> P_arb_request_vector(number_resources, 0.0);
230 vector<double> act_arb_request_vector(number_resources, 0.0);
231 for(unsigned int j = 0; j < number_resources; ++j)
232 {
233 P_arb_request_vector[j] = P_request_vector[i * number_resources + j];
234 act_arb_request_vector[j] = act_request_vector[i * number_resources + j];
235 }
236
237 Model* arb = getSubInstance("Stage1Arb" + (String)i);
238 arb->setProperty("P(Request)", LibUtil::vectorToString(P_arb_request_vector));
239 arb->setProperty("Act(Request)", LibUtil::vectorToString(act_arb_request_vector));
240 arb->setProperty("P(CK)", P_CK);
241 arb->setProperty("Act(CK)", act_CK);
242 arb->update();
243
244 const vector<double>& P_arb_out_request_vector = LibUtil::castStringVector<double>(arb->getGenProperties()->get("P(Grant)").split("[,]"));
245 const vector<double>& act_arb_out_request_vector = LibUtil::castStringVector<double>(arb->getGenProperties()->get("Act(Grant)").split("[,]"));
246 for(unsigned int j = 0; j < number_resources; ++j)
247 {
248 P_int_request_vector[i * number_resources + j] = P_arb_out_request_vector[j];
249 act_int_request_vector[i * number_resources + j] = act_arb_out_request_vector[j];
250 }
251 }
252 // Update stage2 arbiter
253 for(unsigned int i = 0; i < number_resources; ++i)
254 {
255 vector<double> P_arb_request_vector(number_requesters, 0.0);
256 vector<double> act_arb_request_vector(number_requesters, 0.0);
257 for(unsigned int j = 0; j < number_requesters; ++j)
258 {
259 P_arb_request_vector[j] = P_int_request_vector[j * number_resources + i];
260 act_arb_request_vector[j] = act_int_request_vector[j * number_resources + i];
261 }
262
263 Model* arb = getSubInstance("Stage2Arb" + (String)i);
264 arb->setProperty("P(Request)", LibUtil::vectorToString(P_arb_request_vector));
265 arb->setProperty("Act(Request)", LibUtil::vectorToString(act_arb_request_vector));
266 arb->setProperty("P(CK)", P_CK);
267 arb->setProperty("Act(CK)", act_CK);
268 arb->update();
269
270 const vector<double>& P_arb_out_request_vector = LibUtil::castStringVector<double>(arb->getGenProperties()->get("P(Grant)").split("[,]"));
271 const vector<double>& act_arb_out_request_vector = LibUtil::castStringVector<double>(arb->getGenProperties()->get("Act(Grant)").split("[,]"));
272 for(unsigned int j = 0; j < number_requesters; ++j)
273 {
274 P_out_request_vector[j * number_resources + i] = P_arb_out_request_vector[j];
275 act_out_request_vector[j * number_resources + i] = act_arb_out_request_vector[j];
276 }
277 }
278 }
279 else
280 {
281
282 }
283
284 // Update output probabilities
285 getGenProperties()->set("P(Grant)", LibUtil::vectorToString(P_out_request_vector));
286 getGenProperties()->set("Act(Grant)", LibUtil::vectorToString(act_out_request_vector));
287
288 return;
289 }
290 } // namespace DSENT
291