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 27namespace 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 292