OpenASIP 2.2
Loading...
Searching...
No Matches
SimpleICOptimizer.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file SimpleICOptimizer.cc
26 *
27 * Explorer plugin that optimizes the interconnection network by
28 * removing extra sockets and not used connections.
29 *
30 * @author Jari Mäntyneva 2007 (jari.mantyneva-no.spam-tut.fi)
31 * @author Esa Määttä 2008 (esa.maatta-no.spam-tut.fi)
32 * @note rating: red
33 */
34
35#include <vector>
36#include <string>
37#include <set>
38
40#include "DSDBManager.hh"
41#include "Machine.hh"
42#include "TestApplication.hh"
43#include "Program.hh"
44#include "Instruction.hh"
45#include "Move.hh"
46#include "Port.hh"
47#include "FUPort.hh"
48#include "Socket.hh"
49#include "Terminal.hh"
50#include "Terminal.hh"
51#include "HDBRegistry.hh"
53#include "ControlUnit.hh"
54#include "HWOperation.hh"
55#include "StringTools.hh"
56#include "Segment.hh"
57#include "CostEstimates.hh"
58#include "Application.hh"
59#include "Exception.hh"
60#include "Procedure.hh"
61
62#include "LLVMBackend.hh"
64
65#include "MinimalOpSetCheck.hh"
67
68
69using namespace TTAProgram;
70using namespace TTAMachine;
71using namespace HDB;
72using std::endl;
73
74/**
75 * Explorer plugin that optimizes the interconnection network of the given
76 * configuration by removing the connections that are not used in the
77 * parallel program.
78 */
80 PLUGIN_DESCRIPTION("Optimizes the IC of the given configuration");
81
83 tpef_(""),
85 evaluateResult_(true),
87
88 // compulsory parameters
89 // none
90
91 // parameters that have a default value
92 addParameter(tpefPN_, STRING, false, "");
99 }
100
101 virtual bool requiresStartingPointArchitecture() const { return true; }
102 virtual bool producesArchitecture() const { return true; }
103 virtual bool requiresHDB() const { return false; }
104 virtual bool requiresSimulationData() const { return false; }
105 virtual bool requiresApplication() const { return false; }
106
107 /**
108 * Optimizes the IC of the given configuration by removing not used
109 * connections.
110 *
111 * First removes connections and then adds them by looking
112 * all application domains programs instructions and their moves.
113 * Needs the start point configuration to get the architecture
114 * which connections are optimized.
115 *
116 * Supported parameters:
117 * - tpef, name of the scheduled program file, no default value.
118 * - add_only, if parameter is set the connections of the given
119 * configuration won't be emptied, just added new ones, not set as
120 * default.
121 *
122 * @param startPointConfigurationID Configuration to optimize.
123 */
124 virtual std::vector<RowID>
125 explore(const RowID& startPointConfigurationID, const unsigned int&) {
126
127 std::vector<RowID> result;
128
130
131 try {
132 DSDBManager& dsdb = db();
134 dsdb.configuration(startPointConfigurationID);
135
136 // loads starting configuration
137 Machine* origMach = NULL;
138 Machine* mach = NULL;
139 try {
140 origMach = dsdb.architecture(conf.architectureID);
141 mach = dsdb.architecture(conf.architectureID);
142 } catch (const Exception& e) {
143 std::ostringstream msg(std::ostringstream::out);
144 msg << e.errorMessage() << std::endl;
145 verboseLog(msg.str());
146 return result;
147 }
148
149 if (!addOnly_) {
151 }
152
153 // if no scheduled programs given
154 Program* program = NULL;
155 if (tpef_ == "") {
156 //SchedulerFrontend scheduler;
157 try {
158 std::set<RowID> appIDs = dsdb.applicationIDs();
159 std::set<RowID>::const_iterator iter = appIDs.begin();
160 if (iter == appIDs.end()) {
161 // no applications, nothing can be done
162 return result;
163 }
164 for (; iter != appIDs.end(); iter++) {
165 TestApplication testApp(dsdb.applicationPath(*iter));
166
168 testApp.applicationPath(), *origMach);
169 if (program == NULL) {
170 std::string msg = "SimpleICOptimizer: Schedule "
171 "failed for program: " +
172 testApp.applicationPath();
173 verboseLogC(msg, 1)
174 return result;
175 }
176
177 addConnections(*mach, *program);
178 }
179 } catch (const Exception& e) {
180 std::ostringstream msg(std::ostringstream::out);
181 msg << e.errorMessageStack() << std::endl;
182 verboseLog(msg.str());
183 delete mach;
184 mach = NULL;
185 return result;
186 }
187 } else {
188 try {
189 program = Program::loadFromTPEF(tpef_, *origMach);
190
191 addConnections(*mach, *program);
192 } catch (const Exception& e) {
193 std::ostringstream msg(std::ostringstream::out);
194 msg << "Error while loading the program in "
195 << "SimpleICOptimizer:" << endl
196 << e.errorMessage() << endl;
197 verboseLog(msg.str());
198 return result;
199 }
200 }
201
203 try {
204 tempConf.architectureID = dsdb.addArchitecture(*mach);
205 tempConf.hasImplementation = false;
206 } catch (const RelationalDBException& e) {
207 std::ostringstream msg(std::ostringstream::out);
208 msg << "Error while adding ADF to the dsdb. "
209 << "ADF probably too big." << endl;
210 verboseLog(msg.str());
211 return result;
212 }
213
214 // add config to database to pass it to
215 // RemoveUnconnectedComponents plugin
216 RowID tempConfID = dsdb.addConfiguration(tempConf);
217
218 // remove unconnected components with RemoveUnconnectedComponents
219 // plugin
220 DesignSpaceExplorerPlugin* removeUnconnected =
222 "RemoveUnconnectedComponents", &db());
223
224 // parameters for RemoveUnconnectedComponents plugin
225 removeUnconnected->giveParameter("allow_remove", "true");
226
227 std::vector<RowID> cleanedTempConfIDs =
228 removeUnconnected->explore(tempConfID);
229 delete removeUnconnected;
230 removeUnconnected = NULL;
231 if (cleanedTempConfIDs.size() < 1) {
232 std::string errorMsg = "SimpleICOptimizer plugin: "
233 "RemoveUnconnectedComponents plugin failed to produce"
234 "result.";
235 verboseLogC(errorMsg, 2)
236 return result;
237 }
238
240 dsdb.configuration(cleanedTempConfIDs.at(0));
241
242 // if original machine had enough int registers, check and
243 // possibly try to fix the new machine
244 RegisterQuantityCheck RFCheck;
245 if (RFCheck.checkIntRegs(*origMach)) {
246 Machine* cleanedMach =
247 dsdb.architecture(newConf.architectureID);
248 if (fixIntRegisters(*cleanedMach)) {
249 // replace newConf machine with the fixed one
250 newConf.architectureID =
251 dsdb.addArchitecture(*cleanedMach);
252 }
253 }
254
255 // create implementation for newConf if orginal config had one
256 if (conf.hasImplementation && !newConf.hasImplementation) {
257 createImplementation(newConf, newConf);
258 } else {
259 newConf.hasImplementation = false;
260 }
261
262 // evaluate and save new config id as result
263 CostEstimates estimates;
264 if (evaluateResult_) {
265 // evaluate the new config
266 bool estimate = newConf.hasImplementation;
267 if (evaluate(newConf, estimates, estimate)) {
268 RowID confID = dsdb.addConfiguration(newConf);
269 result.push_back(confID);
270 } else {
271 // cannot evaluate
272 std::ostringstream msg(std::ostringstream::out);
273 msg << "SimpleICOptimizer plugin couldn't evaluate "
274 << "generated config - nothing done." << endl;
275 verboseLog(msg.str());
276 return result;
277 }
278 } else {
279 RowID confID = dsdb.addConfiguration(newConf);
280 result.push_back(confID);
281 }
282
283 } catch (const Exception& e) {
284 std::ostringstream msg(std::ostringstream::out);
285 msg << "Error while using SimpleICOptimizer:" << endl
286 << e.errorMessage() << endl;
287 verboseLog(msg.str());
288 return result;
289 }
290 return result;
291 }
292
293private:
294 // parameter name variables
295 static const std::string tpefPN_;
296 static const std::string tpefDefaultPN_;
297 static const std::string addOnlyPN_;
298 static const std::string evaluatePN_;
299 static const std::string preserveMinOpsPN_;
300
301 /// name of the tpef file
302 std::string tpef_;
303 /// can we remove connections
305 /// evaluate the result(s)
307 /// respect minimal opset when removing connections
309
310
311 /**
312 * Reads the parameters given to the plugin.
313 */
320
321
322 /**
323 * Removes all socket-bus connection from the given machine.
324 *
325 * @param mach Machine which connections are removed.
326 */
328 Machine::SocketNavigator socketNav = mach.socketNavigator();
329 Machine::BusNavigator busNav = mach.busNavigator();
330 RegisterQuantityCheck RFCheck;
331 MinimalOpSetCheck minimalOpSetCheck = MinimalOpSetCheck();
332
334 for (int i = 0; i < socketNav.count(); i++) {
335 Socket* socket = socketNav.item(i);
336 for (int bus = 0; bus < busNav.count(); bus++) {
337 socket->detachBus(*busNav.item(bus));
338 }
339 }
340 } else {
341 // remove connections only if connected minimal opset preserved.
342 for (int i = 0; i < socketNav.count(); i++) {
343 Socket* socket = socketNav.item(i);
344 std::set<std::string> ignoreFUNames;
345 std::set<std::string> ignoreRFNames;
346 // check all ports connected to the socket
347 for (int si = 0; si < socket->portCount(); ++si) {
348 Port* port = socket->port(si);
349 if (dynamic_cast<FUPort*>(port)) {
350 ignoreFUNames.insert(port->parentUnit()->name());
351 } else if (dynamic_cast<RFPort*>(port)) {
352 ignoreRFNames.insert(port->parentUnit()->name());
353 }
354 }
355 // TODO: refactor below
356 // TODO: add test that same FU/RF is not checked multiple
357 // times in situations where there are more than one socket
358 // connected to the same FU/RF, do this by storing unit names
359 // and the verdict if connections can be removed as a pair to
360 // a map
361 if (!ignoreFUNames.empty()) {
362 if (minimalOpSetCheck.checkWithIgnore(mach, ignoreFUNames)) {
363 if (!ignoreRFNames.empty()) {
364 if (RFCheck.checkWithIgnore(mach, ignoreRFNames))
365 {
366 for (int bus = 0; bus < busNav.count(); bus++)
367 {
368 socket->detachBus(*busNav.item(bus));
369 }
370 }
371 } else {
372 for (int bus = 0; bus < busNav.count(); bus++) {
373 socket->detachBus(*busNav.item(bus));
374 }
375 }
376 }
377 } else if (!ignoreRFNames.empty()) {
378 if (RFCheck.checkWithIgnore(mach, ignoreRFNames)) {
379 for (int bus = 0; bus < busNav.count(); bus++) {
380 socket->detachBus(*busNav.item(bus));
381 }
382 }
383 } else {
384 for (int bus = 0; bus < busNav.count(); bus++) {
385 socket->detachBus(*busNav.item(bus));
386 }
387 }
388 }
389 }
390 }
391
392 /**
393 * Checks that produced machine is still usable
394 *
395 * @param mach Machine where the connections are added.
396 * @return True if something done to the machine given as parameter.
397 */
399 // check that that machine has enough int registers and fix if needed
400 // and can be fixed
401 RegisterQuantityCheck RFCheck;
402 if (!RFCheck.checkIntRegs(mach) && RFCheck.canFixIntRegs(mach)) {
403 if (!RFCheck.fixIntRegs(mach)) {
404 verboseLog("Failed to add missing integer registers to the"
405 "machine.");
406 return false;
407 } else {
408 return true;
409 }
410 }
411 return false;
412 }
413
414 /**
415 * Adds connections used in the program to the given machine.
416 *
417 * Connections to add are determined by procedure instructions in
418 * application domains programs.
419 *
420 * @param mach Machine where the connections are added.
421 * @param prog Scheduled program where the used connections are searched.
422 */
424 Machine::SocketNavigator socketNav = mach.socketNavigator();
425 Machine::BusNavigator busNav = mach.busNavigator();
426
427 // go through every procedure in the program
428 for (int i = 0; i < prog.procedureCount(); i++) {
429 Procedure& procedure = prog.procedure(i);
430
431 // go through every instruction
432 for (int j = 0; j < procedure.instructionCount(); j++) {
433 Instruction& instruction = procedure.instructionAtIndex(j);
434
435 // check all moves and add connection from source to bus and
436 // bus to destination
437 for (int m = 0; m < instruction.moveCount(); m++) {
438 Move& move = instruction.move(m);
439 std::string busName = move.bus().name();
440 std::string sourceName = "";
441 try {
442 sourceName = move.sourceSocket().name();
443 } catch (const WrongSubclass&) {
444 // source was an immediate, no error
445 assert(move.source().isImmediate());
446 }
447 std::string destinationName =
448 move.destinationSocket().name();
449 Bus* bus = busNav.item(busName);
450
451 // connect the source socket to the bus
452 if (sourceName != "") {
453 Socket* socket = socketNav.item(sourceName);
454 for (int s = 0; s < bus->segmentCount(); s++) {
455 if (!socket->isConnectedTo(*bus->segment(s))) {
456 socket->attachBus(*bus->segment(s));
457 // socket direction is lost when the
458 // connections were removed
460 }
461 }
462 }
463 Socket* socket = socketNav.item(destinationName);
464 for (int s = 0; s < bus->segmentCount(); s++) {
465 if (!socket->isConnectedTo(*bus->segment(s))) {
466 socket->attachBus(*bus->segment(s));
467 // socket direction is lost when the
468 // connections were removed
470 }
471 }
472 }
473 }
474 }
475 }
476};
477
478// parameter names
479const std::string SimpleICOptimizer::tpefPN_("tpef");
480const std::string SimpleICOptimizer::addOnlyPN_("add_only");
481const std::string SimpleICOptimizer::evaluatePN_("evaluate");
482const std::string SimpleICOptimizer::preserveMinOpsPN_("preserve_min_ops");
483
#define verboseLog(text)
#define verboseLogC(text, neededVerbosity)
#define assert(condition)
int RowID
Type definition of row ID in relational databases.
Definition DBTypes.hh:37
#define EXPORT_DESIGN_SPACE_EXPLORER_PLUGIN(PLUGIN_NAME__)
find Finds info of the inner loops in the program
find Finds info of the inner loops in the false
#define BOOL()
static std::string toString(const T &source)
RowID addArchitecture(const TTAMachine::Machine &mom)
TTAMachine::Machine * architecture(RowID id) const
std::set< RowID > applicationIDs() const
MachineConfiguration configuration(RowID id) const
std::string applicationPath(RowID id) const
RowID addConfiguration(const MachineConfiguration &conf)
void readOptionalParameter(const std::string paramName, T &param) const
void addParameter(TCEString name, ExplorerPluginParameterType type, bool compulsory=true, TCEString defaultValue="", TCEString description="")
virtual std::vector< RowID > explore(const RowID &startPointConfigurationID, const unsigned int &maxIter=0)
virtual void giveParameter(const std::string &name, const std::string &value)
bool createImplementation(const DSDBManager::MachineConfiguration &conf, DSDBManager::MachineConfiguration &newConf, const double &frequency=0.0, const double &maxArea=0.0, const bool &createEstimates=true, const std::string &icDec="DefaultICDecoder", const std::string &icDecHDB="asic_130nm_1.5V.hdb")
virtual DSDBManager & db()
static DesignSpaceExplorerPlugin * loadExplorerPlugin(const std::string &pluginName, DSDBManager *dsdb=NULL)
virtual bool evaluate(const DSDBManager::MachineConfiguration &configuration, CostEstimates &results=dummyEstimate_, bool estimate=false)
TTAProgram::Program * schedule(const std::string applicationFile, TTAMachine::Machine &machine, TCEString paramOptions="-O3")
std::string errorMessageStack(bool messagesOnly=false) const
Definition Exception.cc:138
std::string errorMessage() const
Definition Exception.cc:123
bool checkWithIgnore(const TTAMachine::Machine &machine, const std::set< std::string > &ignoreFUName) const
bool checkWithIgnore(const TTAMachine::Machine &mach, const std::set< std::string > &ignoreRFs) const
bool checkIntRegs(const TTAMachine::Machine &mach) const
bool canFixIntRegs(const TTAMachine::Machine &mach) const
bool fixIntRegs(TTAMachine::Machine &mach) const
static const std::string tpefDefaultPN_
static const std::string preserveMinOpsPN_
virtual bool producesArchitecture() const
bool fixIntRegisters(TTAMachine::Machine &mach)
virtual bool requiresHDB() const
virtual bool requiresStartingPointArchitecture() const
bool evaluateResult_
evaluate the result(s)
std::string tpef_
name of the tpef file
static const std::string evaluatePN_
void addConnections(TTAMachine::Machine &mach, Program &prog)
static const std::string tpefPN_
void removeAllConnections(TTAMachine::Machine &mach)
virtual bool requiresSimulationData() const
PLUGIN_DESCRIPTION("Optimizes the IC of the given configuration")
bool addOnly_
can we remove connections
bool preserveMinimalOpset_
respect minimal opset when removing connections
virtual bool requiresApplication() const
virtual std::vector< RowID > explore(const RowID &startPointConfigurationID, const unsigned int &)
static const std::string addOnlyPN_
virtual Segment * segment(int index) const
Definition Bus.cc:329
virtual int segmentCount() const
Definition Bus.cc:385
virtual TCEString name() const
ComponentType * item(int index) const
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
Unit * parentUnit() const
void setDirection(Direction direction)
Definition Socket.cc:130
@ OUTPUT
Data goes from port to bus.
Definition Socket.hh:60
@ INPUT
Data goes from bus to port.
Definition Socket.hh:59
bool isConnectedTo(const Bus &bus) const
Definition Socket.cc:331
void detachBus(Segment &bus)
Definition Socket.cc:213
Port * port(int index) const
Definition Socket.cc:266
void attachBus(Segment &bus)
Definition Socket.cc:166
int portCount() const
virtual int instructionCount() const
virtual Instruction & instructionAtIndex(int index) const
Move & move(int i) const
TTAMachine::Socket & destinationSocket() const
Definition Move.cc:388
TTAMachine::Socket & sourceSocket() const
Definition Move.cc:393
Terminal & source() const
Definition Move.cc:302
const TTAMachine::Bus & bus() const
Definition Move.cc:373
static Program * loadFromTPEF(const std::string &tpefFileName, const TTAMachine::Machine &theMachine)
Definition Program.cc:1112
Procedure & procedure(int index) const
Definition Program.cc:622
int procedureCount() const
Definition Program.cc:610
virtual bool isImmediate() const
Definition Terminal.cc:63
const std::string applicationPath() const