OpenASIP  2.0
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;
49 using namespace TTAMachine;
50 using namespace HDB;
51 using std::endl;
52 
53 class
55  PLUGIN_DESCRIPTION("Arranges architecture FUs into a VLIW-like "
56  "interconnection by adding separate RF for each distinct bus width.");
57 
59  wipeRegisterFile_(false),
60  shortImmediateWidth_(6),
61  longImmediateBusCount_(1) {
62  addParameter(shortImmediateWidthPN_, INT, false, "6",
63  "Short immediate width for each bus.");
64  addParameter(longImmediateBusCountPN_, INT, false, "1",
65  "Number of dummy buses for long immediates. (power-of-2)");
66  addParameter(wipeRegisterFilePN_, BOOL, false, "true",
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&) {
84  readParameters();
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);
317  bus->setImmediateWidth(shortImmediateWidth_);
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) {
332  *mach->instructionTemplateNavigator().item(0));
333  }
334 
335  new InstructionTemplate("no_limm", *mach);
336 
337  InstructionTemplate* limm
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  */
371  void readParameters() {
372  readOptionalParameter(wipeRegisterFilePN_, wipeRegisterFile_);
373  readOptionalParameter(shortImmediateWidthPN_, shortImmediateWidth_);
374  readOptionalParameter(longImmediateBusCountPN_, longImmediateBusCount_);
375  }
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 
418 const TCEString VLIWConnectIC::wipeRegisterFilePN_("wipe_register_file");
420 const TCEString VLIWConnectIC::longImmediateBusCountPN_("limm_bus_count");
421 
423 
VLIWConnectIC::wipeRegisterFile_
bool wipeRegisterFile_
Definition: VLIWConnectIC.cc:358
TTAMachine::Segment::attachSocket
void attachSocket(Socket &socket)
Definition: Segment.cc:180
TTAMachine::Socket::port
Port * port(int index) const
Definition: Socket.cc:266
TTAMachine::Socket::portCount
int portCount() const
TTAMachine::Machine::deleteInstructionTemplate
virtual void deleteInstructionTemplate(InstructionTemplate &instrTempl)
Definition: Machine.cc:599
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
TTAMachine::Bus::setImmediateWidth
virtual void setImmediateWidth(int width)
Definition: Bus.cc:241
HDB
Definition: CostDatabase.hh:49
TTAMachine::Socket::OUTPUT
@ OUTPUT
Data goes from port to bus.
Definition: Socket.hh:60
Exception.hh
VLIWConnectIC
Definition: VLIWConnectIC.cc:53
DSDBManager::architecture
TTAMachine::Machine * architecture(RowID id) const
Definition: DSDBManager.cc:807
TTAMachine::Segment
Definition: Segment.hh:54
DSDBManager::MachineConfiguration::hasImplementation
bool hasImplementation
Definition: DSDBManager.hh:80
TTAMachine::Bus
Definition: Bus.hh:53
TTAMachine::InstructionTemplate::addSlot
virtual void addSlot(const std::string &slotName, int width, ImmediateUnit &dstUnit)
Definition: InstructionTemplate.cc:169
TTAMachine::Port::width
virtual int width() const =0
TTAMachine::Machine::removeBus
virtual void removeBus(Bus &bus)
Definition: Machine.cc:477
DesignSpaceExplorerPlugin
Definition: DesignSpaceExplorerPlugin.hh:55
VLIWConnectIC::requiresSimulationData
virtual bool requiresSimulationData() const
Definition: VLIWConnectIC.cc:73
VLIWConnectIC::longImmediateBusCountPN_
static const TCEString longImmediateBusCountPN_
Definition: VLIWConnectIC.cc:365
RowID
int RowID
Type definition of row ID in relational databases.
Definition: DBTypes.hh:37
TTAMachine::Socket::Direction
Direction
Definition: Socket.hh:58
TTAMachine::Machine::Navigator::count
int count() const
TTAMachine::Socket::direction
Direction direction() const
TTAMachine::Bus::segment
virtual Segment * segment(int index) const
Definition: Bus.cc:329
Conversion::toString
static std::string toString(const T &source)
DesignSpaceExplorerPlugin.hh
TTAMachine::RFPort
Definition: RFPort.hh:45
VLIWConnectIC::requiresHDB
virtual bool requiresHDB() const
Definition: VLIWConnectIC.cc:72
BOOL
@ BOOL
Definition: ExplorerPluginParameter.hh:40
TTAMachine::InstructionTemplate
Definition: InstructionTemplate.hh:49
assert
#define assert(condition)
Definition: Application.hh:86
VLIWConnectIC::widthIndex
int widthIndex(int width)
Definition: VLIWConnectIC.cc:401
TTAMachine::UnconditionalGuard
Definition: Guard.hh:180
TTAMachine::Port::attachSocket
virtual void attachSocket(Socket &socket)
Definition: Port.cc:191
TTAMachine::Machine::addRegisterFile
virtual void addRegisterFile(RegisterFile &unit)
Definition: Machine.cc:236
Segment.hh
TTAMachine::BaseRegisterFile
Definition: BaseRegisterFile.hh:48
TTAMachine::Socket::attachBus
void attachBus(Segment &bus)
Definition: Socket.cc:166
DSDBManager::MachineConfiguration
Definition: DSDBManager.hh:78
PLUGIN_DESCRIPTION
const std::string PLUGIN_DESCRIPTION
Definition: DefaultICDecoderPlugin.cc:917
TTAMachine::Unit
Definition: Unit.hh:51
EXPORT_DESIGN_SPACE_EXPLORER_PLUGIN
#define EXPORT_DESIGN_SPACE_EXPLORER_PLUGIN(PLUGIN_NAME__)
Definition: DesignSpaceExplorerPlugin.hh:125
TTAMachine::Machine::immediateUnitNavigator
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition: Machine.cc:416
TTAMachine::ControlUnit
Definition: ControlUnit.hh:50
Conversion.hh
TTAMachine::RegisterGuard
Definition: Guard.hh:137
TTAMachine::Segment::parentBus
Bus * parentBus() const
TTAMachine::Socket
Definition: Socket.hh:53
Guard.hh
VLIWConnectIC::createBus
TTAMachine::Segment * createBus(TTAMachine::Machine *mach, int width)
Definition: VLIWConnectIC.cc:384
TTAMachine::Machine::removeRegisterFile
virtual void removeRegisterFile(RegisterFile &unit)
Definition: Machine.cc:554
VLIWConnectIC::VLIWConnectIC
VLIWConnectIC()
Definition: VLIWConnectIC.cc:58
VLIWConnectIC::shortImmediateWidth_
int shortImmediateWidth_
Definition: VLIWConnectIC.cc:359
Machine.hh
Exception
Definition: Exception.hh:54
DSDBManager
Definition: DSDBManager.hh:76
TTAMachine::Machine::socketNavigator
virtual SocketNavigator socketNavigator() const
Definition: Machine.cc:368
TTAMachine::Socket::setDirection
void setDirection(Direction direction)
Definition: Socket.cc:130
TTAMachine::Machine::addBus
virtual void addBus(Bus &bus)
Definition: Machine.cc:139
TTAMachine::Machine::SIGN
@ SIGN
Sign extension.
Definition: Machine.hh:82
TTAMachine::Socket::isConnectedTo
bool isConnectedTo(const Bus &bus) const
Definition: Socket.cc:331
VLIWConnectIC::requiresStartingPointArchitecture
virtual bool requiresStartingPointArchitecture() const
Definition: VLIWConnectIC.cc:70
INT
@ INT
Definition: ExplorerPluginParameter.hh:40
VLIWConnectIC::shortImmediateWidthPN_
static const TCEString shortImmediateWidthPN_
Definition: VLIWConnectIC.cc:364
DSDBManager.hh
VLIWConnectIC::readParameters
void readParameters()
Definition: VLIWConnectIC.cc:371
DSDBManager::addConfiguration
RowID addConfiguration(const MachineConfiguration &conf)
Definition: DSDBManager.cc:299
DSDBManager::addArchitecture
RowID addArchitecture(const TTAMachine::Machine &mom)
Definition: DSDBManager.cc:191
VLIWConnectIC::distinctBusWidths_
std::vector< int > distinctBusWidths_
Definition: VLIWConnectIC.cc:362
VLIWConnectIC::explore
virtual std::vector< RowID > explore(const RowID &configurationID, const unsigned int &)
Definition: VLIWConnectIC.cc:83
TTAMachine::BaseRegisterFile::port
virtual RFPort * port(const std::string &name) const
Definition: BaseRegisterFile.cc:129
TTAMachine::Machine::registerFileNavigator
virtual RegisterFileNavigator registerFileNavigator() const
Definition: Machine.cc:450
DSDBManager::configuration
MachineConfiguration configuration(RowID id) const
Definition: DSDBManager.cc:361
VLIWConnectIC::wipeRegisterFilePN_
static const TCEString wipeRegisterFilePN_
Definition: VLIWConnectIC.cc:363
Application::errorStream
static std::ostream & errorStream()
Definition: Application.cc:171
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
TCEString
Definition: TCEString.hh:53
ControlUnit.hh
TTAMachine::Machine::busNavigator
virtual BusNavigator busNavigator() const
Definition: Machine.cc:356
TTAMachine::Port::outputSocket
virtual Socket * outputSocket() const
Definition: Port.cc:281
TTAMachine::RegisterFile::NORMAL
@ NORMAL
Used for general register allocation.
Definition: RegisterFile.hh:51
TTAMachine::Machine::removeSocket
virtual void removeSocket(Socket &socket)
Definition: Machine.cc:490
VLIWConnectIC::longImmediateBusCount_
int longImmediateBusCount_
Definition: VLIWConnectIC.cc:360
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
TTAMachine::RegisterFile
Definition: RegisterFile.hh:47
VLIWConnectIC::producesArchitecture
virtual bool producesArchitecture() const
Definition: VLIWConnectIC.cc:71
TTAMachine
Definition: Assembler.hh:48
VLIWConnectIC::requiresApplication
virtual bool requiresApplication() const
Definition: VLIWConnectIC.cc:74
TTAMachine::Machine::instructionTemplateNavigator
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition: Machine.cc:428
HDBRegistry.hh
TTAMachine::BaseRegisterFile::width
virtual int width() const
DSDBManager::MachineConfiguration::architectureID
RowID architectureID
Definition: DSDBManager.hh:79
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
TTAMachine::Machine::addSocket
virtual void addSocket(Socket &socket)
Definition: Machine.cc:157
TTAMachine::Machine
Definition: Machine.hh:73
TTAMachine::Socket::INPUT
@ INPUT
Data goes from bus to port.
Definition: Socket.hh:59
TTAMachine::Port::parentUnit
Unit * parentUnit() const
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50