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/router/RouterSwitchAllocator.h" 23 24#include "model/PortInfo.h" 25#include "model/EventInfo.h" 26#include "model/TransitionInfo.h" 27#include "model/ModelGen.h" 28#include "model/std_cells/StdCell.h" 29#include "model/std_cells/StdCellLib.h" 30 31namespace DSENT 32{ 33 RouterSwitchAllocator::RouterSwitchAllocator(const String& instance_name_, const TechModel* tech_model_) 34 : ElectricalModel(instance_name_, tech_model_) 35 { 36 initParameters(); 37 initProperties(); 38 } 39 40 RouterSwitchAllocator::~RouterSwitchAllocator() 41 {} 42 43 void RouterSwitchAllocator::initParameters() 44 { 45 addParameterName("NumberInputPorts"); 46 addParameterName("NumberOutputPorts"); 47 addParameterName("TotalNumberVirtualChannels"); 48 addParameterName("ArbiterModel"); 49 return; 50 } 51 52 void RouterSwitchAllocator::initProperties() 53 {} 54 55 RouterSwitchAllocator* RouterSwitchAllocator::clone() const 56 { 57 // TODO 58 return NULL; 59 } 60 61 void RouterSwitchAllocator::constructModel() 62 { 63 // Get parameters 64 unsigned int number_input_ports = getParameter("NumberInputPorts").toUInt(); 65 unsigned int number_output_ports = getParameter("NumberOutputPorts").toUInt(); 66 unsigned int total_number_vcs = getParameter("TotalNumberVirtualChannels").toUInt(); 67 const String& arb_model = getParameter("ArbiterModel"); 68 69 ASSERT(number_input_ports > 0, "[Error] " + getInstanceName() + 70 " -> Number of input ports must be > 0!"); 71 ASSERT(number_output_ports > 0, "[Error] " + getInstanceName() + 72 " -> Number of output ports must be > 0!"); 73 ASSERT(total_number_vcs > 0, "[Error] " + getInstanceName() + 74 " -> Total number of virtual channels must be > 0!"); 75 76 unsigned int stage1_number_requests = total_number_vcs; 77 unsigned int number_stage1_arbiters = number_input_ports; 78 unsigned int stage2_number_requests = number_input_ports; 79 unsigned int number_stage2_arbiters = number_output_ports; 80 81 getGenProperties()->set("NumberStage1Arbiters", number_stage1_arbiters); 82 getGenProperties()->set("Stage1->NumberRequests", stage1_number_requests); 83 getGenProperties()->set("NumberStage2Arbiters", number_stage2_arbiters); 84 getGenProperties()->set("Stage2->NumberRequests", stage2_number_requests); 85 86 // Create ports 87 createInputPort("CK"); 88 for(unsigned int i = 0; i < number_stage1_arbiters; ++i) 89 { 90 for(unsigned int j = 0; j < stage1_number_requests; ++j) 91 { 92 createInputPort(String::format("Stage1Arb%d->Request%d", i, j)); 93 createInputPort(String::format("Stage1Arb%d->Grant%d", i, j)); 94 } 95 } 96 for(unsigned int i = 0; i < number_stage2_arbiters; ++i) 97 { 98 for(unsigned int j = 0; j < stage2_number_requests; ++j) 99 { 100 createInputPort(String::format("Stage2Arb%d->Request%d", i, j)); 101 createInputPort(String::format("Stage2Arb%d->Grant%d", i, j)); 102 } 103 } 104 105 // Create area, power, and event results 106 createElectricalResults(); 107 getEventInfo("Idle")->setStaticTransitionInfos(); 108 getEventInfo("Idle")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 109 110 createElectricalEventResult("ArbitrateStage1"); 111 getEventInfo("ArbitrateStage1")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 112 createElectricalEventResult("ArbitrateStage2"); 113 getEventInfo("ArbitrateStage2")->setTransitionInfo("CK", TransitionInfo(0.0, 1.0, 0.0)); 114 115 // Init Stage1 arbiter 116 vector<String> stage1_arb_dff_names(stage1_number_requests, ""); 117 vector<StdCell*> stage1_arb_dffs(stage1_number_requests, NULL); 118 for(unsigned int i = 0; i < stage1_number_requests; ++i) 119 { 120 stage1_arb_dff_names[i] = "Stage1ArbDFF" + (String)i; 121 stage1_arb_dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", stage1_arb_dff_names[i]); 122 stage1_arb_dffs[i]->construct(); 123 } 124 const String& stage1_arb_name = "Stage1Arb"; 125 ElectricalModel* stage1_arb = (ElectricalModel*)ModelGen::createModel(arb_model, stage1_arb_name, getTechModel()); 126 stage1_arb->setParameter("NumberRequests", stage1_number_requests); 127 stage1_arb->construct(); 128 129 // Init stage2 arbiter 130 vector<String> stage2_arb_dff_names(stage2_number_requests, ""); 131 vector<StdCell*> stage2_arb_dffs(stage2_number_requests, NULL); 132 for(unsigned int i = 0; i < stage2_number_requests; ++i) 133 { 134 stage2_arb_dff_names[i] = "Stage2ArbDFF" + (String)i; 135 stage2_arb_dffs[i] = getTechModel()->getStdCellLib()->createStdCell("DFFQ", stage2_arb_dff_names[i]); 136 stage2_arb_dffs[i]->construct(); 137 } 138 const String& stage2_arb_name = "Stage2Arb"; 139 ElectricalModel* stage2_arb = (ElectricalModel*)ModelGen::createModel(arb_model, stage2_arb_name, getTechModel()); 140 stage2_arb->setParameter("NumberRequests", stage2_number_requests); 141 stage2_arb->construct(); 142 143 // Connect ports 144 for(unsigned int i = 0; i < stage1_number_requests; ++i) 145 { 146 const String& dff_in_name = "Stage1Arb_DFF_In" + (String)i; 147 const String& req_name = "Stage1Arb->Request" + (String)i; 148 const String& grant_name = "Stage1Arb->Grant" + (String)i; 149 createNet(dff_in_name); 150 createNet(req_name); 151 createNet(grant_name); 152 portConnect(stage1_arb_dffs[i], "D", dff_in_name); 153 portConnect(stage1_arb_dffs[i], "CK", "CK"); 154 portConnect(stage1_arb_dffs[i], "Q", req_name); 155 portConnect(stage1_arb, "Request" + (String)i, req_name); 156 portConnect(stage1_arb, "Grant" + (String)i, grant_name); 157 for(unsigned int j = 0; j < number_stage1_arbiters; ++j) 158 { 159 assignVirtualFanin(dff_in_name, String::format("Stage1Arb%d->Request%d", j, i)); 160 assignVirtualFanout(String::format("Stage1Arb%d->Grant%d", j, i), grant_name); 161 } 162 } 163 for(unsigned int i = 0; i < stage2_number_requests; ++i) 164 { 165 const String& dff_in_name = "Stage2Arb_DFF_In" + (String)i; 166 const String& req_name = "Stage2Arb->Request" + (String)i; 167 const String& grant_name = "Stage2Arb->Grant" + (String)i; 168 createNet(dff_in_name); 169 createNet(req_name); 170 createNet(grant_name); 171 portConnect(stage2_arb_dffs[i], "D", dff_in_name); 172 portConnect(stage2_arb_dffs[i], "CK", "CK"); 173 portConnect(stage2_arb_dffs[i], "Q", req_name); 174 portConnect(stage2_arb, "Request" + (String)i, req_name); 175 portConnect(stage2_arb, "Grant" + (String)i, grant_name); 176 for(unsigned int j = 0; j < number_stage2_arbiters; ++j) 177 { 178 assignVirtualFanin(dff_in_name, String::format("Stage2Arb%d->Request%d", j, i)); 179 assignVirtualFanout(String::format("Stage2Arb%d->Grant%d", j, i), grant_name); 180 } 181 } 182 183 // Add sub components 184 for(unsigned int i = 0; i < stage1_number_requests; ++i) 185 { 186 addSubInstances(stage1_arb_dffs[i], 1.0); 187 addElectricalSubResults(stage1_arb_dffs[i], 1.0); 188 } 189 addSubInstances(stage1_arb, number_stage1_arbiters); 190 addElectricalSubResults(stage1_arb, number_stage1_arbiters); 191 for(unsigned int i = 0; i < stage2_number_requests; ++i) 192 { 193 addSubInstances(stage2_arb_dffs[i], 1.0); 194 addElectricalSubResults(stage2_arb_dffs[i], 1.0); 195 } 196 addSubInstances(stage2_arb, number_stage2_arbiters); 197 addElectricalSubResults(stage2_arb, number_stage2_arbiters); 198 199 // Update stage1 arb arbitrate 200 getEventResult("ArbitrateStage1")->addSubResult(stage1_arb->getEventResult("Arbitrate"), stage1_arb_name, 1.0); 201 202 // Update stage2 arb arbitrate 203 getEventResult("ArbitrateStage2")->addSubResult(stage2_arb->getEventResult("Arbitrate"), stage2_arb_name, 1.0); 204 return; 205 } 206 207 void RouterSwitchAllocator::propagateTransitionInfo() 208 { 209 ElectricalModel* stage1_arb = (ElectricalModel*)getSubInstance("Stage1Arb"); 210 stage1_arb->applyTransitionInfo("Arbitrate"); 211 stage1_arb->use(); 212 213 ElectricalModel* stage2_arb = (ElectricalModel*)getSubInstance("Stage2Arb"); 214 stage2_arb->applyTransitionInfo("Arbitrate"); 215 stage2_arb->use(); 216 217 return; 218 } 219} // namespace DSENT 220 221