#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& P_request_vector = LibUtil::castStringVector(P_request.split("[,]")); const vector& act_request_vector = LibUtil::castStringVector(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 P_int_request_vector(number_requesters * number_resources, 0.0); vector act_int_request_vector(number_requesters * number_resources, 0.0); vector P_out_request_vector(number_requesters * number_resources, 0.0); vector 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 P_arb_request_vector(number_resources, 0.0); vector 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& P_arb_out_request_vector = LibUtil::castStringVector(arb->getGenProperties()->get("P(Grant)").split("[,]")); const vector& act_arb_out_request_vector = LibUtil::castStringVector(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 P_arb_request_vector(number_requesters, 0.0); vector 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& P_arb_out_request_vector = LibUtil::castStringVector(arb->getGenProperties()->get("P(Grant)").split("[,]")); const vector& act_arb_out_request_vector = LibUtil::castStringVector(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