OpenASIP 2.2
Loading...
Searching...
No Matches
SimProgramBuilder.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2010 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 SimProgramBuilder.cc
26 *
27 * Definition of SimProgramBuilder class.
28 *
29 * @author Jussi Nykänen 2005 (nykanen-no.spam-cs.tut.fi)
30 * @author Pekka Jääskeläinen 2005, 2010
31 * @note rating: red
32 */
33
34#include "boost/format.hpp"
35
36#include "SimProgramBuilder.hh"
37
38#include "Instruction.hh"
39#include "NullInstruction.hh"
40#include "Immediate.hh"
41#include "Terminal.hh"
42#include "Move.hh"
43#include "MoveGuard.hh"
44#include "Address.hh"
45#include "FUPort.hh"
46#include "StateLocator.hh"
47#include "InstructionMemory.hh"
49#include "ExecutableMove.hh"
54#include "SimulatorToolbox.hh"
56#include "MachineState.hh"
58#include "RegisterFileState.hh"
59#include "PortState.hh"
60#include "BusState.hh"
61#include "StringTools.hh"
62#include "Operation.hh"
63#include "Port.hh"
64#include "BaseFUPort.hh"
65#include "Application.hh"
66#include "Exception.hh"
67#include "Guard.hh"
68#include "ControlUnit.hh"
69#include "UniversalMachine.hh"
70#include "TerminalImmediate.hh"
71#include "GuardState.hh"
72#include "Procedure.hh"
73#include "POMDisassembler.hh"
74#include "TCEString.hh"
75#include "MathTools.hh"
76#include "Program.hh"
77
78using namespace TTAMachine;
79using namespace TTAProgram;
80
81// This should be defined in case control flow operation moves should be
82// visible in bus. This is not the case in real hardware (verify?). This
83// define is here to be able to compare TCE bustrace with MOVE bustrace
84// easily (which makes the moves visible in transport bus).
85#define GCU_OPERATION_MOVES_VISIBLE_IN_BUS true
86
87/**
88 * Constructor.
89 */
91 sequentialProgram_(false) {
92}
93
94/**
95 * Destructor.
96 */
99
100/**
101 * Helper method for processing such terminals that can be both source and
102 * destination in the move.
103 *
104 * @param theTerminal The terminal to process.
105 * @param state MachineState to fetch the state objects from.
106 * @return The StateData object created from the terminal.
107 * @exception IllegalProgram When the terminal is referring to illegal
108 * machine state or the terminal itself is illegal.
109 */
112 const Terminal& theTerminal, MachineState& state) {
113 try {
114 if (theTerminal.isGPR()) {
115
117 theTerminal.registerFile().name());
118 if (&unit == &NullRegisterFileState::instance()) {
119 throw IllegalProgram(
120 __FILE__, __LINE__, __func__,
123 }
124 return &unit.registerState(theTerminal.index());
125
126 } else if (theTerminal.isFUPort()) {
127
128 const BaseFUPort* thePort =
129 dynamic_cast<const BaseFUPort*>(&theTerminal.port());
130
131 if (thePort == NULL)
132 throw IllegalProgram(
133 __FILE__, __LINE__, __func__,
134 "Could not find the FU port.");
135
136 std::string operationString = "";
137 // if this is an opcode-setting port, find the
138 // OpcodeSettingVirtualInputPort instead of a real port
139
140 if (thePort->isOpcodeSetting()) {
141
142 if (!theTerminal.isOpcodeSetting()) {
143 throw IllegalProgram(
144 __FILE__, __LINE__, __func__,
147 str());
148 }
149 operationString =
151 std::string(".") + theTerminal.operation().name());
152 }
153
154 PortState& port = state.portState(
155 thePort->name() + operationString,
156 theTerminal.port().parentUnit()->name());
157
158 if (&port == &NullPortState::instance()) {
159 throw IllegalProgram(
160 __FILE__, __LINE__, __func__,
163 str());
164 }
165
166 return &port;
167
168 } else {
169 abortWithError("Illegal terminal!");
170 }
171 } catch (const OutOfRange& e) {
173 } catch (const WrongSubclass&) {
174 abortWithError("Wrong sub class!");
175 }
176
177 std::string errorMsg =
180 throw IllegalProgram(__FILE__, __LINE__, __func__, errorMsg);
181 return NULL;
182}
183
184/**
185 * Helper method for processing source terminals.
186 *
187 * @param theTerminal The terminal to process.
188 * @param state MachineState to fetch the state objects from.
189 * @return The StateData object created from the terminal.
190 * @exception IllegalProgram When the terminal is referring to illegal
191 * machine state or the terminal itself is illegal.
192 */
195 const Terminal& theTerminal, MachineState& state) {
196 try {
197 if (theTerminal.isImmediateRegister()) {
198
200 theTerminal.immediateUnit().name());
201 if (&unit == &NullLongImmediateUnitState::instance()) {
202 throw IllegalProgram(
203 __FILE__, __LINE__, __func__,
206 }
207 return &unit.immediateRegister(theTerminal.index());
208 } else {
209 return processBidirTerminal(theTerminal, state);
210 }
211 } catch (const OutOfRange&) {
212 } catch (const WrongSubclass&) {
213 }
214 throw IllegalProgram(
215 __FILE__, __LINE__, __func__,
218 return NULL;
219}
220
221/**
222 * Helper method for finding the state object the given guard targets.
223 *
224 * @param guard The guard object from machine object model.
225 * @param state The machine state model.
226 * @return The state object represeting the current value of the guard.
227 * @exception IllegalProgram In case a state model for given guard cannot be
228 * found.
229 */
230const ReadableState&
232 const TTAMachine::Guard& guard, MachineState& state) {
233 try {
234 GuardState& guardModel = state.guardState(guard);
235 if (&guardModel != &NullGuardState::instance())
236 return guardModel;
237 } catch (const Exception& e) {
238 }
239
240 throw IllegalProgram(
241 __FILE__, __LINE__, __func__,
242 "Program references an illegal guard.");
243
244 // should never return from here
246}
247
248/**
249 * Processes a POM Move and produces an ExecutableMove.
250 *
251 * @param move The move to process.
252 * @param state The MachineState the program refers to.
253 * @return The processed move.
254 * @exception IllegalProgram If the input move was illegal.
255 */
258 ReadableState* source = NULL;
259 InlineImmediateValue* immediateSource = NULL;
260
261 if (move.source().isImmediate()) {
262 // extend the immediate so we don't have to extend it
263 // during runtime every time the move is simulated
264 immediateSource = new InlineImmediateValue(move.bus().width());
265
266 if (move.isControlFlowMove()) {
267 int targetWidth = move.destination().port().width();
268 if (!move.bus().signExtends()) {
269 ULongWord immediate =
270 move.source().value().uLongWordValue();
271 if (targetWidth < MathTools::requiredBits(immediate)) {
272 TCEString errorMsg =
273 (boost::format(
274 "Immediate of jump '%s' gets clipped due to the target "
275 "port being too narrow. Wrong execution would occur.")
276 % move.toString()).str();
277 throw IllegalProgram(
278 __FILE__, __LINE__, __func__, errorMsg);
279 }
280 } else {
281 SLongWord immediate =
282 move.source().value().sLongWordValue();
283 if (targetWidth < MathTools::requiredBitsSigned(immediate)) {
284 TCEString errorMsg =
285 (boost::format(
286 "Immediate of jump '%s' gets clipped due to the target "
287 "port being too narrow. Wrong execution would occur.")
288 % move.toString()).str();
289 throw IllegalProgram(
290 __FILE__, __LINE__, __func__, errorMsg);
291 }
292 }
293 }
294
295 SimValue val(move.bus().width());
296 val = move.source().value();
297 if (move.bus().signExtends()) {
298 val.signExtendTo(move.bus().immediateWidth());
299 } else {
300 val.zeroExtendTo(move.bus().immediateWidth());
301 }
302 immediateSource->setValue(val);
303 } else {
304 source = processSourceTerminal(move.source(), state);
305 }
306
307 BusState& bus = state.busState(move.bus().name());
308 if (&bus == &NullBusState::instance()) {
309 throw IllegalProgram(
310 __FILE__, __LINE__, __func__,
313 }
314
315 WritableState& destination =
316 *processBidirTerminal(move.destination(), state);
317
318 // in case this is a sequential move, or a move that executes a
319 // control flow operation with immediate or control unit port source (RA)
320 // it does not utilize any bus
321 bool buslessMove = sequentialProgram_;
323 if (move.destination().isFUPort()) {
324 if (dynamic_cast<const TTAMachine::ControlUnit*>(
325 &move.destination().functionUnit())) {
326 if (move.source().isImmediate() ||
327 (move.source().isFUPort() &&
328 dynamic_cast<const TTAMachine::ControlUnit*>(
329 &move.source().functionUnit()) != NULL)) {
330 buslessMove = true;
331 }
332 }
333 }
334 }
335
336 // handle guards
337 if (move.isUnconditional()) {
338 // create a guardless execmove
339 if (move.source().isImmediate()) {
340 assert(immediateSource != NULL);
341 if (buslessMove) {
342 return new BuslessExecutableMove(immediateSource, destination);
343 } else {
344 return new ExecutableMove(immediateSource, bus, destination);
345 }
346 } else {
347 assert(source != NULL);
348 if (buslessMove) {
349 return new BuslessExecutableMove(*source, destination);
350 } else {
351 return new ExecutableMove(*source, bus, destination);
352 }
353 }
354 } else {
355 // create a guarded move
356 MoveGuard& guard = move.guard();
357
358 if (move.source().isImmediate()) {
359 assert(immediateSource != NULL);
360 if (buslessMove) {
361 return new BuslessExecutableMove(
362 immediateSource, destination,
363 findGuardModel(guard.guard(), state),
364 guard.guard().isInverted());
365 } else {
366 return new ExecutableMove(
367 immediateSource, bus, destination,
368 findGuardModel(guard.guard(), state),
369 guard.guard().isInverted());
370 }
371 } else {
372 assert(source != NULL);
373 if (buslessMove) {
374 return new BuslessExecutableMove(
375 *source, destination,
376 findGuardModel(guard.guard(), state),
377 guard.guard().isInverted());
378 } else {
379 return new ExecutableMove(
380 *source, bus, destination,
381 findGuardModel(guard.guard(), state),
382 guard.guard().isInverted());
383 }
384 }
385 }
386
387 // should never end up here
388 assert(false);
389
390 return NULL;
391}
392
393/**
394 * Processes a POM Instruction and produces an ExecutableInstruction.
395 *
396 * @param instruction The instruction to process.
397 * @param state The MachineState the program refers to.
398 * @return The processed instruction.
399 * @exception IllegalProgram If the input instruction was illegal.
400 */
403 const Instruction& instruction, MachineState& state) {
404 ExecutableInstruction* processedInstruction = new ExecutableInstruction();
405
406 // process long immediates
407 for (int i = 0; i < instruction.immediateCount(); ++i) {
409
410 // first fetch the LongImmediateUnitState, then fetch the
411 // LongImmediateRegisterState from it, because there is no such
412 // object in MOM as LongImmediateRegister, nor any single registers
413 LongImmediateRegisterState* destination = NULL;
414 try {
416 instruction.immediate(i).destination().immediateUnit().name());
417
418 destination = &targetUnit.immediateRegister(
419 instruction.immediate(i).destination().index());
420
421 if (&targetUnit == &NullLongImmediateUnitState::instance()) {
422 throw IllegalProgram(
423 __FILE__, __LINE__, __func__,
426 }
427 } catch (const IllegalParameters&) {
428 throw IllegalProgram(
429 __FILE__, __LINE__, __func__,
432 } catch (const OutOfRange&) {
433 throw IllegalProgram(
434 __FILE__, __LINE__, __func__,
437 }
438
439 processedInstruction->addLongImmediateUpdateAction(
440 new LongImmUpdateAction(instruction.immediate(i).value().value(),
441 *destination));
442 }
443
444 // process all the moves in the instruction
445 for (int j = 0; j < instruction.moveCount(); ++j) {
446 try {
447 processedInstruction->addExecutableMove(
448 processMove(instruction.move(j), state));
449 } catch (const IllegalProgram& e) {
451 e.fileName(), e.lineNum(), e.procedureName(),
452 e.errorMessage() + " Illegal move: " +
453 POMDisassembler::disassemble(instruction.move(j)));
454 throw ip;
455 }
456 }
457 return processedInstruction;
458}
459
460/**
461 * Builds the model of instruction memory ready to be simulated.
462 *
463 * @param prog Program from which the contents of instruction memory is built.
464 * @param state The MachineState the program refers to.
465 * @return The created instruction memory, owned by client.
466 * @exception IllegalProgram If building fails for some reason. The exception
467 * message describes the reason. The message can be
468 * displayed in user interfaces as it's generated by
469 * SimulatorTextGenerator.
470 */
474 (dynamic_cast<const UniversalMachine*>(
475 &prog.targetProcessor()) != NULL);
476 const Address& programStartAddress = prog.startAddress();
477
478 InstructionMemory* memory =
479 new InstructionMemory(programStartAddress.location());
480
481 const TTAProgram::Instruction* currentInstruction = NULL;
482 try {
483
484 for (int procIndex = 0; procIndex < prog.procedureCount();
485 ++procIndex) {
486 const Procedure& proc = prog.procedureAtIndex(procIndex);
487 for (int instrIndex = 0; instrIndex < proc.instructionCount();
488 ++instrIndex) {
489 currentInstruction =
490 &proc.instructionAtIndex(instrIndex);
491 ExecutableInstruction* processedInstruction =
492 processInstruction(*currentInstruction, state);
493
494 if (currentInstruction->size() > 0) {
496 currentInstruction->address().location(),
497 processedInstruction);
498 } else {
500 currentInstruction->address().location(),
501 processedInstruction);
502 }
503 }
504 }
505 } catch (const Exception& e) {
506 throw IllegalProgram(
507 __FILE__, __LINE__, __func__,
508 (boost::format("Error while processing instruction %d "
509 "(with moves %s): %s")
510 % currentInstruction->address().location()
511 % POMDisassembler::disassemble(*currentInstruction)
512 % e.errorMessage()).str());
513 }
514
515 return memory;
516}
#define __func__
#define abortWithError(message)
#define assert(condition)
unsigned long ULongWord
Definition BaseType.hh:51
long SLongWord
Definition BaseType.hh:52
RegisterState InlineImmediateValue
RegisterState can be used as a storage for inline immediates.
find Finds info of the inner loops in the false
#define GCU_OPERATION_MOVES_VISIBLE_IN_BUS
std::string fileName() const
std::string errorMessage() const
Definition Exception.cc:123
std::string procedureName() const
int lineNum() const
void addExecutableMove(ExecutableMove *move)
void addLongImmediateUpdateAction(LongImmUpdateAction *action)
void addImplicitExecutableInstruction(InstructionAddress addr, ExecutableInstruction *instruction)
void addExecutableInstruction(InstructionAddress addr, ExecutableInstruction *instruction)
virtual LongImmediateRegisterState & immediateRegister(int i)
PortState & portState(const std::string &portName, const std::string &fuName)
LongImmediateUnitState & longImmediateUnitState(const std::string &name)
GuardState & guardState(const TTAMachine::Guard &guard)
RegisterFileState & registerFileState(const std::string &name)
BusState & busState(const std::string &name)
static int requiredBits(unsigned long int number)
static int requiredBitsSigned(SLongWord number)
static NullBusState & instance()
Definition BusState.cc:112
static NullGuardState & instance()
static NullLongImmediateUnitState & instance()
static NullPortState & instance()
Definition PortState.cc:96
static NullRegisterFileState & instance()
virtual TCEString name() const
Definition Operation.cc:93
static std::string disassemble(const TTAProgram::Move &move)
virtual RegisterState & registerState(int index)
virtual void setValue(const SimValue &value)
ExecutableMove * processMove(const TTAProgram::Move &move, MachineState &state)
const ReadableState & findGuardModel(const TTAMachine::Guard &guard, MachineState &state)
ExecutableInstruction * processInstruction(const TTAProgram::Instruction &instruction, MachineState &state)
StateData * processBidirTerminal(const TTAProgram::Terminal &theTerminal, MachineState &state)
StateData * processSourceTerminal(const TTAProgram::Terminal &theTerminal, MachineState &state)
InstructionMemory * build(const TTAProgram::Program &prog, MachineState &state)
void zeroExtendTo(int bitWidth)
Definition SimValue.cc:1567
ULongWord uLongWordValue() const
Definition SimValue.cc:1027
void signExtendTo(int bitWidth)
Definition SimValue.cc:1531
SLongWord sLongWordValue() const
Definition SimValue.cc:997
static SimulatorTextGenerator & textGenerator()
static std::string stringToLower(const std::string &source)
virtual bool isOpcodeSetting() const =0
int width() const
Definition Bus.cc:149
int immediateWidth() const
Definition Bus.cc:160
bool signExtends() const
Definition Bus.cc:171
virtual TCEString name() const
virtual bool isInverted() const
virtual int width() const =0
Unit * parentUnit() const
virtual std::string name() const
Definition Port.cc:141
InstructionAddress location() const
virtual int instructionCount() const
virtual Instruction & instructionAtIndex(int index) const
TerminalImmediate & value() const
Definition Immediate.cc:103
const Terminal & destination() const
Definition Immediate.cc:92
Move & move(int i) const
Address address() const
Immediate & immediate(int i) const
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
MoveGuard & guard() const
Definition Move.cc:345
bool isControlFlowMove() const
Definition Move.cc:233
bool isUnconditional() const
Definition Move.cc:154
std::string toString() const
Definition Move.cc:436
Terminal & source() const
Definition Move.cc:302
Terminal & destination() const
Definition Move.cc:323
const TTAMachine::Bus & bus() const
Definition Move.cc:373
const Procedure & procedureAtIndex(int index) const
Definition Program.cc:508
Address startAddress() const
Definition Program.cc:286
TTAMachine::Machine & targetProcessor() const
Definition Program.cc:202
int procedureCount() const
Definition Program.cc:610
virtual SimValue value() const
virtual SimValue value() const
Definition Terminal.cc:178
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition Terminal.cc:251
virtual int index() const
Definition Terminal.cc:274
virtual bool isOpcodeSetting() const
Definition Terminal.cc:285
virtual Operation & operation() const
Definition Terminal.cc:319
virtual bool isGPR() const
Definition Terminal.cc:107
virtual bool isImmediateRegister() const
Definition Terminal.cc:97
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
virtual bool isImmediate() const
Definition Terminal.cc:63
virtual const TTAMachine::ImmediateUnit & immediateUnit() const
Definition Terminal.cc:240
virtual const TTAMachine::RegisterFile & registerFile() const
Definition Terminal.cc:225
virtual bool isFUPort() const
Definition Terminal.cc:118
virtual boost::format text(int textId)
@ TXT_ILLEGAL_PROGRAM_IU_STATE_NOT_FOUND
Text of the exception thrown when Immediate Unit state could not be found and there is instruction re...
@ TXT_ILLEGAL_PROGRAM_BUS_STATE_NOT_FOUND
Text of the exception thrown when FUPortState could not be found and there is instruction referring t...
@ TXT_ILLEGAL_PROGRAM_OPCODE_NOT_FOUND
Text of the exception thrown when a port to be written is an opcode setting port and no opcode is fou...
@ TXT_ILLEGAL_PROGRAM_UNKNOWN_MOVE_TERMINAL_TYPE
Text of the exception thrown when the terminal type of a move is not regocnized.
@ TXT_ILLEGAL_PROGRAM_PORT_STATE_NOT_FOUND
Text of the exception thrown when FUPortState could not be found and there is instruction referring t...
@ TXT_ILLEGAL_PROGRAM_RF_STATE_NOT_FOUND
Text of the exception thrown when RegisterFileState could not be found and there is instruction refer...