OpenASIP  2.0
BlocksConnectIC.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2021 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 BlocksConnectIC.cc (Derived from VLIWConnectIC.cc)
26  *
27  * Explorer plugin, that generates connections for Blocks machine
28  *
29  * @author Kanishkan Vadivel 2021
30  * @note rating: red
31  */
32 
33 #include <algorithm>
34 #include <vector>
35 
36 #include "ControlUnit.hh"
37 #include "Conversion.hh"
38 #include "DSDBManager.hh"
40 #include "Exception.hh"
41 #include "Guard.hh"
42 #include "HDBRegistry.hh"
43 #include "Machine.hh"
44 #include "Segment.hh"
45 
46 // using namespace TTAProgram;
47 using namespace TTAMachine;
48 using namespace HDB;
49 using std::endl;
50 
53  "Arranges architecture FUs into a Blocks-like interconnection");
54 
56 
57  virtual bool
59  return true;
60  }
61  virtual bool
63  return true;
64  }
65  virtual bool
66  requiresHDB() const {
67  return false;
68  }
69  virtual bool
71  return false;
72  }
73  virtual bool
75  return false;
76  }
77 
78  /**
79  *
80  * Arranges architecture FUs into a Blocks-like interconnection.
81  * This is typically as baseline for running the BusMergeMinimizer and
82  * RFPortMergeMinimizer plugins.
83  * Reference: Blocks, a reconfigurable architecture combining
84  * energy efficiency and flexibility. Wijtvliet, M. (2020).
85  * Technische Universiteit Eindhoven.
86  */
87  virtual std::vector<RowID>
88  explore(const RowID& configurationID, const unsigned int&) {
89  std::vector<RowID> result;
90 
91  DSDBManager& dsdb = db();
93  conf.hasImplementation = false;
94  TTAMachine::Machine* mach = NULL;
95 
96  // load the adf from file or from dsdb
97  try {
98  conf = dsdb.configuration(configurationID);
99  mach = dsdb.architecture(conf.architectureID);
100  } catch (const Exception& e) {
101  std::ostringstream msg(std::ostringstream::out);
103  << "Error loading the adf." << std::endl;
104  return result;
105  }
106  assert(mach != NULL);
107 
108  // Remove unconnected sockets
110  mach->socketNavigator();
111  for (int i = 0; i < socketNavi.count(); i++) {
112  if (socketNavi.item(i)->portCount() == 0) {
113  mach->removeSocket(*socketNavi.item(i));
114  i--;
115  }
116  }
117 
118  // Wiping buses also destroys socket directions (input/output)
119  // and there seems to be no other way to find out whether a port
120  // is input or output.
121  // Save the directions before wiping the buses
122  for (int i = 0; i < socketNavi.count(); i++) {
123  Socket* sock = socketNavi.item(i);
124  // Restrict to 32-bit bus
125  int width = sock->port(0)->width();
126  assert(width == 32 && "ADF has Socket != 32-bit");
127  }
128 
129  // save directions and sockets
130  std::vector<Socket::Direction> directions;
131  std::vector<int> readSockets, writeSockets;
132  int gcu_ra_input = -1, gcu_ra_output = -1, gcu_pc = -1;
133 
134  for (int i = 0; i < socketNavi.count(); i++) {
135  Socket* sock = socketNavi.item(i);
136  Socket::Direction dir = sock->direction();
137  directions.push_back(dir);
138 
139  // Allow only 2-output buffers at max
140  int port_count = sock->portCount();
141  assert(
142  port_count > 0 && port_count <= 2 &&
143  "Socket is not connected or connected to more than 2 FUs");
144  // Separate GCU RA socket for special handling
145  Unit* parentUnit = sock->port(0)->parentUnit();
146  ControlUnit* gcu = dynamic_cast<ControlUnit*>(parentUnit);
147  if (dir == Socket::INPUT) {
148  if (gcu != NULL && sock->port(0)->name() == "ra") {
149  gcu_ra_input = i;
150  } else {
151  readSockets.push_back(i);
152  }
153  } else {
154  writeSockets.push_back(i);
155  if (gcu != NULL && sock->port(0)->name() == "ra") {
156  gcu_ra_output = i;
157  }
158  }
159  }
160 
161  // Wipe all existing buses
163  for (int i = 0; i < busNavi.count(); i++) {
164  mach->removeBus(*busNavi.item(i));
165  i--;
166  }
167 
168  // Add new bus for each input port (i.e. We mux the 4xinput via single
169  // bus)
170  int busCount = 0;
171  std::vector<int> readBuses, writeBuses;
172 
173  /* initialize random seed: */
174  std::srand(time(NULL));
175  for (unsigned int i = 0; i < readSockets.size(); i++) {
176  int rd_soc_idx = readSockets[i];
177  Socket* input_sock = socketNavi.item(rd_soc_idx);
178 
179  // Attach 32-bit bus segment
180  TTAMachine::Segment* newSegment = createBus(mach, 32);
181  newSegment->attachSocket(*input_sock);
182  input_sock->setDirection(directions[rd_soc_idx]);
183  // Handle special case for GCU
184  Unit* parentUnit = input_sock->port(0)->parentUnit();
185  if (dynamic_cast<ControlUnit*>(parentUnit) != NULL &&
186  input_sock->port(0)->name() == "pc") {
187  assert(gcu_ra_input != -1);
188  Socket* ra_sock = socketNavi.item(gcu_ra_input);
189  newSegment->attachSocket(*ra_sock);
190  ra_sock->setDirection(directions[gcu_ra_input]);
191  gcu_pc = rd_soc_idx;
192  }
193  readBuses.push_back(busCount++);
194 
195  // Make connections to the socket (maximum 4 connections)
196  int output_socket_count = writeSockets.size();
197  int req_connections = std::min(output_socket_count, 4);
198  while (req_connections > 0) {
199  // Select random FU output port
200  int wr_soc_idx =
201  writeSockets[std::rand() % writeSockets.size()];
202  Socket* output_sock = socketNavi.item(wr_soc_idx);
203 
204  // Check if we already have connections
205  if (newSegment->isConnectedTo(*output_sock)) {
206  continue;
207  }
208 
209  // No connections to this port yet; make connection
210  newSegment->attachSocket(*output_sock);
211  output_sock->setDirection(directions[wr_soc_idx]);
212  req_connections--;
213  }
214  }
215 
216  // Create instruction template for imm unit
217  if (mach->immediateUnitNavigator().count() != 0) {
218  ImmediateUnit* immu = mach->immediateUnitNavigator().item(0);
219 
220  while (mach->instructionTemplateNavigator().count() > 0) {
222  *mach->instructionTemplateNavigator().item(0));
223  }
224 
225  new InstructionTemplate("no_limm", *mach);
226 
227  InstructionTemplate* limm =
228  new InstructionTemplate("limm", *mach);
229  TTAMachine::Segment* newSegment = createBus(mach, 32);
230  Bus* newBus = newSegment->parentBus();
231 
232  limm->addSlot(newBus->name(), 32, *immu);
233 
234  // Attch GCU's RA and PC sockets (We do not have explicit RA port
235  // in Blocks; so, this is just to emulate the effect of single
236  // port.)
237  assert(gcu_ra_input != -1);
238  newSegment->attachSocket(*socketNavi.item(gcu_ra_input));
239  assert(gcu_ra_output != -1);
240  newSegment->attachSocket(*socketNavi.item(gcu_ra_output));
241  assert(gcu_pc != -1);
242  newSegment->attachSocket(*socketNavi.item(gcu_pc));
243  }
244 
245  // add machine to configuration
246  conf.architectureID = dsdb.addArchitecture(*mach);
247 
248  // add new configuration to dsdb
249  RowID confID = dsdb.addConfiguration(conf);
250  result.push_back(confID);
251  return result;
252  }
253 
254 protected:
255  /**
256  * Creates a bus with specified bit width.
257  *
258  * @param mach Machine for that bus.
259  * @param width Bit width of a bus.
260  * @return Bus segment.
261  */
263  createBus(TTAMachine::Machine* mach, int width) {
264  int idx = mach->busNavigator().count();
265  TCEString busName = "B" + Conversion::toString(idx);
266  Bus* newBus = new Bus(busName, width, 0, Machine::SIGN);
267  TTAMachine::Segment* newSegment =
268  new TTAMachine::Segment(busName, *newBus);
269  mach->addBus(*newBus);
270  return newSegment;
271  }
272 };
273 
TTAMachine::Segment::attachSocket
void attachSocket(Socket &socket)
Definition: Segment.cc:180
TTAMachine::Socket::portCount
int portCount() const
TTAMachine::Socket::port
Port * port(int index) const
Definition: Socket.cc:266
BlocksConnectIC::requiresStartingPointArchitecture
virtual bool requiresStartingPointArchitecture() const
Definition: BlocksConnectIC.cc:58
TTAMachine::Machine::deleteInstructionTemplate
virtual void deleteInstructionTemplate(InstructionTemplate &instrTempl)
Definition: Machine.cc:599
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
HDB
Definition: CostDatabase.hh:49
Exception.hh
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
BlocksConnectIC::requiresSimulationData
virtual bool requiresSimulationData() const
Definition: BlocksConnectIC.cc:70
RowID
int RowID
Type definition of row ID in relational databases.
Definition: DBTypes.hh:37
BlocksConnectIC::explore
virtual std::vector< RowID > explore(const RowID &configurationID, const unsigned int &)
Definition: BlocksConnectIC.cc:88
TTAMachine::Socket::Direction
Direction
Definition: Socket.hh:58
TTAMachine::Machine::Navigator::count
int count() const
TTAMachine::Socket::direction
Direction direction() const
Conversion::toString
static std::string toString(const T &source)
DesignSpaceExplorerPlugin.hh
TTAMachine::InstructionTemplate
Definition: InstructionTemplate.hh:49
assert
#define assert(condition)
Definition: Application.hh:86
Segment.hh
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::Segment::parentBus
Bus * parentBus() const
TTAMachine::Socket
Definition: Socket.hh:53
Guard.hh
BlocksConnectIC::createBus
TTAMachine::Segment * createBus(TTAMachine::Machine *mach, int width)
Definition: BlocksConnectIC.cc:263
BlocksConnectIC::requiresApplication
virtual bool requiresApplication() const
Definition: BlocksConnectIC.cc:74
Machine.hh
TTAMachine::Segment::isConnectedTo
bool isConnectedTo(const Socket &socket) const
Definition: Segment.cc:274
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
BlocksConnectIC::BlocksConnectIC
BlocksConnectIC()
Definition: BlocksConnectIC.cc:55
DSDBManager.hh
DSDBManager::addConfiguration
RowID addConfiguration(const MachineConfiguration &conf)
Definition: DSDBManager.cc:299
BlocksConnectIC::requiresHDB
virtual bool requiresHDB() const
Definition: BlocksConnectIC.cc:66
DSDBManager::addArchitecture
RowID addArchitecture(const TTAMachine::Machine &mom)
Definition: DSDBManager.cc:191
DSDBManager::configuration
MachineConfiguration configuration(RowID id) const
Definition: DSDBManager.cc:361
Application::errorStream
static std::ostream & errorStream()
Definition: Application.cc:171
BlocksConnectIC::producesArchitecture
virtual bool producesArchitecture() const
Definition: BlocksConnectIC.cc:62
TTAMachine::Port::name
virtual std::string name() const
Definition: Port.cc:141
TCEString
Definition: TCEString.hh:53
ControlUnit.hh
TTAMachine::Machine::busNavigator
virtual BusNavigator busNavigator() const
Definition: Machine.cc:356
TTAMachine::Machine::removeSocket
virtual void removeSocket(Socket &socket)
Definition: Machine.cc:490
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
TTAMachine
Definition: Assembler.hh:48
TTAMachine::Machine::instructionTemplateNavigator
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition: Machine.cc:428
HDBRegistry.hh
DSDBManager::MachineConfiguration::architectureID
RowID architectureID
Definition: DSDBManager.hh:79
BlocksConnectIC
Definition: BlocksConnectIC.cc:51
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
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