OpenASIP 2.2
Loading...
Searching...
No Matches
BlocksTranslator.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 BlocksTranslator.cc
26 *
27 * Implementation of the translation (Blocks to TTA) functions.
28 *
29 * @author Maarten Molendijk 2020 (m.j.molendijk@tue.nl)
30 * @author Kanishkan Vadivel 2021 (k.vadivel@tue.nl)
31 */
32
33#include "BlocksTranslator.hh"
34
35#include <map>
36#include <memory>
37#include <string>
38
39#include "BlocksModel.hh"
40#include "ExecutionPipeline.hh"
41#include "Segment.hh"
42
43using namespace TTAMachine;
44using namespace std;
45
46/**
47 * Build the TTA model (adf file) from the Blocks model.
48 *
49 * @param BlocksModel The Blocks model created from the Blocks
50 * 'architecture.xml'.
51 * @param outputName The name of the output adf.
52 */
53void
55 BlocksModel& blocksModel, const string& outputName) {
56 Machine ttaMach;
57 ttaMach.setLittleEndian(true);
58 // Create data and instruction adress spaces
59 const int bitWidth = 8;
60 const unsigned int minAddress = 0;
61 // TODO(mm): Allow for different instr mem size than default
62 const unsigned int maxAddressInstr = 2046;
63 // TODO(mm): Allow for different data mem size than default
64 const unsigned int maxAddressData = 32768;
65 AddressSpace asData(
66 "data", bitWidth, minAddress, maxAddressData, ttaMach);
67 AddressSpace asInstr(
68 "instructions", bitWidth, minAddress, maxAddressInstr, ttaMach);
69
70 // Create a list for each functional unit type
71 list<BlocksALUPair*> aluList;
72 list<BlocksLSUPair*> lsuList;
73 list<BlocksRF*> rfList;
74 list<BlocksIMM*> iuList;
75 list<BlocksMULPair*> mulList;
76
77 // Default required unit
78 InstructionTemplate limm("limm", ttaMach);
79 BlocksGCU gcu(
80 ttaMach, "abu",
81 asInstr); // Has to be created here so in IU slot can be added
82
83 // Check which outputs of the FU are used, each output requires a seperate
84 // TTA FU.
85 for (auto& fu : blocksModel.mFunctionalUnitList) {
86 for (auto& source : fu.src) {
87 // Split the string into FU and port
88 string sourcePort = source.substr(source.rfind(".") + 1);
89 string sourceFu = source.substr(0, source.rfind("."));
90 // Set the usesOutx to true
91 for (auto& srcFu : blocksModel.mFunctionalUnitList) {
92 if (srcFu.name == sourceFu) {
93 if (sourcePort == "0")
94 srcFu.usesOut0 = true;
95 else
96 srcFu.usesOut1 = true;
97 }
98 }
99 }
100 }
101
102 // Create for each Blocks unit a TTA unit (except default GCU and IDs)
103 for (auto& fu : blocksModel.mFunctionalUnitList) {
104 switch (fu.type) {
105 case FU_TYPE::ID:
106 break; // Instruction decoders are not taken into account.
107 case FU_TYPE::LSU:
108 lsuList.push_back(new BlocksLSUPair(
109 ttaMach, fu.name, fu.src, asData, fu.usesOut0,
110 fu.usesOut1));
111 break;
112 case FU_TYPE::ALU:
113 aluList.push_back(new BlocksALUPair(
114 ttaMach, fu.name, fu.src, fu.usesOut0, fu.usesOut1));
115 break;
116 case FU_TYPE::RF:
117 rfList.push_back(new BlocksRF(ttaMach, fu.name, fu.src));
118 break;
119 case FU_TYPE::IU:
120 iuList.push_back(new BlocksIMM(ttaMach, fu.name, fu.src));
121 if (iuList.size() == 1)
122 limm.addSlot("ra_out_to_ra_in", 32, *(iuList.back()->iu));
123 break;
124 case FU_TYPE::MUL:
125 mulList.push_back(new BlocksMULPair(
126 ttaMach, fu.name, fu.src, fu.usesOut0, fu.usesOut1));
127 break;
128 case FU_TYPE::ABU:
129 gcu.sources = fu.src;
130 break;
131 default:
132 try {
133 throw "Illegal function unit type in Blocks.xml file, aborting translation. \n";
134 } catch (const char* error) {
135 fprintf(stderr, "%s", error);
137 ttaMach, aluList, lsuList, rfList, iuList, mulList);
138 return;
139 }
140 }
141 }
142
143 ConnectInputs(ttaMach, gcu, aluList, lsuList, rfList, mulList);
144 ttaMach.writeToADF(outputName);
145 Deinitialize(ttaMach, aluList, lsuList, rfList, iuList, mulList);
146}
147
148/**
149 * Create a connection between two different sockets.
150 * Note: Input := Bus to port, output := Port to bus.
151 *
152 * @param mach The TTA machine where the connection needs to be made.
153 * @param inputSocket A pointer to the TTA input socket that needs to be
154 * connected.
155 * @param outputSocket A pointer to the TTA output socket that needs to be
156 * connected.
157 * @param gcu A reference to the TTA GCU (ABU) model.
158 */
159Bus*
161 Machine& mach, Socket* inputSocket, Socket* outputSocket,
162 BlocksGCU& gcu) {
163 // TODO(mm): add exception catching where given "input" is not an input
164 // port
165 const int busWidth = 32;
166 const int immWidth = 0;
167 const string& to = inputSocket->name();
168 const string& from = outputSocket->name();
169 Machine::Extension busExt = Machine::Extension::ZERO;
170 Machine::BusNavigator busNav = mach.busNavigator();
171 const string newBusNum = to_string(busNav.count());
172 Bus* ttaBus;
173 // Verify if the socket is already attached to a bus (excluding
174 // 'ra_out_to_ra_in')
175 if (inputSocket->segmentCount() == 0) {
176 ttaBus = new Bus("bus_" + newBusNum, busWidth, immWidth, busExt);
177 mach.addBus(*ttaBus);
178 new Segment("seg1", *ttaBus);
179 if (inputSocket->name() == "ra_in" || inputSocket->name() == "pc") {
180 gcu.pcIn->attachBus(*ttaBus);
181 gcu.raIn->attachBus(*ttaBus);
182 } else {
183 inputSocket->attachBus(*ttaBus);
184 }
185 } else if (
186 inputSocket->segmentCount() == 1 &&
187 inputSocket->segment(0)->parentBus()->name() == "ra_out_to_ra_in") {
188 ttaBus = new Bus("bus_" + newBusNum, busWidth, immWidth, busExt);
189 mach.addBus(*ttaBus);
190 new Segment("seg1", *ttaBus);
191 if (inputSocket->name() == "ra_in" || inputSocket->name() == "pc") {
192 gcu.pcIn->attachBus(*ttaBus);
193 gcu.raIn->attachBus(*ttaBus);
194 } else {
195 inputSocket->attachBus(*ttaBus);
196 }
197 } else if (
198 inputSocket->segmentCount() == 2 &&
199 inputSocket->segment(0)->parentBus()->name() == "ra_out_to_ra_in") {
200 Segment* segment1 = inputSocket->segment(1);
201 ttaBus = segment1->parentBus();
202 }
203 // Not 'ra_out_to_ra_in' and segmentCount == 1
204 else {
205 Segment* segment1 = inputSocket->segment(0);
206 ttaBus = segment1->parentBus();
207 }
208 // Attach busses to sockets
209 outputSocket->attachBus(*ttaBus);
210 outputSocket->setDirection(Socket::Direction::OUTPUT);
211 return ttaBus;
212}
213
214/**
215 * Create all the connectivity in the TTA model.
216 *
217 * @param mach The TTA machine where the connections need to be made.
218 * @param gcu A reference to the TTA GCU (ABU) model.
219 * @param aluList A list with all ALU pairs currently in the TTA model.
220 * @param lsuList A list with all LSU pairs currently in the TTA model.
221 * @param rfList A list with all RFs currently in the TTA model.
222 * @param mulList A list with all MUL pairs currently in the TTA model.
223 */
224void
226 TTAMachine::Machine& mach, BlocksGCU& gcu,
227 std::list<BlocksALUPair*> aluList, std::list<BlocksLSUPair*> lsuList,
228 std::list<BlocksRF*> rfList, std::list<BlocksMULPair*> mulList) {
230 // Create ALU connections (all connections that are an input to the ALUs)
231 for (auto& blocksAlu : aluList) {
232 for (auto& source : blocksAlu->sources) {
233 Socket* outputSocket = FindOutputSocket(nav, source);
235 mach, blocksAlu->in1sock.get(), outputSocket, gcu);
237 mach, blocksAlu->in2sock.get(), outputSocket, gcu);
238 }
239 }
240
241 // Create LSU connections (all connections that are an input to the LSUs)
242 for (auto& lsu : lsuList) {
243 for (auto& source : lsu->sources) {
244 Socket* outputSocket = FindOutputSocket(nav, source);
245 CreateConnection(mach, lsu->in1sock.get(), outputSocket, gcu);
246 CreateConnection(mach, lsu->in2sock.get(), outputSocket, gcu);
247 }
248 }
249
250 // Create MUL connections (all connections that are an input to the MULs)
251 for (auto& mul : mulList) {
252 for (auto& source : mul->sources) {
253 Socket* outputSocket = FindOutputSocket(nav, source);
254 CreateConnection(mach, mul->in1sock.get(), outputSocket, gcu);
255 CreateConnection(mach, mul->in2sock.get(), outputSocket, gcu);
256 }
257 }
258
259 // Create RF connections (all connections that are an input to the RFs)
260 for (auto& rf : rfList) {
261 for (auto& source : rf->sources) {
262 Socket* outputSocket = FindOutputSocket(nav, source);
263 CreateConnection(mach, rf->in1sock, outputSocket, gcu);
264 }
265 }
266
267 // IMM has no input socket so is skipped.
268 // Create GCU connections
269 for (auto& source : gcu.sources) {
270 Socket* outputSocket = FindOutputSocket(nav, source);
271 CreateConnection(mach, gcu.pcIn, outputSocket, gcu);
272 CreateConnection(mach, gcu.valIn, outputSocket, gcu);
273 }
274}
275
276/**
277 * Find the output socket corresponding to a FU name.
278 *
279 * @param nav An instance of a socketnavigator.
280 * @param source The source of which the handle to the output socket needs to
281 * be returned.
282 */
283Socket*
285 Machine::SocketNavigator nav, string source) {
286 // String manipulation to get the right format
287 source.replace(source.rfind("."), 1, "_out");
288 assert(
289 nav.hasItem(source) &&
290 "Cannot create connection, output socket not found!");
291 return nav.item(source);
292}
293
294/**
295 * Clean up the memory, deletes all FUs and busses.
296 *
297 * @param mach The TTA machine where the connections need to be made.
298 * @param aluList A list with all ALU pairs currently in the TTA model.
299 * @param lsuList A list with all LSU pairs currently in the TTA model.
300 * @param rfList A list with all RFs currently in the TTA model.
301 * @param mulList A list with all MUL pairs currently in the TTA model.
302 */
303void
305 TTAMachine::Machine& mach, std::list<BlocksALUPair*> aluList,
306 std::list<BlocksLSUPair*> lsuList, std::list<BlocksRF*> rfList,
307 std::list<BlocksIMM*> iuList, std::list<BlocksMULPair*> mulList) {
308 while (!aluList.empty()) {
309 delete aluList.front();
310 aluList.pop_front();
311 }
312 while (!lsuList.empty()) {
313 delete lsuList.front();
314 lsuList.pop_front();
315 }
316 while (!rfList.empty()) {
317 delete rfList.front();
318 rfList.pop_front();
319 }
320 while (!iuList.empty()) {
321 delete iuList.front();
322 iuList.pop_front();
323 }
324 while (!mulList.empty()) {
325 delete mulList.front();
326 mulList.pop_front();
327 }
328 // Delete busses
329 Machine::BusNavigator busNav = mach.busNavigator();
330 while (busNav.count() != 0) {
331 Bus* toDelete = busNav.item(busNav.count() - 1);
332 delete toDelete->segment(0);
333 delete toDelete;
334 }
335}
336
337/**
338 * main()
339 */
340int
341main(int argc, char* argv[]) {
342 // Define a structured way to represent the .xml architecture.
343 // Verify input arguments and open xml file.
344 try {
345 if (argc != 3)
346 throw "Invalid number of arguments, expected 2 arguments. \n";
347 } catch (const char* error) {
348 fprintf(stderr, "%s", error);
349 fprintf(
350 stdout,
351 "Expected path to .xml file with Blocks architecture and name of "
352 "output architecture (<name>.adf). \n");
353 return 1;
354 }
355
356 const string filepath = string(argv[1]);
357 const string outputFileName = string(argv[2]);
358
359 BlocksModel blocksModel(filepath);
361}
#define assert(condition)
int main(int argc, char *argv[])
static std::string outputFileName(const std::string &adfFile)
Definition CreateBEM.cc:77
std::list< std::string > sources
Definition BlocksGCU.hh:60
TTAMachine::Socket * pcIn
Definition BlocksGCU.hh:57
TTAMachine::Socket * raIn
Definition BlocksGCU.hh:55
TTAMachine::Socket * valIn
Definition BlocksGCU.hh:58
std::list< FunctionalUnit > mFunctionalUnitList
virtual Segment * segment(int index) const
Definition Bus.cc:329
virtual TCEString name() const
virtual void addSlot(const std::string &slotName, int width, ImmediateUnit &dstUnit)
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
void setLittleEndian(bool flag)
Definition Machine.hh:259
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual void addBus(Bus &bus)
Definition Machine.cc:139
void writeToADF(const std::string &adfFileName) const
Definition Machine.cc:907
Bus * parentBus() const
void setDirection(Direction direction)
Definition Socket.cc:130
void attachBus(Segment &bus)
Definition Socket.cc:166
Segment * segment(int index) const
Definition Socket.cc:401
int segmentCount() const
void BuildTTAModel(BlocksModel &blocksModel, const std::string &outputName)
void Deinitialize(TTAMachine::Machine &mach, std::list< BlocksALUPair * > aluList, std::list< BlocksLSUPair * > lsuList, std::list< BlocksRF * > rfList, std::list< BlocksIMM * > iuList, std::list< BlocksMULPair * > mulList)
void ConnectInputs(TTAMachine::Machine &mach, BlocksGCU &gcu, std::list< BlocksALUPair * > aluList, std::list< BlocksLSUPair * > lsuList, std::list< BlocksRF * > rfList, std::list< BlocksMULPair * > mulList)
TTAMachine::Socket * FindOutputSocket(TTAMachine::Machine::SocketNavigator nav, std::string source)
TTAMachine::Bus * CreateConnection(TTAMachine::Machine &mach, TTAMachine::Socket *inputSocket, TTAMachine::Socket *outputSocket, BlocksGCU &gcu)