From e8ed7b1d1b5bef31e9874f679a5797c2e00d06f1 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Sat, 11 Oct 2014 15:02:23 -0500 Subject: ext: add the source code for DSENT This patch adds a tool called DSENT to the ext/ directory. DSENT is a tool that models power and area for on-chip networks. The next patch adds a script for using the tool. --- ext/dsent/model/electrical/SeparableAllocator.cc | 270 +++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 ext/dsent/model/electrical/SeparableAllocator.cc (limited to 'ext/dsent/model/electrical/SeparableAllocator.cc') diff --git a/ext/dsent/model/electrical/SeparableAllocator.cc b/ext/dsent/model/electrical/SeparableAllocator.cc new file mode 100644 index 000000000..e0965cbe9 --- /dev/null +++ b/ext/dsent/model/electrical/SeparableAllocator.cc @@ -0,0 +1,270 @@ +#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 + -- cgit v1.2.3