OpenASIP 2.2
Loading...
Searching...
No Matches
UniversalMachine.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2011 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 UniversalMachine.cc
26 *
27 * Implementation of UniversalMachine class.
28 *
29 * @author Lasse Laasonen 2004 (lasse.laasonen-no.spam-tut.fi)
30 * @author Pekka Jääskeläinen 2006,2011 (pjaaskel-no.spam-cs.tut.fi)
31 * @note rating: yellow
32 */
33
34#include <string>
35
36#include "UniversalMachine.hh"
39#include "Segment.hh"
40#include "Port.hh"
42#include "Guard.hh"
43#include "ControlUnit.hh"
44#include "HWOperation.hh"
45#include "FUPort.hh"
46#include "ExecutionPipeline.hh"
47#include "OperationPool.hh"
48
49using std::string;
50using namespace TTAMachine;
51
54
55/**
56 * Constructor.
57 *
58 * Creates a complete universal machine with all the required components.
59 * Only called by instance().
60 */
65
66/**
67 * Use this to get access to an UM.
68 *
69 * Do not explicitly create new instances of UM anymore.
70 * It's deprecated and won't work in the future. *
71 */
74 if (instance_ == NULL)
76 return *instance_;
77}
78
79/**
80 * Actually constructs the resources in the universal machine.
81 */
82void
84
85 try {
86 // add bus
87 Bus* bus = new Bus(UM_BUS_NAME, 64, 32, Machine::ZERO);
88 addBus(*bus);
89
90 // add a segment to the bus
91 Segment* segment = new Segment(UM_SEGMENT_NAME, *bus);
92
93 // add sockets
94 Socket* inputSocket = new Socket(UM_INPUT_SOCKET_NAME);
95 Socket* outputSocket = new Socket(UM_OUTPUT_SOCKET_NAME);
96 addSocket(*inputSocket);
97 addSocket(*outputSocket);
98 inputSocket->attachBus(*segment);
99 inputSocket->setDirection(Socket::INPUT);
100 outputSocket->attachBus(*segment);
101 outputSocket->setDirection(Socket::OUTPUT);
102
103 // add a boolean register file
104 RegisterFile* boolean = new RegisterFile(
106 addRegisterFile(*boolean);
107 (new RFPort(UM_BOOLEAN_RF_WRITE_PORT, *boolean))->
108 attachSocket(*inputSocket);
109 (new RFPort(UM_BOOLEAN_RF_READ_PORT, *boolean))->
110 attachSocket(*outputSocket);
111
112 // add boolean register guards
113 new RegisterGuard(false, *boolean, 0, bus);
114 new RegisterGuard(true, *boolean, 0, bus);
115
116 // add universal register file for integers
119 addRegisterFile(*integerURF);
120 (new RFPort(UM_INTEGER_URF_WRITE_PORT, *integerURF))->
121 attachSocket(*inputSocket);
122 (new RFPort(UM_INTEGER_URF_READ_PORT, *integerURF))->
123 attachSocket(*outputSocket);
124
125 // add universal register file for doubles
128 addRegisterFile(*doubleURF);
129 (new RFPort(UM_DOUBLE_URF_WRITE_PORT, *doubleURF))->
130 attachSocket(*inputSocket);
131 (new RFPort(UM_DOUBLE_URF_READ_PORT, *doubleURF))->
132 attachSocket(*outputSocket);
133
134 // add a special register file for function return value
135 RegisterFile* specialRF = new RegisterFile(
137 addRegisterFile(*specialRF);
138 (new RFPort(UM_SPECIAL_RF_WRITE_PORT, *specialRF))->
139 attachSocket(*inputSocket);
140 (new RFPort(UM_SPECIAL_RF_READ_PORT, *specialRF))->
141 attachSocket(*outputSocket);
142
143 // add address space for instruction memory
144 AddressSpace* iMem = new AddressSpace(
145 UM_IMEM_NAME, 8, 0, 0xFFFFFF, *this);
146 // add address space for data memory
147 AddressSpace* dMem = new AddressSpace(
148 UM_DMEM_NAME, 8, 0, DATA_MEM_SIZE_UINT - 1, *this);
149
150 // add universal function unit
153 addFunctionUnit(*uFU);
154 uFU->setAddressSpace(dMem);
155
156 // add control unit
157 ControlUnit* cu = new ControlUnit(UM_GCU_NAME, 0, 1);
158 setGlobalControl(*cu);
159 cu->setAddressSpace(iMem);
160 HWOperation* callOp = new HWOperation("CALL", *cu);
161 HWOperation* jumpOp = new HWOperation("JUMP", *cu);
162
163 FUPort* port1 = new FUPort("port1", 32, *cu, true, true);
164 port1->attachSocket(*inputSocket);
165 FUPort* port2 = new FUPort("port2", 32, *cu, false, false);
166 port2->attachSocket(*inputSocket);
167 SpecialRegisterPort* raPort = new SpecialRegisterPort("ra", 32, *cu);
168 raPort->attachSocket(*inputSocket);
169 raPort->attachSocket(*outputSocket);
170 cu->setReturnAddressPort(*raPort);
171
172 // create pipelines and operand bindings of GCU operations
173 callOp->bindPort(1, *port1);
174 callOp->pipeline()->addPortRead(1, 0, 1);
175 jumpOp->bindPort(1, *port1);
176 jumpOp->pipeline()->addPortRead(1, 0, 1);
177 } catch (const Exception& exception) {
178 const string procName = "UniversalMachine::UniversalMachine";
180 __FILE__, __LINE__, procName, exception.errorMessage());
182 }
183
184 isBuilt_ = true;
185}
186
187
188/**
189 * Destructor.
190 */
193
194bool
196 return true;
197}
198
199/**
200 * Returns the universal function unit of the machine.
201 *
202 * @return The universal function unit.
203 */
209 UniversalFunctionUnit* ufu = dynamic_cast<UniversalFunctionUnit*>(fu);
210 assert(ufu != NULL);
211 return *ufu;
212}
213
214
215/**
216 * Returns the boolean register file of the universal machine.
217 *
218 * @return The boolean register file.
219 */
226
227
228/**
229 * Returns the unbounded register file for integers.
230 *
231 * @return The unbounded register file for integers.
232 */
238 UnboundedRegisterFile* urf = dynamic_cast<UnboundedRegisterFile*>(rf);
239 assert(urf != NULL);
240 return *urf;
241}
242
243
244/**
245 * Returns the unbounded register file for double precision floating point
246 * numbers.
247 *
248 * @return The unbounded register file for doubles.
249 */
255 UnboundedRegisterFile* urf = dynamic_cast<UnboundedRegisterFile*>(rf);
256 assert(urf != NULL);
257 return *urf;
258}
259
260
261/**
262 * Returns the special register file.
263 *
264 * @return The special register file.
265 */
272
273
274/**
275 * Returns the address space of instruction memory.
276 *
277 * @return The address space of instruction memory.
278 */
285
286
287/**
288 * Returns the address space of data memory.
289 *
290 * @return The address space of data memory.
291 */
298
299
300/**
301 * Returns the only transport bus of universal machine.
302 *
303 * @return The bus.
304 */
305Bus&
307 BusNavigator busNav = busNavigator();
308 assert(busNav.hasItem(UM_BUS_NAME));
309 return *busNav.item(UM_BUS_NAME);
310}
311
312
313/**
314 * Adds a bus to the machine.
315 *
316 * Aborts the program if tried to add a bus after the UniversalMachine is
317 * constructed. DO NOT CALL THIS METHOD.
318 *
319 * @param bus Bus being added.
320 * @exception ComponentAlreadyExists If a bus by the same name already exists
321 * in the machine.
322 */
323void
325 if (!isBuilt_) {
326 Machine::addBus(bus);
327 } else {
328 const string procName = "UniversalMachine::addBus";
329 const string errorMsg = "Tried to add a bus to UniversalMachine!";
330 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
332 }
333}
334
335/**
336 * Adds a socket to the machine.
337 *
338 * Aborts the program if tried to add a socket after the UniversalMachine
339 * is constructed. DO NOT CALL THIS METHOD.
340 *
341 * @param socket The socket being added.
342 * @exception ComponentAlreadyExists If a socket by the same name already
343 * exists in the machine.
344 */
345void
347 if (!isBuilt_) {
348 Machine::addSocket(socket);
349 } else {
350 const string procName = "UniversalMachine::addSocket";
351 const string errorMsg = "Tried to add a socket to UniversalMachine!";
352 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
354 }
355}
356
357/**
358 * Adds a function unit to the machine. Aborts the program if tried to
359 * add a function unit after the UniversalMachine is constructed. DO
360 * NOT CALL THIS METHOD.
361 *
362 * @param unit The function unit being added.
363 * @exception ComponentAlreadyExists If a function unit by the same name
364 * already exists in the machine.
365 */
366void
368 if (!isBuilt_) {
370 } else {
371 const string procName = "UniversalMachine::addFunctionUnit";
372 const string errorMsg =
373 "Tried to add a function unit to UniversalMachine!";
374 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
376 }
377}
378
379/**
380 * Aborts the program. It is not allowed to add immediate units to
381 * UniversalMachine. DO NOT CALL THIS METHOD.
382 *
383 * @param unit Never used.
384 * @exception ComponentAlreadyExists Never thrown.
385 */
386void
388 const string procName = "UniversalMachine::addImmediateUnit";
389 const string errorMsg =
390 "Tried to add an immediate unit to UniversalMachine!";
391 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
393}
394
395/**
396 * Adds a register file to the machine. Aborts the program if tried to
397 * add a register file after the UniversalMachine is constructed. DO NOT CALL
398 * THIS METHOD.
399 *
400 * @param unit The register file being added.
401 * @exception ComponentAlreadyExists If a register file by the same name
402 * already exists in the machine.
403 */
404void
406 if (!isBuilt_) {
408 } else {
409 const string procName = "UniversalMachine::addRegisterFile";
410 const string errorMsg =
411 "Tried to add a register file to UniversalMachine!";
412 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
414 }
415}
416
417/**
418 * Adds an address space to the machine. Aborts the program if tried
419 * to add an address space after the UniversalMachine is
420 * constructed. DO NOT CALL THIS METHOD.
421 *
422 * @param as The address space being added.
423 * @exception ComponentAlreadyExists If an address space by the same name
424 * already exists in the machine.
425 */
426void
428 if (!isBuilt_) {
430 } else {
431 const string procName = "UniversalMachine::addAddressSpace";
432 const string errorMsg =
433 "Tried to add an address space to UniversalMachine!";
434 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
436 }
437}
438
439/**
440 * Aborts the program. UniversalMachine can not contain bridges. DO NOT CALL
441 * THIS METHOD.
442 *
443 * @param bridge Never used.
444 * @exception ComponentAlreadyExists Never thrown.
445 */
446void
448 const string procName = "UniversalMachine::addBridge";
449 const string errorMsg = "Tried to add a bridge to UniversalMachine!";
450 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
452}
453
454/**
455 * Aborts the program. UniversalMachine can not contain instruction
456 * templates. DO NOT CALL THIS METHOD!
457 *
458 * @param iTemp Never used.
459 * @exception ComponentAlreadyExists Never thrown.
460 */
461void
463 const string procName = "UniversalMachine::addInstructionTemplate";
464 const string errorMsg =
465 "Tried to add an instruction template to UniversalMachine!";
466 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
468}
469
470/**
471 * Sets the control unit of the machine. Aborts the program if tried to set
472 * the control unit after the UniversalMachine is constructed. DO NOT CALL
473 * THIS METHOD!
474 *
475 * @param unit The control unit to be set.
476 * @exception ComponentAlreadyExists Never thrown.
477 */
478void
480 if (!isBuilt_) {
482 } else {
483 const string procName = "UniversalMachine::setGlobalControl";
484 const string errorMsg =
485 "Tried to set control unit to UniversalMachine!";
486 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
488 }
489}
490
491/**
492 * Aborts the program. It is not allowed to remove buses from
493 * UniversalMachine. DO NOT CALL THIS METHOD!
494 *
495 * @param bus Never used.
496 * @exception InstanceNotFound Never thrown.
497 */
498void
500 const string procName = "UniversalMachine::removeBus";
501 const string errorMsg = "Tried to remove bus from UniversalMachine!";
502 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
504}
505
506/**
507 * Aborts the program. It is not allowed to remove sockets from
508 * UniversalMachine. DO NOT CALL THIS METHOD!
509 *
510 * @param socket Never used.
511 * @exception InstanceNotFound Never thrown.
512 */
513void
515 const string procName = "UniversalMachine::removeSocket";
516 const string errorMsg = "Tried to remove socket from UniversalMachine!";
517 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
519}
520
521/**
522 * Aborts the program. It is not allowed to remove function units from
523 * UniversalMachine. DO NOT CALL THIS METHOD!
524 *
525 * @param unit Never used.
526 * @exception InstanceNotFound Never thrown.
527 */
528void
530 const string procName = "UniversalMachine::removeFunctionUnit";
531 const string errorMsg =
532 "Tried to remove function unit from UniversalMachine!";
533 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
535}
536
537/**
538 * Aborts the program. It is not allowed to remove register files from
539 * UniversalMachine. DO NOT CALL THIS METHOD!
540 *
541 * @param unit Never used.
542 * @exception InstanceNotFound Never thrown.
543 */
544void
546 const string procName = "UniversalMachine::removeRegisterFile";
547 const string errorMsg =
548 "Tried to remove register file from UniversalMachine!";
549 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
551}
552
553/**
554 * Aborts the program. It is not allowed to delete address spaces from
555 * UniversalMachine. DO NOT CALL THIS METHOD!
556 *
557 * @param as Never used.
558 * @exception InstanceNotFound Never thrown.
559 */
560void
562 const string procName = "UniversalMachine::deleteAddressSpace";
563 const string errorMsg =
564 "Tried to delete address space from UniversalMachine!";
565 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
567}
568
569/**
570 * Aborts the program. It is not allowed to unset global control unit from
571 * UniversalMachine. DO NOT CALL THIS METHOD!
572 */
573void
575
576 const string procName = "UniversalMachine::unsetglobalControl";
577 const string errorMsg =
578 "Tried to unset global control unit from UniversalMachine!";
579 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
581}
582
583
584/**
585 * Redefinement of this method prevents loading the state of
586 * UniversalMachine from an ObjectState tree. Aborts the program if
587 * this method is called. DO NOT CALL THIS METHOD.
588 *
589 * @param state ObjectState instance.
590 * @exception ObjectStateLoadingException Never thrown.
591 */
592void
594 const string procName = "UniversalMachine::loadState";
595 const string errorMsg =
596 "Tried to load UniversalMachine from an ObjectState tree!";
597 Application::writeToErrorLog(__FILE__, __LINE__, procName, errorMsg);
599}
#define assert(condition)
find Finds info of the inner loops in the false
const unsigned int DATA_MEM_SIZE_UINT
#define UM_BUS_NAME
Machine component names reserved for the universal machine.
#define UM_BOOLEAN_RF_READ_PORT
#define UM_SPECIAL_RF_WRITE_PORT
#define UM_INTEGER_URF_READ_PORT
#define UM_DOUBLE_URF_NAME
#define UM_SEGMENT_NAME
#define UM_INTEGER_URF_WRITE_PORT
#define UM_DOUBLE_URF_WRITE_PORT
#define UM_UNIVERSAL_FU_NAME
#define UM_OUTPUT_SOCKET_NAME
#define UM_DMEM_NAME
#define UM_GCU_NAME
#define UM_IMEM_NAME
#define UM_BOOLEAN_RF_WRITE_PORT
#define UM_DOUBLE_URF_READ_PORT
#define DATA_MEMORY_SIZE
#define UM_BOOLEAN_RF_NAME
#define UM_INPUT_SOCKET_NAME
#define UM_INTEGER_URF_NAME
#define UM_SPECIAL_RF_NAME
#define UM_SPECIAL_RF_READ_PORT
static void abortProgram() __attribute__((noreturn))
static void writeToErrorLog(const std::string fileName, const int lineNumber, const std::string functionName, const std::string message, const int neededVerbosity=0)
std::string errorMessage() const
Definition Exception.cc:123
void setReturnAddressPort(const SpecialRegisterPort &port)
void addPortRead(int operand, int start, int duration)
virtual void setAddressSpace(AddressSpace *as)
ExecutionPipeline * pipeline() const
virtual void bindPort(int operand, const FUPort &port)
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual void addFunctionUnit(FunctionUnit &unit)
Definition Machine.cc:202
virtual AddressSpaceNavigator addressSpaceNavigator() const
Definition Machine.cc:392
virtual void addBus(Bus &bus)
Definition Machine.cc:139
@ ZERO
Zero extension.
Definition Machine.hh:81
virtual void addRegisterFile(RegisterFile &unit)
Definition Machine.cc:236
virtual void setGlobalControl(ControlUnit &unit)
Definition Machine.cc:317
virtual void addAddressSpace(AddressSpace &as)
Definition Machine.cc:248
virtual void addSocket(Socket &socket)
Definition Machine.cc:157
virtual void attachSocket(Socket &socket)
Definition Port.cc:191
@ NORMAL
Used for general register allocation.
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
void attachBus(Segment &bus)
Definition Socket.cc:166
virtual void addSocket(TTAMachine::Socket &socket)
virtual void addRegisterFile(TTAMachine::RegisterFile &unit)
virtual void addBridge(TTAMachine::Bridge &bridge)
TTAMachine::AddressSpace & dataAddressSpace() const
virtual void removeSocket(TTAMachine::Socket &socket)
virtual void removeBus(TTAMachine::Bus &bus)
virtual void addAddressSpace(TTAMachine::AddressSpace &as)
virtual void unsetGlobalControl()
TTAMachine::AddressSpace & instructionAddressSpace() const
virtual void addBus(TTAMachine::Bus &bus)
TTAMachine::RegisterFile & booleanRegisterFile() const
OperationPool opPool
The operation pool instance to use for finding operations.
virtual void addFunctionUnit(TTAMachine::FunctionUnit &unit)
virtual void removeFunctionUnit(TTAMachine::FunctionUnit &unit)
virtual void addInstructionTemplate(TTAMachine::InstructionTemplate &iTemp)
static UniversalMachine & instance()
TTAMachine::RegisterFile & specialRegisterFile() const
UniversalFunctionUnit & universalFunctionUnit() const
virtual void removeRegisterFile(TTAMachine::RegisterFile &unit)
UnboundedRegisterFile & integerRegisterFile() const
TTAMachine::Bus & universalBus() const
bool isBuilt_
Indicates whether the UniversalMachine is built completely.
virtual void deleteAddressSpace(TTAMachine::AddressSpace &as)
virtual bool isUniversalMachine() const
static UniversalMachine * instance_
The singleton instance. Use this instance everywhere. Creating multiple instances of UM is deprecated...
virtual void setGlobalControl(TTAMachine::ControlUnit &unit)
virtual void addImmediateUnit(TTAMachine::ImmediateUnit &unit)
UnboundedRegisterFile & doubleRegisterFile() const
virtual void loadState(const ObjectState *state)