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/SeparableAllocator.h"
24 #include "model/ModelGen.h"
25 #include "model/timing_graph/ElectricalNet.h"
29 SeparableAllocator::SeparableAllocator(const String
& instance_name_
, const TechModel
* tech_model_
)
30 : ElectricalModel(instance_name_
, tech_model_
)
36 SeparableAllocator::~SeparableAllocator()
39 void SeparableAllocator::initParameters()
41 addParameterName("NumberRequesters");
42 addParameterName("NumberResources");
43 addParameterName("IsRequesterFirst", true);
44 addParameterName("Stage1->ArbiterModel");
45 addParameterName("Stage2->ArbiterModel");
49 void SeparableAllocator::initProperties()
51 addPropertyName("P(Request)");
52 addPropertyName("Act(Request)");
53 addPropertyName("P(CK)");
54 addPropertyName("Act(CK)");
58 SeparableAllocator
* SeparableAllocator::clone() const
64 void SeparableAllocator::constructModel()
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");
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!");
78 // Create area, power, and event results
79 createElectricalResults();
80 addEventResult(new Result("Allocate"));
83 createInputPort("CK");
84 for(unsigned int i
= 0; i
< number_requesters
; ++i
)
86 createInputPort("Request" + (String
)i
, makeNetIndex(0, number_resources
-1));
87 createOutputPort("Grant" + (String
)i
, makeNetIndex(0, number_resources
-1));
90 // If is_requester_first is set, requests from the same requester will be arbitrate
92 if(is_requester_first
)
94 // Init stage 1 arbiters
95 for(unsigned int i
= 0; i
< number_requesters
; ++i
)
97 ElectricalModel
* arb
= (ElectricalModel
*)ModelGen::createModel(stage1_arbiter_model
, "Stage1Arb" + (String
)i
, getTechModel());
98 arb
->setParameter("NumberRequests", number_resources
);
101 addSubInstances(arb
, 1.0);
102 addElectricalSubResults(arb
, 1.0);
104 getEventResult("Allocate")->addSubResult(arb
->getEventResult("Arbitrate"), arb
->getInstanceName(), 1.0);
106 createNet("Stage1Arb_In" + (String
)i
, makeNetIndex(0, number_resources
-1));
107 createNet("Stage1Arb_Out" + (String
)i
, makeNetIndex(0, number_resources
-1));
109 portConnect(arb
, "CK", "CK");
110 assign("Stage1Arb_In" + (String
)i
, "Request" + (String
)i
);
111 for(unsigned int j
= 0; j
< number_resources
; ++j
)
113 portConnect(arb
, "Request" + (String
)j
, "Stage1Arb_In" + (String
)i
, makeNetIndex(j
));
114 portConnect(arb
, "Grant" + (String
)j
, "Stage1Arb_Out" + (String
)i
, makeNetIndex(j
));
118 // Init stage 2 arbiters
119 for(unsigned int i
= 0; i
< number_resources
; ++i
)
121 ElectricalModel
* arb
= (ElectricalModel
*)ModelGen::createModel(stage2_arbiter_model
, "Stage2Arb" + (String
)i
, getTechModel());
122 arb
->setParameter("NumberRequests", number_requesters
);
125 addSubInstances(arb
, 1.0);
126 addElectricalSubResults(arb
, 1.0);
128 getEventResult("Allocate")->addSubResult(arb
->getEventResult("Arbitrate"), arb
->getInstanceName(), 1.0);
130 createNet("Stage2Arb_In" + (String
)i
, makeNetIndex(0, number_requesters
-1));
131 createNet("Stage2Arb_Out" + (String
)i
, makeNetIndex(0, number_requesters
-1));
133 portConnect(arb
, "CK", "CK");
134 for(unsigned int j
= 0; j
< number_requesters
; ++j
)
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
));
145 // Init stage 1 arbiters
146 for(unsigned int i
= 0; i
< number_resources
; ++i
)
148 ElectricalModel
* arb
= (ElectricalModel
*)ModelGen::createModel(stage1_arbiter_model
, "Stage1Arb" + (String
)i
, getTechModel());
149 arb
->setParameter("NumberRequests", number_requesters
);
152 addSubInstances(arb
, 1.0);
153 addElectricalSubResults(arb
, 1.0);
155 getEventResult("Allocate")->addSubResult(arb
->getEventResult("Arbitrate"), arb
->getInstanceName(), 1.0);
157 createNet("Stage1Arb_In" + (String
)i
, makeNetIndex(0, number_requesters
-1));
158 createNet("Stage1Arb_Out" + (String
)i
, makeNetIndex(0, number_requesters
-1));
160 portConnect(arb
, "CK", "CK");
161 for(unsigned int j
= 0; j
< number_requesters
; ++j
)
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
));
169 // Init stage 2 arbiters
170 for(unsigned int i
= 0; i
< number_requesters
; ++i
)
172 ElectricalModel
* arb
= (ElectricalModel
*)ModelGen::createModel(stage2_arbiter_model
, "Stage2Arb" + (String
)i
, getTechModel());
173 arb
->setParameter("NumberRequests", number_requesters
);
176 addSubInstances(arb
, 1.0);
177 addElectricalSubResults(arb
, 1.0);
179 getEventResult("Allocate")->addSubResult(arb
->getEventResult("Arbitrate"), arb
->getInstanceName(), 1.0);
181 createNet("Stage2Arb_In" + (String
)i
, makeNetIndex(0, number_resources
-1));
182 createNet("Stage2Arb_Out" + (String
)i
, makeNetIndex(0, number_resources
-1));
184 portConnect(arb
, "CK", "CK");
185 for(unsigned int j
= 0; j
< number_resources
; ++j
)
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
));
191 assign("Grant" + (String
)i
, "Stage2Arb_Out" + (String
)i
);
197 void SeparableAllocator::updateModel()
200 unsigned int number_requesters
= getParameter("NumberRequesters").toUInt();
201 unsigned int number_resources
= getParameter("NumberResources").toUInt();
202 bool is_requester_first
= getParameter("IsRequesterFirst").toBool();
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)");
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("[,]"));
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
);
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
)
226 // Update stage1 arbiter
227 for(unsigned int i
= 0; i
< number_requesters
; ++i
)
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
)
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
];
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
);
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
)
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
];
252 // Update stage2 arbiter
253 for(unsigned int i
= 0; i
< number_resources
; ++i
)
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
)
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
];
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
);
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
)
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
];
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
));