OpenASIP 2.2
Loading...
Searching...
No Matches
CompiledSimulation.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 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 CompiledSimulation.cc
26 *
27 * Definition of CompiledSimulation class.
28 *
29 * @author Viljami Korhonen 2007 (viljami.korhonen-no.spam-tut.fi)
30 * @author Pekka Jääskeläinen 2009 (pekka.jaaskelainen-no.spam-tut.fi)
31 * @note rating: red
32 */
33
34#include <string>
35#include "CompiledSimulation.hh"
36#include "Machine.hh"
37#include "Instruction.hh"
38#include "SimulatorFrontend.hh"
42#include "DirectAccessMemory.hh"
44#include "ControlUnit.hh"
47#include "PluginTools.hh"
48#include "FileSystem.hh"
49#include "Program.hh"
50#include "Move.hh"
51#include "MemorySystem.hh"
52#include "Conversion.hh"
53
54using namespace TTAMachine;
55using namespace TTAProgram;
56
58 std::numeric_limits<ClockCycleCount>::max();
59
60/**
61 * The constructor
62 *
63 * Grabs all shared data from machine and program and saves them for
64 * easy access for later usage.
65 *
66 * @param machine The simulated machine
67 * @param program The simulated program
68 * @param frontend The simulation frontend
69 * @param memorySystem The memory system
70 *
71 */
74 InstructionAddress entryAddress,
75 InstructionAddress lastInstruction,
76 SimulatorFrontend& frontend,
77 CompiledSimController& controller,
78 MemorySystem& memorySystem,
79 bool dynamicCompilation,
80 ProcedureBBRelations& procedureBBRelations) :
81 cycleCount_(0),
82 basicBlockCount_(0),
83 jumpTarget_(entryAddress),
84 programCounter_(entryAddress),
85 lastExecutedInstruction_(0),
86 cyclesToSimulate_(MAX_CYCLES),
87 stopRequested_(false),
88 isFinished_(false),
89 conflictDetected_(false),
90 dynamicCompilation_(dynamicCompilation),
91 procedureBBRelations_(procedureBBRelations),
92 machine_(machine),
93 entryAddress_(entryAddress),
94 lastInstruction_(lastInstruction), pimpl_(new CompiledSimulationPimpl()) {
97 pimpl_->controller_ = &controller;
98
99 // Allocate memory for calculating move and basic block execution counts
100 int moveCount = pimpl_->controller_->program().moveCount();
101 moveExecCounts_ = new ClockCycleCount[moveCount];
102 for (int i = 0; i < moveCount; ++i) {
103 moveExecCounts_[i] = 0;
104 }
105
106 int bbCount = lastInstruction - entryAddress + 1;
107 bbExecCounts_ = new ClockCycleCount[bbCount];
108 for (int i = 0; i < bbCount; ++i) {
109 bbExecCounts_[i] = 0;
110 }
111
112 // Find program exit points
115}
116
117/**
118 * The destructor. Frees private implementation
119 */
121 delete[] bbExecCounts_;
122 bbExecCounts_ = NULL;
123
124 delete[] moveExecCounts_;
125 moveExecCounts_ = NULL;
126
127 delete pimpl_;
128 pimpl_ = NULL;
129
130}
131
132/**
133 * Lets the simulator frontend handle a single cycle end.
134 *
135 * Used for example when generating traces.
136 */
137void
144
145/**
146 * Advance the simulation by a given amout of cycles.
147 *
148 * @note Advances only at an accuracy of a one basic block!
149 *
150 * @param count The number of cycles the simulation should be advanced at least
151 * @exception SimulationExecutionError If a runtime error occurs in
152 * the simulated program.
153 */
154void
156 cyclesToSimulate_ = cycleCount_ + static_cast<ClockCycleCount>(count);
157 stopRequested_ = false;
158
159 while (!stopRequested_ && !isFinished_) {
161 }
162}
163
164/**
165 * Throws an exception since this feature is not supported yet!
166 *
167 * @exception SimulationExecutionError always thrown
168 */
169void
171
172 std::string msg(
173 "Command nexti not yet supported in the compiled simulation!");
174 throw SimulationExecutionError(__FILE__, __LINE__, __FUNCTION__, msg);
175
176 if (count) {}
177}
178
179/**
180 * Runs the simulation until it is finished or an exception occurs
181 *
182 * @note Advances only at an accuracy of a one basic block!
183 *
184 * @param address An address the simulation is allowed to stop after
185 * @exception SimulationExecutionError If a runtime error occurs in
186 * the simulated program.
187 */
188void
196
197/**
198 * Advance the simulation until a given address is reached
199 *
200 * @note Advances only at an accuracy of a one basic block!
201 *
202 * @param address An address the simulation is allowed to stop after
203 * @exception SimulationExecutionError If a runtime error occurs in
204 * the simulated program.
205 */
206void
209 stopRequested_ = false;
210 while ((!stopRequested_ && !isFinished_ &&
211 (jumpTarget_ != address || cycleCount_ == 0))) {
213 }
214}
215
216/**
217 * Returns the value of the current PC
218 *
219 * @return the value of the current PC
220 *
221 */
226
227/**
228 * Returns address of the last executed instruction
229 *
230 * @return Address of the last executed instruction
231 */
236
237/**
238 * Returns the current cycle count
239 *
240 * @return the current cycle count
241 */
245
246/**
247 * Returns the value of the selected register
248 *
249 * @param rfName The name of the register file
250 * @param registerIndex index of the register in the RF
251 * @return A SimValue containing the present register value
252 * @exception InstanceNotFound If the RF cannot be found
253 */
255CompiledSimulation::registerFileValue(const char* rfName, int registerIndex) {
256
259 std::string registerFile = symbolGen.registerSymbol(rf, registerIndex);
260
261 CompiledSimulationPimpl::Symbols::const_iterator rfIterator =
262 pimpl_->symbols_.find(registerFile);
263 if (rfIterator != pimpl_->symbols_.end()) {
264 return *(rfIterator->second);
265 } else {
266 throw InstanceNotFound(__FILE__, __LINE__, __func__,
267 "Register file " + std::string(rfName) + " not found.");
268 }
269}
270
271/**
272 * Returns the value of the selected immediate unit register
273 *
274 * @param iuName The name of the immediate unit
275 * @param index Index of the immediate register
276 * @return A SimValue containing the present immediate register value
277 * @exception InstanceNotFound If the immediate unit cannot be found
278 */
280CompiledSimulation::immediateUnitRegisterValue(const char* iuName, int index) {
281
284 std::string immediateUnit = symbolGen.immediateRegisterSymbol(
285 iu, index);
286
287 CompiledSimulationPimpl::Symbols::const_iterator iuIterator =
288 pimpl_->symbols_.find(immediateUnit);
289 if (iuIterator != pimpl_->symbols_.end()) {
290 return *(iuIterator->second);
291 } else {
292 throw InstanceNotFound(__FILE__, __LINE__, __func__,
293 "Immediate unit " + std::string(iuName) + " not found.");
294 }
295}
296
297/**
298 * Returns the value of the given FU port
299 *
300 * @param fuName Name of the FU
301 * @param portIndex index of the port in the FU
302 * @return A SimValue containing the port's present value
303 * @exception InstanceNotFound If the FU port cannot be found
304 */
306CompiledSimulation::FUPortValue(const char* fuName, const char* portName) {
307
309 FunctionUnit* fu = NULL;
310 try {
311 fu = &functionUnit(fuName);
312 } catch(InstanceNotFound& e) {
313 fu = machine_.controlUnit();
314 }
315
316 std::string fuPort = symbolGen.portSymbol(*fu->port(portName));
317
318 CompiledSimulationPimpl::Symbols::const_iterator fuPortIterator =
319 pimpl_->symbols_.find(fuPort);
320 if (fuPortIterator != pimpl_->symbols_.end()) {
321 return *(fuPortIterator->second);
322 } else {
323 throw InstanceNotFound(__FILE__, __LINE__, __func__,
324 "FU port " + std::string(fuPort) + " not found.");
325 }
326}
327
328/**
329 * Sets the simulation to be requested to stop
330 */
331void
335
336/**
337 * Returns true if the simulation is requested to stop
338 *
339 * This can be either because the simulation has finished or the
340 * requested amount of cycles has been simulated.
341 *
342 * @return true if the simulation should stop
343 */
344bool
348
349/** Returns true if the simulation is finished
350 *
351 * @return true if the simulation is finished
352 */
353bool
357
358/**
359 * Returns move execution count for move #moveNumber.
360 *
361 * @param moveNumber move number as in POM
362 * @return move execution count
363 */
366 int moveNumber,
367 InstructionAddress address) const {
369 InstructionAddress programStartAddress = program.startAddress().location();
370 const Move& move = program.moveAt(moveNumber);
371
372 if (move.isUnconditional() && pimpl_->exitPoints_.find(address) ==
373 pimpl_->exitPoints_.end()) {
374 // Grab the whole basic block execution count
375 InstructionAddress bbStart = basicBlockStart(address -
376 programStartAddress);
377 return bbExecCounts_[bbStart];
378 } else { // guarded move or an exit point, grab single move execution count
379 return moveExecCounts_[moveNumber];
380 }
381}
382
383/**
384 * Returns start of the basic block for given address of a basic block
385 * @param address address of a basic block
386 * @return start address of the basic block
387 */
392
393/**
394 * Returns a function unit of the given name
395 *
396 * @param name name of the function unit to return
397 * @return function unit of given name
398 * @exception InstanceNotFound If a function unit is not found
399 */
401CompiledSimulation::functionUnit(const char* name) const {
402 return *machine_.functionUnitNavigator().item(name);
403}
404
405/**
406 * Returns a memory object of the given function unit
407 *
408 * @param FUName name of the function unit
409 * @return memory object of the given function unit
410 * @exception InstanceNotFound If an item is not found
411 */
413CompiledSimulation::FUMemory(const char* FUName) const {
414 assert(
415 machine_.functionUnitNavigator().item(FUName)->addressSpace() != NULL);
416 return
417 dynamic_cast<DirectAccessMemory&>(
420 FUName)->addressSpace()).get());
421}
422
423/**
424 * Returns a pointer to the memory system
425 *
426 * @return a pointer to the memory system
427 */
433
434/**
435 * Returns a reference to the simulator frontend
436 *
437 * @return a reference to the simulator frontend
438 */
441 return *(pimpl_->frontend_);
442}
443
444/**
445 * A short cut for printing debugging info from the compiled code.
446 *
447 * @param message The message string to be shown on the log stream
448 */
449void
450CompiledSimulation::msg(const char* message) const {
451 Application::logStream() << message << std::endl;
452}
453
454/**
455 * Halts simulation by throwing an exception with a message attached to it
456 *
457 * @param file file where the exception happened, i.e. __FILE__
458 * @param line line where the exception happened, i.e. __LINE__
459 * @param procedure function where the exception happened, i.e. __FUNCTION__
460 * @param message message to attach
461 * @exception SimulationExecutionError thrown always
462 */
463void
465 const char* file,
466 int line,
467 const char* procedure,
468 const char* message) const {
469 throw SimulationExecutionError(file, line, procedure, message);
470}
471
472/**
473 * Resizes the jump table
474 *
475 * @param newSize New size
476 */
477void
479 pimpl_->jumpTable_.resize(newSize, 0);
480}
481
482/**
483 * Gets the simulate function of given address from the jump table.
484 *
485 * If this is a dynamic compiled simulation, it'll first check if the simulate-
486 * function is available. If not, it will compile the required files first and
487 * then loads the simulate function symbols.
488 *
489 * @param address address to get the simulate function for
490 * @return Simulate Function of given address from the jump table
491 * @exception SimulationExecutionError If the jump function couldn't be gotten
492 */
495
496 // Is there an already existing simulate function in the given address?
497 SimulateFunction targetFunction = pimpl_->jumpTable_[address];
498 if (targetFunction != 0) {
499 return targetFunction;
500 }
501
503 compileAndLoadFunction(address);
504 targetFunction = pimpl_->jumpTable_[address];
505 if (targetFunction != 0) {
506 return targetFunction;
507 }
508 }
509
510 throw SimulationExecutionError(__FILE__, __LINE__, __FUNCTION__,
511 "Cannot simulate jump to address " + Conversion::toString(address) +
512 ". Please try with the interpretive simulation engine." );
513}
514
515/**
516 * Sets a jump target function for given address at the jump table
517 *
518 * @param address address to set a jump function for
519 * @param fp function pointer to set at the address
520 */
521void
527
528/**
529 * Compiles and loads all simulate functions belonging to a procedure
530 * containing the given address.
531 *
532 * @param address (any) address of a procedure to compile
533 */
534void
536
537 InstructionAddress procedureStart =
539
540 // Files compiled so far
541 std::set<std::string> compiledFiles;
542
544
545 // Get basic blocks of a procedure
546 typedef ProcedureBBRelations::BasicBlockStarts::iterator BBIterator;
547 std::pair<BBIterator, BBIterator> equalRange =
548 procedureBBRelations_.basicBlockStarts.equal_range(procedureStart);
549
550 // Loop all basic blocks of a procedure, then compile all its files
551 for (BBIterator it = equalRange.first; it != equalRange.second; ++it) {
552 std::string file = procedureBBRelations_.basicBlockFiles[it->second];
553
554 // Compile the file if it hasn't been already
555 if (compiledFiles.find(file) == compiledFiles.end()) {
557 std::string soPath = FileSystem::directoryOfPath(file)
559 + FileSystem::fileNameBody(file) + ".so";
561 compiledFiles.insert(file);
562 }
563
564 // Load the generated simulate function
567 symbolGen.basicBlockSymbol(it->second), fn);
568 setJumpTargetFunction(it->second, fn);
569 }
570}
571
572/**
573 * Returns value of the given symbol (be it RF, FU, or IU)
574 *
575 * @param symbolName Symbol name in the generated code
576 * @return a pointer to the symbol's SimValue or 0 if the symbol wasn't found
577 */
579CompiledSimulation::getSymbolValue(const char* symbolName) {
580
581 CompiledSimulationPimpl::Symbols::iterator it = pimpl_->symbols_.find(
582 std::string(symbolName));
583
584 if (it != pimpl_->symbols_.end()) {
585 return it->second;
586 } else {
587 return 0;
588 }
589}
590
591/**
592 * Adds a new symbol name -> SimValue pair to the symbols map
593 * @param symbolName the symbol name
594 * @param value the SimValue
595 */
596void
597CompiledSimulation::addSymbol(const char* symbolName, SimValue& value) {
598 pimpl_->symbols_[std::string(symbolName)] = &value;
599}
#define __func__
#define assert(condition)
Word UIntWord
Definition BaseType.hh:144
UInt32 InstructionAddress
Definition BaseType.hh:175
static const ClockCycleCount MAX_CYCLES
void(* SimulateFunction)(void *engine)
Type for the simulateXXXXX basic block functions.
TTAMachine::Machine * machine
the architecture definition of the estimated processor
find Finds info of the inner loops in the program
find Finds info of the inner loops in the false
CycleCount ClockCycleCount
Alias for ClockCycleCount.
static std::ostream & logStream()
int compileToSO(const std::string &path, const std::string &flags="", bool verbose=false) const
const TTAProgram::Program & program() const
InstructionAddress basicBlockStart(InstructionAddress address) const
std::string basicBlockSymbol(InstructionAddress startAddress) const
std::string portSymbol(const TTAMachine::Port &port) const
std::string registerSymbol(const TTAProgram::Terminal &terminal) const
std::string immediateRegisterSymbol(const TTAProgram::Terminal &terminal) const
MemorySystem * memorySystem_
The memory system.
std::set< InstructionAddress > exitPoints_
Program exit points in a set.
CompiledSimController * controller_
Simulation controller.
Symbols symbols_
A Symbol map for easily getting the SimValues out of the simulation.
CompiledSimCompiler compiler_
The Compiled Simulation compiler.
SimulatorFrontend * frontend_
The simulator frontend.
JumpTable jumpTable_
The jump table.
PluginTools pluginTools_
Plugintools used to load the compiled .so files.
MemorySystem * memorySystem() const
virtual ClockCycleCount moveExecutionCount(int moveNumber, InstructionAddress address) const
CompiledSimulation(const TTAMachine::Machine &machine, InstructionAddress entryAddress, InstructionAddress lastInstruction, SimulatorFrontend &frontend, CompiledSimController &controller, MemorySystem &memorySystem, bool dynamicCompilation, ProcedureBBRelations &procedureBBRelations)
void setJumpTargetFunction(InstructionAddress address, SimulateFunction fp)
virtual InstructionAddress lastExecutedInstruction() const
ProcedureBBRelations & procedureBBRelations_
A struct for finding out procedure begins from procedure's basic blocks.
virtual void simulateCycle()=0
SimulateFunction getSimulateFunction(InstructionAddress address)
virtual void requestToStop()
const TTAMachine::Machine & machine_
The simulated machine.
virtual void step(double count)
virtual SimValue registerFileValue(const char *rfName, int registerIndex)
ClockCycleCount * moveExecCounts_
Move execution counts in a C style table.
bool stopRequested_
Should the simulation stop or not?
virtual void runUntil(UIntWord address)
SimulatorFrontend & frontend() const
virtual ClockCycleCount cycleCount() const
virtual bool isFinished() const
ClockCycleCount cycleCount_
Number of cycles simulated so far.
CompiledSimulationPimpl * pimpl_
Private implementation in a separate source file.
bool isFinished_
Is the simulation finished?
InstructionAddress programCounter_
The program counter. i.e. which address the simulation is currently at.
InstructionAddress lastExecutedInstruction_
Last executed instruction.
DirectAccessMemory & FUMemory(const char *FUName) const
virtual bool stopRequested() const
void resizeJumpTable(int newSize)
void addSymbol(const char *symbolName, SimValue &value)
virtual InstructionAddress programCounter() const
virtual void next(int count)
void msg(const char *message) const
void compileAndLoadFunction(InstructionAddress address)
void haltSimulation(const char *file, int line, const char *procedure, const char *message) const
ClockCycleCount * bbExecCounts_
Basic block execution counts in a C style table.
virtual SimValue immediateUnitRegisterValue(const char *iuName, int index)
SimValue * getSymbolValue(const char *symbolName)
virtual SimValue FUPortValue(const char *fuName, const char *portName)
ClockCycleCount cyclesToSimulate_
Number of cycles left to simulate until the execution returns.
InstructionAddress jumpTarget_
The jump target. Allows jumping to different addresses in the code.
bool dynamicCompilation_
Is this a dynamic compiled simulation?
TTAMachine::FunctionUnit & functionUnit(const char *name) const
virtual InstructionAddress basicBlockStart(InstructionAddress address) const
static std::string toString(const T &source)
static const std::string DIRECTORY_SEPARATOR
static std::string fileNameBody(const std::string &fileName)
static std::string directoryOfPath(const std::string fileName)
Definition FileSystem.cc:79
void handleEvent(int event)
MemoryPtr memory(const TTAMachine::AddressSpace &as)
void importSymbol(const std::string &symbolName, T *&target, const std::string &module)
void registerModule(const std::string &module)
@ SE_CYCLE_END
Generated before advancing the simulator clock at the end of a simulation cycle.
SimulationEventHandler & eventHandler()
virtual BaseFUPort * port(const std::string &name) const
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition Machine.cc:416
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
InstructionAddress location() const
bool isUnconditional() const
Definition Move.cc:154
Address startAddress() const
Definition Program.cc:286
int moveCount() const
Definition Program.cc:494
virtual std::set< InstructionAddress > findProgramExitPoints(const TTAProgram::Program &program, const TTAMachine::Machine &machine) const
A struct for tracking basic blocks and their relation to their procedures.
std::map< InstructionAddress, std::string > basicBlockFiles
Basic block starts and their corresponding .cpp files.
std::map< InstructionAddress, InstructionAddress > procedureStart
Procedure start per basic block starts.
BasicBlockStarts basicBlockStarts
All basic block start addresses per procedure start.