OpenASIP 2.2
Loading...
Searching...
No Matches
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;
47using namespace TTAMachine;
48using namespace HDB;
49using 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) {
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
254protected:
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
#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__)
static std::ostream & errorStream()
virtual bool requiresHDB() const
virtual std::vector< RowID > explore(const RowID &configurationID, const unsigned int &)
TTAMachine::Segment * createBus(TTAMachine::Machine *mach, int width)
virtual bool requiresStartingPointArchitecture() const
virtual bool producesArchitecture() const
PLUGIN_DESCRIPTION("Arranges architecture FUs into a Blocks-like interconnection")
virtual bool requiresApplication() const
virtual bool requiresSimulationData() const
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)
virtual DSDBManager & db()
virtual TCEString name() const
virtual void addSlot(const std::string &slotName, int width, ImmediateUnit &dstUnit)
ComponentType * item(int index) const
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 removeSocket(Socket &socket)
Definition Machine.cc:490
virtual int width() const =0
Unit * parentUnit() const
virtual std::string name() const
Definition Port.cc:141
bool isConnectedTo(const Socket &socket) const
Definition Segment.cc:274
Bus * parentBus() const
void attachSocket(Socket &socket)
Definition Segment.cc:180
void setDirection(Direction direction)
Definition Socket.cc:130
@ INPUT
Data goes from bus to port.
Definition Socket.hh:59
Direction direction() const
Port * port(int index) const
Definition Socket.cc:266
int portCount() const