| /* Copyright (c) 2012 Massachusetts Institute of Technology |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to deal |
| * in the Software without restriction, including without limitation the rights |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| * THE SOFTWARE. |
| */ |
| |
| #include "model/electrical/SeparableAllocator.h" |
| |
| #include "model/ModelGen.h" |
| #include "model/timing_graph/ElectricalNet.h" |
| |
| namespace DSENT |
| { |
| SeparableAllocator::SeparableAllocator(const String& instance_name_, const TechModel* tech_model_) |
| : ElectricalModel(instance_name_, tech_model_) |
| { |
| initParameters(); |
| initProperties(); |
| } |
| |
| SeparableAllocator::~SeparableAllocator() |
| {} |
| |
| void SeparableAllocator::initParameters() |
| { |
| addParameterName("NumberRequesters"); |
| addParameterName("NumberResources"); |
| addParameterName("IsRequesterFirst", true); |
| addParameterName("Stage1->ArbiterModel"); |
| addParameterName("Stage2->ArbiterModel"); |
| return; |
| } |
| |
| void SeparableAllocator::initProperties() |
| { |
| addPropertyName("P(Request)"); |
| addPropertyName("Act(Request)"); |
| addPropertyName("P(CK)"); |
| addPropertyName("Act(CK)"); |
| return; |
| } |
| |
| SeparableAllocator* SeparableAllocator::clone() const |
| { |
| // TODO |
| return NULL; |
| } |
| |
| void SeparableAllocator::constructModel() |
| { |
| // Get parameters |
| unsigned int number_requesters = getParameter("NumberRequesters").toUInt(); |
| unsigned int number_resources = getParameter("NumberResources").toUInt(); |
| bool is_requester_first = getParameter("IsRequesterFirst").toBool(); |
| const String& stage1_arbiter_model = getParameter("Stage1->ArbiterModel"); |
| const String& stage2_arbiter_model = getParameter("Stage2->ArbiterModel"); |
| |
| ASSERT(number_requesters > 0, "[Error] " + getInstanceName() + |
| " -> Number of requesters must be > 0!"); |
| ASSERT(number_resources > 0, "[Error] " + getInstanceName() + |
| " -> Number of resources must be > 0!"); |
| |
| // Create area, power, and event results |
| createElectricalResults(); |
| addEventResult(new Result("Allocate")); |
| |
| // Create ports |
| createInputPort("CK"); |
| for(unsigned int i = 0; i < number_requesters; ++i) |
| { |
| createInputPort("Request" + (String)i, makeNetIndex(0, number_resources-1)); |
| createOutputPort("Grant" + (String)i, makeNetIndex(0, number_resources-1)); |
| } |
| |
| // If is_requester_first is set, requests from the same requester will be arbitrate |
| // on stage 1 |
| if(is_requester_first) |
| { |
| // Init stage 1 arbiters |
| for(unsigned int i = 0; i < number_requesters; ++i) |
| { |
| ElectricalModel* arb = (ElectricalModel*)ModelGen::createModel(stage1_arbiter_model, "Stage1Arb" + (String)i, getTechModel()); |
| arb->setParameter("NumberRequests", number_resources); |
| arb->construct(); |
| |
| addSubInstances(arb, 1.0); |
| addElectricalSubResults(arb, 1.0); |
| |
| getEventResult("Allocate")->addSubResult(arb->getEventResult("Arbitrate"), arb->getInstanceName(), 1.0); |
| |
| createNet("Stage1Arb_In" + (String)i, makeNetIndex(0, number_resources-1)); |
| createNet("Stage1Arb_Out" + (String)i, makeNetIndex(0, number_resources-1)); |
| |
| portConnect(arb, "CK", "CK"); |
| assign("Stage1Arb_In" + (String)i, "Request" + (String)i); |
| for(unsigned int j = 0; j < number_resources; ++j) |
| { |
| portConnect(arb, "Request" + (String)j, "Stage1Arb_In" + (String)i, makeNetIndex(j)); |
| portConnect(arb, "Grant" + (String)j, "Stage1Arb_Out" + (String)i, makeNetIndex(j)); |
| } |
| } |
| |
| // Init stage 2 arbiters |
| for(unsigned int i = 0; i < number_resources; ++i) |
| { |
| ElectricalModel* arb = (ElectricalModel*)ModelGen::createModel(stage2_arbiter_model, "Stage2Arb" + (String)i, getTechModel()); |
| arb->setParameter("NumberRequests", number_requesters); |
| arb->construct(); |
| |
| addSubInstances(arb, 1.0); |
| addElectricalSubResults(arb, 1.0); |
| |
| getEventResult("Allocate")->addSubResult(arb->getEventResult("Arbitrate"), arb->getInstanceName(), 1.0); |
| |
| createNet("Stage2Arb_In" + (String)i, makeNetIndex(0, number_requesters-1)); |
| createNet("Stage2Arb_Out" + (String)i, makeNetIndex(0, number_requesters-1)); |
| |
| portConnect(arb, "CK", "CK"); |
| for(unsigned int j = 0; j < number_requesters; ++j) |
| { |
| assign("Stage2Arb_In" + (String)i, makeNetIndex(j), "Stage1Arb_Out" + (String)j, makeNetIndex(i)); |
| portConnect(arb, "Request" + (String)j, "Stage2Arb_In" + (String)i, makeNetIndex(j)); |
| portConnect(arb, "Grant" + (String)j, "Stage2Arb_Out" + (String)i, makeNetIndex(j)); |
| assign("Grant" + (String)j, makeNetIndex(i), "Stage2Arb_Out" + (String)i, makeNetIndex(j)); |
| } |
| } |
| } |
| else |
| { |
| // Init stage 1 arbiters |
| for(unsigned int i = 0; i < number_resources; ++i) |
| { |
| ElectricalModel* arb = (ElectricalModel*)ModelGen::createModel(stage1_arbiter_model, "Stage1Arb" + (String)i, getTechModel()); |
| arb->setParameter("NumberRequests", number_requesters); |
| arb->construct(); |
| |
| addSubInstances(arb, 1.0); |
| addElectricalSubResults(arb, 1.0); |
| |
| getEventResult("Allocate")->addSubResult(arb->getEventResult("Arbitrate"), arb->getInstanceName(), 1.0); |
| |
| createNet("Stage1Arb_In" + (String)i, makeNetIndex(0, number_requesters-1)); |
| createNet("Stage1Arb_Out" + (String)i, makeNetIndex(0, number_requesters-1)); |
| |
| portConnect(arb, "CK", "CK"); |
| for(unsigned int j = 0; j < number_requesters; ++j) |
| { |
| assign("Stage1Arb_In" + (String)i, makeNetIndex(j), "Request" + (String)j, makeNetIndex(i)); |
| portConnect(arb, "Request" + (String)j, "Stage1Arb_In" + (String)i, makeNetIndex(j)); |
| portConnect(arb, "Grant" + (String)j, "Stage1Arb_Out" + (String)i, makeNetIndex(j)); |
| } |
| } |
| |
| // Init stage 2 arbiters |
| for(unsigned int i = 0; i < number_requesters; ++i) |
| { |
| ElectricalModel* arb = (ElectricalModel*)ModelGen::createModel(stage2_arbiter_model, "Stage2Arb" + (String)i, getTechModel()); |
| arb->setParameter("NumberRequests", number_requesters); |
| arb->construct(); |
| |
| addSubInstances(arb, 1.0); |
| addElectricalSubResults(arb, 1.0); |
| |
| getEventResult("Allocate")->addSubResult(arb->getEventResult("Arbitrate"), arb->getInstanceName(), 1.0); |
| |
| createNet("Stage2Arb_In" + (String)i, makeNetIndex(0, number_resources-1)); |
| createNet("Stage2Arb_Out" + (String)i, makeNetIndex(0, number_resources-1)); |
| |
| portConnect(arb, "CK", "CK"); |
| for(unsigned int j = 0; j < number_resources; ++j) |
| { |
| assign("Stage2Arb_In" + (String)i, makeNetIndex(j), "Stage1Arb_Out" + (String)j, makeNetIndex(i)); |
| portConnect(arb, "Request" + (String)j, "Stage2Arb_In", makeNetIndex(j)); |
| portConnect(arb, "Grant" + (String)j, "Stage2Arb_Out", makeNetIndex(j)); |
| } |
| assign("Grant" + (String)i, "Stage2Arb_Out" + (String)i); |
| } |
| } |
| return; |
| } |
| |
| void SeparableAllocator::updateModel() |
| { |
| // Get parameters |
| unsigned int number_requesters = getParameter("NumberRequesters").toUInt(); |
| unsigned int number_resources = getParameter("NumberResources").toUInt(); |
| bool is_requester_first = getParameter("IsRequesterFirst").toBool(); |
| |
| // Get probabilities from inputs |
| const String& P_request = getProperty("P(Request)"); |
| const String& act_request = getProperty("Act(Request)"); |
| const String& P_CK = getProperty("P(CK)"); |
| const String& act_CK = getProperty("Act(CK)"); |
| |
| const vector<double>& P_request_vector = LibUtil::castStringVector<double>(P_request.split("[,]")); |
| const vector<double>& act_request_vector = LibUtil::castStringVector<double>(act_request.split("[,]")); |
| |
| ASSERT(P_request_vector.size() == (number_requesters * number_resources), "[Error] " + getInstanceName() + |
| " -> Expecting " + (String)(number_requesters * number_resources) + |
| " request probabilities, but got " + P_request); |
| ASSERT(act_request_vector.size() == (number_requesters * number_resources), "[Error] " + getInstanceName() + |
| " -> Expecting " + (String)(number_requesters * number_resources) + |
| " request actvities multiplier, but got " + act_request); |
| |
| vector<double> P_int_request_vector(number_requesters * number_resources, 0.0); |
| vector<double> act_int_request_vector(number_requesters * number_resources, 0.0); |
| vector<double> P_out_request_vector(number_requesters * number_resources, 0.0); |
| vector<double> act_out_request_vector(number_requesters * number_resources, 0.0); |
| if(is_requester_first) |
| { |
| // Update stage1 arbiter |
| for(unsigned int i = 0; i < number_requesters; ++i) |
| { |
| vector<double> P_arb_request_vector(number_resources, 0.0); |
| vector<double> act_arb_request_vector(number_resources, 0.0); |
| for(unsigned int j = 0; j < number_resources; ++j) |
| { |
| P_arb_request_vector[j] = P_request_vector[i * number_resources + j]; |
| act_arb_request_vector[j] = act_request_vector[i * number_resources + j]; |
| } |
| |
| Model* arb = getSubInstance("Stage1Arb" + (String)i); |
| arb->setProperty("P(Request)", LibUtil::vectorToString(P_arb_request_vector)); |
| arb->setProperty("Act(Request)", LibUtil::vectorToString(act_arb_request_vector)); |
| arb->setProperty("P(CK)", P_CK); |
| arb->setProperty("Act(CK)", act_CK); |
| arb->update(); |
| |
| const vector<double>& P_arb_out_request_vector = LibUtil::castStringVector<double>(arb->getGenProperties()->get("P(Grant)").split("[,]")); |
| const vector<double>& act_arb_out_request_vector = LibUtil::castStringVector<double>(arb->getGenProperties()->get("Act(Grant)").split("[,]")); |
| for(unsigned int j = 0; j < number_resources; ++j) |
| { |
| P_int_request_vector[i * number_resources + j] = P_arb_out_request_vector[j]; |
| act_int_request_vector[i * number_resources + j] = act_arb_out_request_vector[j]; |
| } |
| } |
| // Update stage2 arbiter |
| for(unsigned int i = 0; i < number_resources; ++i) |
| { |
| vector<double> P_arb_request_vector(number_requesters, 0.0); |
| vector<double> act_arb_request_vector(number_requesters, 0.0); |
| for(unsigned int j = 0; j < number_requesters; ++j) |
| { |
| P_arb_request_vector[j] = P_int_request_vector[j * number_resources + i]; |
| act_arb_request_vector[j] = act_int_request_vector[j * number_resources + i]; |
| } |
| |
| Model* arb = getSubInstance("Stage2Arb" + (String)i); |
| arb->setProperty("P(Request)", LibUtil::vectorToString(P_arb_request_vector)); |
| arb->setProperty("Act(Request)", LibUtil::vectorToString(act_arb_request_vector)); |
| arb->setProperty("P(CK)", P_CK); |
| arb->setProperty("Act(CK)", act_CK); |
| arb->update(); |
| |
| const vector<double>& P_arb_out_request_vector = LibUtil::castStringVector<double>(arb->getGenProperties()->get("P(Grant)").split("[,]")); |
| const vector<double>& act_arb_out_request_vector = LibUtil::castStringVector<double>(arb->getGenProperties()->get("Act(Grant)").split("[,]")); |
| for(unsigned int j = 0; j < number_requesters; ++j) |
| { |
| P_out_request_vector[j * number_resources + i] = P_arb_out_request_vector[j]; |
| act_out_request_vector[j * number_resources + i] = act_arb_out_request_vector[j]; |
| } |
| } |
| } |
| else |
| { |
| |
| } |
| |
| // Update output probabilities |
| getGenProperties()->set("P(Grant)", LibUtil::vectorToString(P_out_request_vector)); |
| getGenProperties()->set("Act(Grant)", LibUtil::vectorToString(act_out_request_vector)); |
| |
| return; |
| } |
| } // namespace DSENT |
| |