OpenASIP 2.2
Loading...
Searching...
No Matches
VLIWConnectIC.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2017 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 VLIWConnectIC.cc
26 *
27 * Explorer plugin that adds maximum connections to all the buses in
28 * the machine.
29 *
30 * @author Timo Viitanen 2014
31 * @author Alex Hirvonen 2017 (alex.hirvonen-no.spam-gmail.com)
32 * @note rating: red
33 */
34
35#include <vector>
36#include <algorithm>
37
39#include "DSDBManager.hh"
40#include "HDBRegistry.hh"
41#include "Exception.hh"
42#include "Machine.hh"
43#include "Conversion.hh"
44#include "Segment.hh"
45#include "Guard.hh"
46#include "ControlUnit.hh"
47
48//using namespace TTAProgram;
49using namespace TTAMachine;
50using namespace HDB;
51using std::endl;
52
53class
55 PLUGIN_DESCRIPTION("Arranges architecture FUs into a VLIW-like "
56 "interconnection by adding separate RF for each distinct bus width.");
57
63 "Short immediate width for each bus.");
65 "Number of dummy buses for long immediates. (power-of-2)");
67 "Generate a VLIW-style register file.");
68 }
69
70 virtual bool requiresStartingPointArchitecture() const { return true; }
71 virtual bool producesArchitecture() const { return true; }
72 virtual bool requiresHDB() const { return false; }
73 virtual bool requiresSimulationData() const { return false; }
74 virtual bool requiresApplication() const { return false; }
75
76
77 /**
78 * Arranges architecture FUs into a VLIW-like interconnection. This is
79 * typically as baseline for running the BusMergeMinimizer and
80 * RFPortMergeMinimizer plugins.
81 */
82 virtual std::vector<RowID>
83 explore(const RowID& configurationID, const unsigned int&) {
85
86 std::vector<RowID> result;
87
88 DSDBManager& dsdb = db();
90 conf.hasImplementation = false;
91 TTAMachine::Machine* mach = NULL;
92
93 // load the adf from file or from dsdb
94 try {
95 conf = dsdb.configuration(configurationID);
96 mach = dsdb.architecture(conf.architectureID);
97 } catch (const Exception& e) {
98 std::ostringstream msg(std::ostringstream::out);
100 << "Error loading the adf." << std::endl;
101 return result;
102 }
103 assert(mach != NULL);
104
105 //Find BOOL
107 = mach->registerFileNavigator();
108
109 RegisterFile* boolrf = NULL;
110 for (int i = 0; i < rfNavi.count(); i++) {
111 RegisterFile* rf = rfNavi.item(i);
112 if (rf->width() == 1) {
113 boolrf = rf;
114 }
115 }
116 assert(boolrf != NULL);
117
118 // Remove register files, except for BOOL
119 if (wipeRegisterFile_) {
120 for (int i = 0; i < rfNavi.count(); i++) {
121 RegisterFile* rf = rfNavi.item(i);
122 if (rf->width() != 1) {
123 mach->removeRegisterFile(*rfNavi.item(i));
124 i--;
125 }
126 }
127 }
128
129 // Remove unconnected sockets
131 = mach->socketNavigator();
132 for (int i = 0; i < socketNavi.count(); i++) {
133 if (socketNavi.item(i)->portCount() == 0 ) {
134 mach->removeSocket(*socketNavi.item(i));
135 i--;
136 }
137 }
138
139 // Wiping buses also destroys socket directions (input/output)
140 // and there seems to be no other way to find out whether a port
141 // is input or output.
142 // -> Save the directions before wiping the buses
143
144 // get number of all distinct bus widths in the machine first
145 std::vector<int>::iterator iter;
146
147 for (int i = 0; i < socketNavi.count(); i++) {
148 Socket* sock = socketNavi.item(i);
149
150 assert(sock->portCount() == 1);
151 int width = sock->port(0)->width();
152
153 // combine <=32 bit widths into one cluster
154 if (width < 32) {
155 width = 32;
156 }
157
158 // add non-existing width to distinctBusWidths
159 iter = std::find(distinctBusWidths_.begin(),
160 distinctBusWidths_.end(), width);
161 if (iter == distinctBusWidths_.end()) {
162 distinctBusWidths_.push_back(width);
163 }
164 }
165
166 sort(distinctBusWidths_.begin(), distinctBusWidths_.end());
167 int numDistinctBusWidths = distinctBusWidths_.size();
168
169 // save directions and sockets
170 std::vector<Socket::Direction> directions;
171 std::vector< std::vector<int> > readSockets(numDistinctBusWidths),
172 writeSockets(numDistinctBusWidths),
173 controlSockets(numDistinctBusWidths);
174
175 for (int i = 0; i < socketNavi.count(); i++) {
176 Socket* sock = socketNavi.item(i);
177 Socket::Direction dir = sock->direction();
178 directions.push_back(dir);
179
180 assert(sock->portCount() == 1);
181 Unit* parentUnit = sock->port(0)->parentUnit();
182 int width = sock->port(0)->width();
183 int widx = widthIndex(width);
184
185 if (dynamic_cast<BaseRegisterFile*>(parentUnit) == NULL
186 && dynamic_cast<ControlUnit*>(parentUnit) == NULL) {
187 if (dir == Socket::INPUT) {
188 readSockets[widx].push_back(i);
189 }
190 else {
191 writeSockets[widx].push_back(i);
192 }
193 }
194 else {
195 controlSockets[widx].push_back(i);
196 }
197
198 }
199
200 // Wipe all existing buses
201
203 for (int i = 0; i < busNavi.count(); i++) {
204 mach->removeBus(*busNavi.item(i));
205 i--;
206 }
207
208 // Add new bus for each fu/gcu socket
209 std::vector< std::vector<int> > readBuses(numDistinctBusWidths),
210 writeBuses(numDistinctBusWidths);
211 int busCount = 0;
212
213 for (int widx = 0; widx < numDistinctBusWidths; ++widx) {
214 int width = distinctBusWidths_[widx];
215
216 if (widx == 0) {
217 TTAMachine::Segment* newSegment = createBus(mach, 32);
218
219 for (unsigned int i = 0; i < controlSockets[widx].size(); i++) {
220 int idx = controlSockets[widx][i];
221 newSegment->attachSocket(*socketNavi.item(idx));
222 socketNavi.item(idx)->setDirection(directions[idx]);
223 }
224 readBuses[widx].push_back(busCount);
225 writeBuses[widx].push_back(busCount++);
226 }
227
228 for (unsigned int i = 0; i < readSockets[widx].size(); i++) {
229 int idx = readSockets[widx][i];
230 TTAMachine::Segment* newSegment = createBus(mach, width);
231 newSegment->attachSocket(*socketNavi.item(idx));
232 socketNavi.item(idx)->setDirection(directions[idx]);
233 readBuses[widx].push_back(busCount++);
234 }
235
236 for (unsigned int i = 0; i < writeSockets[widx].size(); i++) {
237 int idx = writeSockets[widx][i];
238 TTAMachine::Segment* newSegment = createBus(mach, width);
239 newSegment->attachSocket(*socketNavi.item(idx));
240 socketNavi.item(idx)->setDirection(directions[idx]);
241 writeBuses[widx].push_back(busCount++);
242 }
243 }
244
245 // Add register file
246 for (int widx = 0; widx < numDistinctBusWidths; ++widx) {
247 if (readBuses[widx].size() == 0 && writeBuses[widx].size() == 0) {
248 continue;
249 }
250
251 if (wipeRegisterFile_) {
252 int width = distinctBusWidths_[widx];
253
254 RegisterFile* rf = new RegisterFile(
255 "RF_" + Conversion::toString(width),
256 512, // high enough to avoid register spills
257 width,
258 readBuses[widx].size(),
259 writeBuses[widx].size(),
260 0,
262 mach->addRegisterFile(*rf);
263
264 // Add RF read ports
265 for (unsigned int i = 0; i < readBuses[widx].size(); i++) {
266 TCEString socketName = "R" + Conversion::toString(i) +
267 "_" + Conversion::toString(width);
268 Socket* newSocket = new Socket(socketName);
269 mach->addSocket(*newSocket);
270
271 RFPort* newPort = new RFPort(socketName, *rf);
272 newPort->attachSocket(*newSocket);
273 busNavi.item(readBuses[widx][i])->segment(0)->
274 attachSocket(*newSocket);
275 newSocket->setDirection(Socket::OUTPUT);
276 }
277
278 // Add RF write ports
279 for (unsigned int i = 0; i < writeBuses[widx].size(); i++) {
280 TCEString socketName = "W" + Conversion::toString(i) +
281 "_" + Conversion::toString(width);
282 Socket* newSocket = new Socket(socketName);
283 mach->addSocket(*newSocket);
284
285 RFPort* newPort = new RFPort(socketName, *rf);
286 newPort->attachSocket(*newSocket);
287 busNavi.item(writeBuses[widx][i])->segment(0)->
288 attachSocket(*newSocket);
289 newSocket->setDirection(Socket::INPUT);
290 }
291 }
292 }
293
294 // Add bypasses
295 for (int widx = 0; widx < numDistinctBusWidths; ++widx) {
296 for (unsigned int i = 0; i < writeSockets[widx].size(); i++) {
297 Socket* output = socketNavi.item(writeSockets[widx][i]);
298 for (unsigned int j = 0; j < readBuses[widx].size(); j++) {
299 Bus* readBus = busNavi.item(readBuses[widx][j]);
300 readBus->segment(0)->attachSocket(*output);
301 }
302 }
303 }
304
305 for (int i = 0; i < busNavi.count(); i++) {
306 Bus* bus = busNavi.item(i);
307
308 new UnconditionalGuard(false, *bus);
309 new RegisterGuard(false, *boolrf, 0, bus);
310 new RegisterGuard(true, *boolrf, 0, bus);
311 new RegisterGuard(false, *boolrf, 1, bus);
312 new RegisterGuard(true, *boolrf, 1, bus);
313 }
314
315 for (int i = 0; i < busNavi.count(); i++) {
316 Bus* bus = busNavi.item(i);
318
319 // connect each bus to immediate unit to avoid register files access
320 ImmediateUnit* immu = mach->immediateUnitNavigator().item(0);
321 if (!immu->port(0)->outputSocket()->isConnectedTo(*bus)) {
322 immu->port(0)->outputSocket()->attachBus(*bus->segment(0));
323 }
324 }
325
326 // add unconnected long immediate buses
327 if (mach->immediateUnitNavigator().count() != 0) {
328 ImmediateUnit* immu = mach->immediateUnitNavigator().item(0);
329
330 while (mach->instructionTemplateNavigator().count() > 0) {
333 }
334
335 new InstructionTemplate("no_limm", *mach);
336
338 = new InstructionTemplate("limm", *mach);
339 for (int i = 0; i < longImmediateBusCount_; i++) {
340 TTAMachine::Segment* newSegment = createBus(mach, 32);
341 Bus* newBus = newSegment->parentBus();
342
343 limm->addSlot(newBus->name(), 32/longImmediateBusCount_, *immu);
344 }
345 }
346
347 // add machine to configuration
348 conf.architectureID = dsdb.addArchitecture(*mach);
349
350 // add new configuration to dsdb
351 RowID confID = dsdb.addConfiguration(conf);
352 result.push_back(confID);
353 return result;
354 }
355
356 protected:
357
361 // number of distinct bus widths in current machine
362 std::vector<int> distinctBusWidths_;
366
367
368 /**
369 * Reads the parameters given to the plugin.
370 */
376
377 /**
378 * Creates a bus with specified bit width.
379 *
380 * @param mach Machine for that bus.
381 * @param width Bit width of a bus.
382 * @return Bus segment.
383 */
385 int idx = mach->busNavigator().count();
386 TCEString busName = "B" + Conversion::toString(idx);
387 Bus* newBus = new Bus(busName, width, 0, Machine::SIGN);
388 TTAMachine::Segment* newSegment =
389 new TTAMachine::Segment(busName, *newBus);
390 mach->addBus(*newBus);
391 return newSegment;
392 }
393
394 /**
395 * Returns corresponding cluster index in distinct buses vector list.
396 *
397 * @param width Bus width to get index.
398 * @param buses Vector list of distinct buses in current machine.
399 * @return Bus width cluster index.
400 */
401 int widthIndex(int width) {
402 if (width < 32) {
403 width = 32;
404 }
405
406 int i = 0;
407 for (auto const& busW : distinctBusWidths_) {
408 if (width == busW) {
409 break;
410 }
411 i++;
412 }
413 return i;
414 }
415
416};
417
418const TCEString VLIWConnectIC::wipeRegisterFilePN_("wipe_register_file");
421
423
#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 false
#define INT(OPERAND)
Definition OSAL.hh:312
#define BOOL()
static std::ostream & errorStream()
static std::string toString(const T &source)
RowID addArchitecture(const TTAMachine::Machine &mom)
TTAMachine::Machine * architecture(RowID id) const
MachineConfiguration configuration(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 DSDBManager & db()
virtual int width() const
virtual RFPort * port(const std::string &name) const
virtual Segment * segment(int index) const
Definition Bus.cc:329
virtual void setImmediateWidth(int width)
Definition Bus.cc:241
virtual TCEString name() const
virtual void addSlot(const std::string &slotName, int width, ImmediateUnit &dstUnit)
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition Machine.cc:428
virtual void deleteInstructionTemplate(InstructionTemplate &instrTempl)
Definition Machine.cc:599
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
virtual void removeBus(Bus &bus)
Definition Machine.cc:477
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual void addBus(Bus &bus)
Definition Machine.cc:139
@ SIGN
Sign extension.
Definition Machine.hh:82
virtual void addRegisterFile(RegisterFile &unit)
Definition Machine.cc:236
virtual void removeSocket(Socket &socket)
Definition Machine.cc:490
virtual void addSocket(Socket &socket)
Definition Machine.cc:157
virtual void removeRegisterFile(RegisterFile &unit)
Definition Machine.cc:554
virtual Socket * outputSocket() const
Definition Port.cc:281
virtual void attachSocket(Socket &socket)
Definition Port.cc:191
virtual int width() const =0
Unit * parentUnit() const
@ NORMAL
Used for general register allocation.
Bus * parentBus() const
void attachSocket(Socket &socket)
Definition Segment.cc:180
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
Direction direction() const
Port * port(int index) const
Definition Socket.cc:266
void attachBus(Segment &bus)
Definition Socket.cc:166
int portCount() const
virtual bool producesArchitecture() const
virtual bool requiresApplication() const
virtual std::vector< RowID > explore(const RowID &configurationID, const unsigned int &)
static const TCEString wipeRegisterFilePN_
virtual bool requiresSimulationData() const
std::vector< int > distinctBusWidths_
static const TCEString shortImmediateWidthPN_
static const TCEString longImmediateBusCountPN_
int widthIndex(int width)
virtual bool requiresStartingPointArchitecture() const
TTAMachine::Segment * createBus(TTAMachine::Machine *mach, int width)
PLUGIN_DESCRIPTION("Arranges architecture FUs into a VLIW-like " "interconnection by adding separate RF for each distinct bus width.")
virtual bool requiresHDB() const