OpenASIP  2.0
CompiledSimCodeGenerator.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 CompiledSimCodeGenerator.cc
26  *
27  * Definition of CompiledSimCodeGenerator class.
28  *
29  * @author Viljami Korhonen 2007 (viljami.korhonen-no.spam-tut.fi)
30  * @author Pekka Jääskeläinen 2009-2010 (pekka.jaaskelainen-no.spam-tut.fi)
31  * @note rating: red
32  */
33 
34 #include <iostream>
35 #include <fstream>
36 #include <string>
37 #include <sstream>
38 #include <vector>
39 #include <cstdlib>
40 
41 #include "SimulatorFrontend.hh"
44 #include "Machine.hh"
45 #include "FunctionUnit.hh"
46 #include "FUPort.hh"
47 #include "PipelineElement.hh"
48 #include "Program.hh"
49 #include "Procedure.hh"
50 #include "Instruction.hh"
51 #include "ExecutableInstruction.hh"
52 #include "NullInstruction.hh"
53 #include "NullRegisterFile.hh"
54 #include "Move.hh"
55 #include "Guard.hh"
56 #include "MoveGuard.hh"
57 #include "Terminal.hh"
58 #include "TerminalImmediate.hh"
59 #include "TerminalFUPort.hh"
60 #include "Immediate.hh"
61 #include "Operation.hh"
62 #include "OperationContext.hh"
63 #include "OperationDAGConverter.hh"
64 #include "OperationPool.hh"
65 #include "HWOperation.hh"
66 #include "ControlUnit.hh"
67 #include "SpecialRegisterPort.hh"
68 #include "FileSystem.hh"
69 #include "CodeLabel.hh"
70 #include "DataLabel.hh"
71 #include "ControlFlowGraph.hh"
72 #include "tce_config.h"
73 #include "BaseType.hh"
74 #include "MachineInfo.hh"
76 #include "CompiledSimMove.hh"
77 #include "CompiledSimCompiler.hh"
78 #include "DisassemblyRegister.hh"
79 #include "MapTools.hh"
80 #include "TCEString.hh"
81 
82 using namespace TTAMachine;
83 using namespace TTAProgram;
84 using std::string;
85 using std::fstream;
86 using std::endl;
87 using std::vector;
88 
89 namespace {
90 
91 enum class AccessMode : unsigned char { read, write };
92 enum class ExtensionMode : unsigned char { sign, zero };
93 enum class MAUOrder : unsigned char { littleEndian, bigEndian };
94 
95 struct MemoryOperationDescription {
96  AccessMode accessMode;
97  unsigned mauCount;
98  ExtensionMode extensionMode; // relevant only for load ops
99  MAUOrder mauOrder;
100 
101 };
102 
103 // Since DirectAccessMemory's advanceClock() method is empty and is not
104 // called, memory operations with latency more than one are not supported
105 // in compiled simulation.
106 // However, these operations are exception and uses other methods for
107 // simulating latency.
108 std::map<TCEString, MemoryOperationDescription, TCEString::ICLess>
109 supportedMemoryOps{
110  {"ldq",
111  {AccessMode::read, 1, ExtensionMode::sign, MAUOrder::bigEndian}},
112  {"ldqu",
113  {AccessMode::read, 1, ExtensionMode::zero, MAUOrder::bigEndian}},
114  {"ldh",
115  {AccessMode::read, 2, ExtensionMode::sign, MAUOrder::bigEndian}},
116  {"ldhu",
117  {AccessMode::read, 2, ExtensionMode::zero, MAUOrder::bigEndian}},
118  {"ldw",
119  {AccessMode::read, 4, ExtensionMode::sign, MAUOrder::bigEndian}},
120  {"ld8",
121  {AccessMode::read, 1, ExtensionMode::sign, MAUOrder::littleEndian}},
122  {"ldu8",
123  {AccessMode::read, 1, ExtensionMode::zero, MAUOrder::littleEndian}},
124  {"ld16",
125  {AccessMode::read, 2, ExtensionMode::sign, MAUOrder::littleEndian}},
126  {"ldu16",
127  {AccessMode::read, 2, ExtensionMode::zero, MAUOrder::littleEndian}},
128  {"ld32",
129  {AccessMode::read, 4, ExtensionMode::sign, MAUOrder::littleEndian}},
130 
131  {"st8",
132  {AccessMode::write, 1, ExtensionMode::zero, MAUOrder::littleEndian}},
133  {"st16",
134  {AccessMode::write, 2, ExtensionMode::zero, MAUOrder::littleEndian}},
135  {"st32",
136  {AccessMode::write, 4, ExtensionMode::zero, MAUOrder::littleEndian}},
137  {"stq",
138  {AccessMode::write, 1, ExtensionMode::zero, MAUOrder::bigEndian}},
139  {"sth",
140  {AccessMode::write, 2, ExtensionMode::zero, MAUOrder::bigEndian}},
141  {"stw",
142  {AccessMode::write, 4, ExtensionMode::zero, MAUOrder::bigEndian}}
143 };
144 
145 } // anonymous namespace.
146 
147 
148 /**
149  * The constructor
150  *
151  * Gets the settings for compiled simulation code generation.
152  *
153  * @param machine The machine to run the simulation on
154  * @param program The simulated program
155  * @param controller Compiled Simulation controller
156  * @param fuResourceConflictDetection is the conflict detection on?
157  * @param handleCycleEnd should we let frontend handle each cycle end
158  * @param basicBlockPerFile Should we generate only one BB per code file?
159  */
163  const TTASimulationController& controller,
164  bool fuResourceConflictDetection,
165  bool handleCycleEnd,
166  bool dynamicCompilation,
167  bool basicBlockPerFile,
168  bool functionPerFile,
169  const TCEString& globalSymbolSuffix) :
170  machine_(machine), program_(program), simController_(controller),
171  gcu_(*machine.controlUnit()),
172  handleCycleEnd_(handleCycleEnd),
173  dynamicCompilation_(dynamicCompilation),
174  basicBlockPerFile_(basicBlockPerFile),
175  functionPerFile_(functionPerFile),
176  instructionNumber_(0), instructionCounter_(0),
177  moveCounter_(0),
178  isProcedureBegin_(true), currentProcedure_(0),
179  lastInstructionOfBB_(0),
180  className_(TCEString("CompiledSimulationEngine_") + globalSymbolSuffix),
181  os_(NULL), symbolGen_(globalSymbolSuffix),
182  conflictDetectionGenerator_(
183  machine_, symbolGen_, fuResourceConflictDetection),
184  needGuardPipeline_(false), globalSymbolSuffix_(globalSymbolSuffix) {
185 
186  // this should result in roughly 100K-400K .cpp files
188  // roughly 300-600 c++ lines per simulation function
190 
191 // Create the guardpipeline.
192 
194  needGuardPipeline_ = true;
195 
196  int ggLatency = machine.controlUnit()->globalGuardLatency();
197 
198  const TTAMachine::Machine::BusNavigator busNav =
200 
201  for (int i = 0; i < busNav.count(); i++) {
202  const TTAMachine::Bus* bus = busNav.item(i);
203  for (int j = 0; j < bus->guardCount(); j++) {
204  Guard* guard = bus->guard(j);
205  RegisterGuard* rg = dynamic_cast<RegisterGuard*>(guard);
206  if (rg != NULL) {
207  const RegisterFile* rf = rg->registerFile();
208  int rgLat = rg->registerFile()->guardLatency();
209  string symbolName =
211  guardPipeline_[symbolName] = ggLatency + rgLat + 1;
212  }
213  }
214  }
215  }
216 }
217 
218 /**
219  * The destructor
220  */
222 }
223 
224 /**
225  * Generates compiled simulation code to the given directory.
226  *
227  * @param directory Directory where all the code is to be generated at
228  * @exception IOException if the directory could not be opened for writing
229  */
230 void
232  targetDirectory_ = directory;
233  headerFile_ = "CompiledSimulationEngine.hh";
234  mainFile_ = "CompiledSimulationEngine.cc";
235 
239 }
240 
241 /**
242  * Generates a Makefile for compiling the simulation engine.
243  */
244 void
246 
249 
250  std::ofstream makefile(currentFileName_.c_str());
251  std::vector<std::string> includePaths = Environment::includeDirPaths();
252  std::string includes;
253  for (std::vector<std::string>::iterator it = includePaths.begin();
254  it != includePaths.end(); ++it) {
255  includes += "-I" + *it + " ";
256  }
257 
258  makefile
259  << "sources = $(wildcard *.cpp)" << endl
260  << "objects = $(patsubst %.cpp,%.o,$(sources))" << endl
261  << "dobjects = $(patsubst %.cpp,%.so,$(sources))" << endl
262  << "includes = " << includes << endl
263  << "soflags = " << CompiledSimCompiler::COMPILED_SIM_SO_FLAGS << endl
264 
265  // use because ccache doesn't like changing directory paths
266  // (in a preprocessor comment)
267  << "cppflags = " << CompiledSimCompiler::COMPILED_SIM_CPP_FLAGS << endl
268  << endl
269 
270  << "all: CompiledSimulationEngine.so" << endl << endl
271 
272  << "CompiledSimulationEngine.so: CompiledSimulationEngine.hh.gch "
273  << "$(dobjects) CompiledSimulationEngine.cc" << endl
274  << "\t#@echo Compiling CompiledSimulationEngine.so" << endl
275  << "\t$(CC) $(cppflags) -O0 $(includes) CompiledSimulationEngine.cc "
276  << "-c -o CompiledSimulationEngine.o" << endl
277  << "\t$(CC) $(soflags) CompiledSimulationEngine.o -o CompiledSimulationEngine.so"
278  << endl << endl
279  << "$(dobjects): %.so: %.cpp CompiledSimulationEngine.hh.gch" << endl
280 
281  // compile and link phases separately to allow distributed compilation
282  // thru distcc
283  << "\t$(CC) -c $(cppflags) $(opt_flags) $(includes) $< -o $@.o" << endl
284  << "\t$(CC) $(soflags) $(opt_flags) -lgcc $@.o -o $@" << endl
285  << "\t@rm -f $@.so.o" << endl
286  << endl
287 
288  // use precompiled headers for more speed
289  << "CompiledSimulationEngine.hh.gch:" << endl
290  << "\t$(CC) $(cppflags) $(opt_flags) $(includes) "
291  << "-xc++-header CompiledSimulationEngine.hh" << endl
292  << endl
293 
294  << "clean:" << endl
295  << "\t@rm -f $(dobjects) CompiledSimulationEngine.so CompiledSimulationEngine.hh.gch" << endl;
296 
297  makefile.close();
298  currentFileName_.clear();
299 }
300 
301 /**
302  * Returns a list of the created .cpp filenames
303  *
304  * @return a list of the created .cpp filenames
305  */
308  return createdFiles_;
309 }
310 
311 /**
312  * Returns a list of basic blocks of the program
313  *
314  * @return a list of basic blocks of the program
315  */
318  if (bbStarts_.empty()) {
319  findBasicBlocks();
320  }
321  return bbEnds_;
322 }
323 
324 /**
325  * Returns a struct of basic blocks and their corresponding code files
326  *
327  * @return a struct of basic blocks and their corresponding code files
328  */
331  return procedureBBRelations_;
332 }
333 
334 /**
335  * Creates a header file to be used for all the .cpp files and the main
336  * source file which includes the constructor and the main simulation loop.
337  *
338  * Initializes all variables required by the simulation
339  *
340  * Sets up new SimValue variables for all the FUs, registers,
341  * FU pipeline stages and so on. Variables are created as member variables.
342  *
343  */
344 void
346 
347  // Open a new file for the header
348  const string DS = FileSystem::DIRECTORY_SEPARATOR;
350  currentFile_.open(currentFileName_.c_str(), fstream::out);
351  os_ = &currentFile_;
352 
354 
355  // Generate includes
356  *os_ << "// " << className_ << " Generated automatically by ttasim" << endl
357  << "#ifndef _AUTO_GENERATED_COMPILED_SIMULATION_H_" << endl
358  << "#define _AUTO_GENERATED_COMPILED_SIMULATION_H_" << endl
359  << "#include \"SimValue.hh\"" << endl
360  << "#include \"DirectAccessMemory.hh\"" << endl
361  << "#include \"OSAL.hh\"" << endl
362  << "#include \"Operation.hh\"" << endl
363  << "#include \"OperationPool.hh\"" << endl
364  << "#include \"OperationContext.hh\"" << endl
365  << "#include \"CompiledSimulation.hh\"" << endl
366  << "#include \"BaseType.hh\"" << endl
367  << "#include \"MathTools.hh\"" << endl
369  << endl;
370 
371  // Open up class declaration and define some extra member variables
372  *os_ << "class " << className_ << ";" << endl << endl;
373  *os_ << "class " << className_ << " : public CompiledSimulation {" << endl
374  << "public:" << endl;
375 
376  // Declare all FUs
378  for (int i = 0; i < fus.count(); ++i) {
379  const FunctionUnit& fu = *fus.item(i);
380 
381  // FU Ports
382  for (int j = 0; j < fu.operationPortCount(); ++j) {
383  const FUPort& port = *fu.operationPort(j);
385  }
386 
387  // Conflict detectors
390  }
391 
392  // Operation contexts
393  *os_ << "\t" << "OperationContext "
394  << symbolGen_.operationContextSymbol(fu) << ";" << endl;
395 
396  // Address spaces
397  if (fu.addressSpace() != NULL) {
398  *os_ << "\t" << "DirectAccessMemory& "
399  << symbolGen_.DAMemorySymbol(*fus.item(i)) << ";"
400  << endl;
401  }
402 
403  // All operations of the FU
404  for (int j = 0; j < fu.operationCount(); ++j) {
405  string opName = fu.operation(j)->name();
406  *os_ << "\t" << "Operation& "
407  << symbolGen_.operationSymbol(opName, fu) << ";" << endl;
408 
409  usedOperations_.insert(
410  std::make_pair(opName, symbolGen_.operationSymbol(opName, fu)));
411  }
412 
413  // FU output results
414  std::vector<Port*> outPorts = fuOutputPorts(fu);
415  for (size_t j = 0; j < outPorts.size(); ++j) {
416  *os_ << "\t" << "FUResultType "
417  << symbolGen_.FUResultSymbol(*outPorts.at(j))
418  << ";" << endl;
419  }
420  }
421  *os_ << endl;
422 
423  // GCU
425  if (gcu) {
426  for (int i = 0; i < gcu->specialRegisterPortCount(); ++i) {
427  SpecialRegisterPort& port = *gcu->specialRegisterPort(i);
429  }
430  for (int i = 0; i < gcu->operationPortCount(); ++i) {
431  FUPort& port = *gcu->operationPort(i);
433  }
434  }
435 
436  // Declare all IUs
437  const Machine::ImmediateUnitNavigator& ius =
439  for (int i = 0; i < ius.count(); ++i) {
440  const ImmediateUnit& iu = *ius.item(i);
441  for (int j = 0; j < iu.numberOfRegisters(); ++j) {
443  iu.width());
444  }
445  }
446 
447  // Register files
448  const Machine::RegisterFileNavigator& rfs =
450  for (int i = 0; i < rfs.count(); ++i) {
451  const RegisterFile& rf = *rfs.item(i);
452  for (int j = 0; j < rf.numberOfRegisters(); ++j) {
454  rf.width());
455  }
456  }
457 
458  // Buses
460  for (int i = 0; i < buses.count(); ++i) {
461  const Bus& bus = *buses.item(i);
463  }
464 
465  // guard pipeline
466  if (needGuardPipeline_) {
468  }
469 
472  *os_ << ";" << endl;
473 
475 
476  // Generate dummy destructor
477  *os_ << "EXPORT virtual ~" << className_ << "() { }" << endl << endl;
478  *os_ << "EXPORT virtual void simulateCycle();" << endl << endl << "}; // end class" << endl;
479 
480  *os_ << "extern \"C\" EXPORT void updateFUOutputs_"
481  << globalSymbolSuffix_ << "(" << className_ << "&);" << endl;
482 
483  *os_ << endl << endl << "#endif // include once" << endl << endl;
484 
485  // header written
486  currentFile_.close();
487  currentFileName_.clear();
488  os_ = NULL;
489 
491 }
492 
493 /**
494  * Generates the parameter list for the constructor.
495  */
496 void
498  *os_ << className_
499  << "(const TTAMachine::Machine& machine," << endl
500  << "InstructionAddress entryAddress," << endl
501  << "InstructionAddress lastInstruction," << endl
502  << "SimulatorFrontend& frontend," << endl
503  << "CompiledSimController& controller," << endl
504  << "MemorySystem& memorySystem," << endl
505  << "bool dynamicCompilation,"
506  << "ProcedureBBRelations& procedureBBRelations)";
507 }
508 
509 /**
510  * Generates code for the class constructor in the main .cpp file.
511  */
512 void
514 
515  const string DS = FileSystem::DIRECTORY_SEPARATOR;
516  currentFile_.open((targetDirectory_ + DS + mainFile_).c_str(), fstream::out);
517  createdFiles_.insert(mainFile_);
518  os_ = &currentFile_;
519 
521 
522  *os_ << "#include \"" << headerFile_ << "\"" << endl << endl;
523 
524  // generate forward declarations for simulate functions
525  for (AddressMap::const_iterator it = bbStarts_.begin();
526  it != bbStarts_.end(); ++it) {
527  *os_ << "\t" << "extern \"C\" EXPORT void "
528  << symbolGen_.basicBlockSymbol(it->first)
529  << "(void*);" << endl;
530  }
531 
532  *os_ << "EXPORT " << className_ << "::";
533 
535 
536  *os_ << " : " << endl
537  << "CompiledSimulation(machine, entryAddress, lastInstruction, "
538  << "frontend, controller, memorySystem, dynamicCompilation, "
539  << "procedureBBRelations),"
540  << endl;
541 
544 
545  const Machine::FunctionUnitNavigator& fus =
547  for (int i = 0; i < fus.count(); i++) {
548  const FunctionUnit& fu = *fus.item(i);
549  std::string context = symbolGen_.operationContextSymbol(fu);
550 
551  *os_ << "\t" << context << ".setCycleCountVariable(cycleCount_);"
552  << endl;
553  // Create a state for each operation
554  for (int j = 0; j < fu.operationCount(); ++j) {
555  std::string operation = symbolGen_.operationSymbol(
556  fu.operation(j)->name(), fu);
557 
558  *os_ << "\t" << operation << ".createState(" << context << ");"
559  << endl;
560  }
561 
562  // Set a Memory for the context
563  if (fu.addressSpace() != NULL) {
564  *os_ << "\t" << context << ".setMemory(&"
565  << symbolGen_.DAMemorySymbol(fu) << ");" << endl;
566  }
567  }
568 
570 
572  << "}" << endl << endl;
573 
574  // generate simulateCycle() method
575  *os_ << "// Simulation code:" << endl
576  << "EXPORT void " << className_ << "::simulateCycle() {"
577  << endl << endl;
578 
579  // Create a jump dispatcher for accessing each basic block start
580  *os_ << "\t// jump dispatcher" << endl
581  << "\tjumpTargetFunc_ = getSimulateFunction(jumpTarget_);" << endl
582  << "\t(jumpTargetFunc_)(this);" << endl << endl;
583 
585  << "}" << endl << endl;
586 
589 }
590 
591 /**
592  * Generates the simulateCycle() function that is called outside the .so file
593  *
594  * The generated function simulates one basic block at a time by calling
595  * the according basic block methods.
596  */
597 void
599 
600  findBasicBlocks();
602 
603  // generate code for all procedures
604  for (int i = 0; i < program_.procedureCount(); ++i) {
606  }
607 
608  // Close the last file
609  currentFile_.close();
610  currentFileName_.clear();
611  os_ = NULL;
612 }
613 
614 /**
615  * Finds all basic blocks of the program and stores them in two std::maps
616  *
617  * Big basic blocks are split to smaller ones to reduce the engine
618  * compilation memory consumption.
619  */
620 void
622  for (int i = 0; i < program_.procedureCount(); ++i) {
624  for (int i = 0; i < cfg.nodeCount(); ++i) {
625  BasicBlockNode& node = cfg.node(i);
626  if (!node.isNormalBB()) continue;
627 
628  InstructionAddress blockStart = node.originalStartAddress();
629  const InstructionAddress end = node.originalEndAddress();
630 
631  if (end - blockStart > maxInstructionsPerSimulationFunction_) {
632  // split the real basic block to smaller ones in case
633  // there are too many instructions (huge basic blocks might
634  // explode the engine compiler memory consumption)
635  InstructionAddress blockEnd = blockStart;
636 #if 0
638  << "splitting a bb " << blockStart << " to " << end
639  << " with size " << end - blockStart << std::endl;
640 #endif
641  for (; blockStart < end; blockStart = blockEnd + 1) {
642  blockEnd =
643  std::min(
645  end);
646 
647  // we must ensure that the branch and its delay slots
648  // end up in the same block due to the way guard
649  // reads are handled as local variables in the simulation
650  // func
651  if (blockEnd + machine_.controlUnit()->delaySlots() >= end) {
652  blockEnd = end;
653  }
654 
655  bbEnds_[blockEnd] = blockStart;
656  bbStarts_[blockStart] = blockEnd;
657 #if 0
659  << "small block: " << blockStart << " to "
660  << blockEnd << std::endl;
661 #endif
662  }
663  // the "leftover" block:
664 
665 
666  blockStart = blockEnd + 1;
667  if (blockStart <= end) {
668 #if 0
670  << "leftover block: " << blockStart << " to "
671  << end << std::endl;
672 #endif
673  bbEnds_[end] = blockStart;
674  bbStarts_[blockStart] = end;
675  }
676  } else {
677  bbEnds_[end] = blockStart;
678  bbStarts_[blockStart] = end;
679  }
680  }
681  }
682 }
683 
684 /**
685  * Generates code for each instruction in a procedure
686  *
687  * @param procedure the procedure to generate code from
688  * @exception InstanceNotFound if the first instruction wasn't found
689  */
690 void
692  currentProcedure_ = &procedure;
693  isProcedureBegin_ = true;
694  for (int i = 0; i < procedure.instructionCount(); i++) {
695  Instruction& instruction = procedure.instructionAtIndex(i);
696  generateInstruction(instruction);
699  isProcedureBegin_ = false;
700  }
701 }
702 
703 /**
704  * Generates shutdown code for the given instruction address
705  *
706  * @param address Address location of the instruction. Will be saved in the PC
707  *
708  */
709 void
711  *os_ << "/* PROGRAM EXIT */" << endl
712  << "engine.programCounter_ = " << address << ";" << endl
713  << "engine.isFinished_ = true; return;" << endl;
714 }
715 
716 /**
717  * Generates a function that is used to update all FU outputs
718  * from the "result buffer".
719  */
720 void
722  // use C-style functions only! (C++ name mangling complicates stuff)
723  *os_ << "/* Updates all FU outputs to correct the visible machine state */" << endl
724  << "extern \"C\" EXPORT void updateFUOutputs_"
725  << globalSymbolSuffix_ << "("
726  << className_ << "& engine) {" << endl;
727 
729  for (int i = 0; i < fus.count(); ++i) {
730  const FunctionUnit& fu = *fus.item(i);
731  std::vector<Port*> outPorts = fuOutputPorts(fu);
732  for (size_t j = 0; j < outPorts.size(); ++j) {
733  symbolGen_.enablePrefix("engine.");
734  *os_ << "\t" << generateFUResultRead(
735  symbolGen_.portSymbol(*outPorts.at(j)),
736  symbolGen_.FUResultSymbol(*outPorts.at(j)));
737  }
738  }
739 
740  *os_
741  << "}" << endl
742  << endl;
743 }
744 
745 /**
746  * Generates code for a C function that returns an instance of the compiled sim
747  */
748 void
750  // use C-style functions only! (C++ name mangling complicates stuff)
751  *os_ << "/* Class getter function */" << endl
752  << "extern \"C\" EXPORT CompiledSimulation* "
753  << "getSimulation_" << globalSymbolSuffix_ << "(" << endl
754  << "\tconst TTAMachine::Machine& machine," << endl
755  << "\tInstructionAddress entryAddress," << endl
756  << "\tInstructionAddress lastInstruction," << endl
757  << "\tSimulatorFrontend& frontend," << endl
758  << "\tCompiledSimController& controller," << endl
759  << "\tMemorySystem& memorySystem," << endl
760  << "\tbool dynamicCompilation," << endl
761  << "\tProcedureBBRelations& procedureBBRelations) {" << endl
762  << "\treturn new " << className_
763  << "(machine, entryAddress, lastInstruction, frontend, controller, "
764  << "memorySystem, dynamicCompilation, procedureBBRelations); "
765  << endl << "}" << endl << endl; // 2x end-of-line in the end of file
766 }
767 
768 /**
769  * Generates code for halting the simulation
770  *
771  * @param message Reason for the halt
772  * @return generated code for halting the simulation
773  */
774 string
776  return std::string("\thaltSimulation(__FILE__, __LINE__, __FUNCTION__, \""
777  + message + "\");\n");
778 }
779 
780 /**
781  * Generates code for advancing clocks of various items per cycle
782  */
784  *os_ << endl << "void inline advanceClocks() {" << endl;
785  if (needGuardPipeline_) {
787  }
789 
790  *os_ << endl << "}" << endl;
791 }
792 
793 /**
794  * Updates the declared symbols list after the program code is generated.
795  *
796  * Generates constructor calls for each declared symbol.
797  */
798 void
800 
802 
803  // Constructor calls for SimValues
804  for (SimValueSymbolDeclarations::iterator it = declaredSymbols_.begin();
805  it != declaredSymbols_.end(); ++it) {
806  *os_ << "\t";
807  if (it != declaredSymbols_.begin()) {
808  *os_ << ",";
809  }
810  *os_ << it->first << "(" << Conversion::toString(it->second)
811  << ")" << endl;
812  }
813  if (!declaredSymbols_.empty()) {
814  *os_ << endl;
815  }
816 
817  // Operations
818  for (OperationSymbolDeclarations::iterator it = usedOperations_.begin();
819  it != usedOperations_.end(); ++it) {
820  *os_ << "\t," << it->second
821  << "(operationPool_.operation(\"" << it->first << "\"))" << endl;
822  }
823  if (!usedOperations_.empty()) {
824  *os_ << endl;
825  }
826 
827  // FU result symbols
829  for (int i = 0; i < fus.count(); ++i) {
830  const FunctionUnit& fu = *fus.item(i);
831  std::vector<Port*> outPorts = fuOutputPorts(fu);
832  for (size_t j = 0; j < outPorts.size(); ++j) {
833  *os_ << "\t," << symbolGen_.FUResultSymbol(*outPorts.at(j))
834  << "(" << Conversion::toString(fu.maxLatency()+1) << ")";
835  *os_ << endl;
836  }
837  }
838  if (fus.count() > 0) {
839  *os_ << endl;
840  }
841  // Conflict detectors
843 
844  // DirectAccessMemories
845  for (int i = 0; i < fus.count(); i++) {
846  const FunctionUnit & fu = *fus.item(i);
847  if (fu.addressSpace() != NULL) {
848  *os_ << "\t," << symbolGen_.DAMemorySymbol(fu)
849  << "(FUMemory(\"" << fu.name() << "\"))" << endl;
850  }
851  }
852  *os_ << " {" << endl;
853 }
854 
855 /**
856  * Updates the Symbols map of the CompiledSimulation class
857  */
858 void
860  for (SimValueSymbolDeclarations::const_iterator it =
861  declaredSymbols_.begin(); it != declaredSymbols_.end(); ++it) {
862  string symbolName = it->first;
863  *os_ << "\t" << "addSymbol(\"" << symbolName << "\", "
864  << symbolName << ");" << endl;
865  }
866 }
867 
868 /**
869  * Generates declarations for all the symbols in the declared symbols -list
870  *
871  * (SimValues, bool guards...)
872  */
873 void
875 
877 
878  for (SimValueSymbolDeclarations::const_iterator it =
879  declaredSymbols_.begin(); it != declaredSymbols_.end(); ++it) {
880  *os_ << "\t" << "SimValue " << it->first << ";" << endl;
881  }
882  *os_ << endl;
883 }
884 
885 /**
886  * Generates code that updates the jump table and finds out all the basic blocks
887  */
888 void
890  *os_ << "\t" << "resizeJumpTable(lastInstruction_ + 1);" << endl;
891 
892  // If static simulation, set all jump targets in the constructor.
893  if (!dynamicCompilation_) {
894  for (AddressMap::const_iterator it = bbStarts_.begin();
895  it != bbStarts_.end(); ++it) {
896  *os_ << "\t" << "setJumpTargetFunction(" << it->first << ", &"
897  << symbolGen_.basicBlockSymbol(it->first) << ");" << endl;
898  }
899  }
900 }
901 
902 /**
903  * Adds a new declared symbol to the map
904  *
905  * @param name name of the symbol
906  * @param width SimValue width
907  */
908 void
909 CompiledSimCodeGenerator::addDeclaredSymbol(const string& name, int width) {
910  declaredSymbols_[name] = width;
911 }
912 
913 
914 /**
915  * Generates code for a jump operation
916  *
917  * @param op A jump or call operation
918  * @return A std::string containing generated code for the jump call
919  */
920 string
922  assert(op.name() == "call" || op.name() == "jump");
923 
924  std::stringstream ss;
925  ss << "engine.jumpTarget_ = "
926  << symbolGen_.portSymbol(*op.port(1)) << ".sIntWordValue();";
927  if (op.name() == "call") { // save return address
928  ss << symbolGen_.returnAddressSymbol(gcu_) << " = "
929  << instructionNumber_ + gcu_.delaySlots() + 1 << "u;" << endl;
930  }
931  return ss.str();
932 }
933 
934 /**
935  * Generates code for a triggered operation.
936  *
937  * @param op The triggered operation
938  * @return A std::string containing generated code for the operation call
939  */
940 string
942  std::stringstream ss;
943 
944  ss << endl << "/* Operation: " << op.name() << ", latency: "
945  << op.latency() << " */" << endl;
946 
947  if (operationPool_.operation(op.name().c_str()).dagCount() <= 0) {
948  ss << handleOperationWithoutDag(op);
949  } else {
950  /// @todo maybe use IsCall & IsControlFlowOperation.
951  if (op.name() != "jump" && op.name() != "call") {
952  ss << "#define context "
954  << endl
955  << "#define opPool_ engine.operationPool_" << endl
956  << generateTriggerCode(op) << endl
957  << "#undef context" << endl
958  << "#undef opPool_" << endl
959  << endl;
960  } else { // simulate a jump
961  ss << handleJump(op);
962  }
963  }
964  return ss.str();
965 }
966 
967 /**
968  * Generates code for a triggered operation that has no DAG available
969  *
970  * @param op The triggered operation
971  * @return A std::string containing generated code for the operation call
972  */
973 string
975  const TTAMachine::HWOperation& op) {
976  std::stringstream ss;
977 
978  std::vector<string> operandSymbols;
979  string operandTable = symbolGen_.generateTempVariable();
980 
981  // Generate symbols for each operand, and temporaries for output operands
982  for (int i = 1; op.port(i) != NULL; ++i) {
983  if (op.port(i)->isOutput()) {
984  string outputSymbol = symbolGen_.generateTempVariable();
985  operandSymbols.push_back(outputSymbol);
986  ss << "SimValue " << outputSymbol
987  << "(" << op.port(i)->width() << ");" << endl;
988  } else { // input port
989  string inputSymbol = symbolGen_.portSymbol(*op.port(i));
990  operandSymbols.push_back(inputSymbol);
991  }
992  }
993 
994  // Add operand symbols to the operand table
995  ss << "SimValue* " << operandTable << "[] = {";
996  for (size_t i = 0; i < operandSymbols.size(); ++i) {
997  ss << "&" << operandSymbols.at(i);
998  if (i < operandSymbols.size() - 1) {
999  ss << ",";
1000  }
1001  ss << " ";
1002  }
1003  ss << "};";
1004 
1005  // call simulateTrigger with the previously generated operand table
1006  /// @todo maybe use IsCall & IsControlFlowOperation.
1007  if (op.name() != "jump" && op.name() != "call") {
1008  ss << symbolGen_.operationSymbol(op.name(), *op.parentUnit())
1009  << ".simulateTrigger(" << operandTable << ", "
1011  << "); ";
1012 
1013  // add output values as delayed assignments
1014  for (int i = 1; op.port(i) != NULL; ++i) {
1015  if (op.port(i)->isOutput()) {
1016  ss << generateAddFUResult(*op.port(i), operandSymbols.at(i - 1),
1017  op.latency());
1018  }
1019  }
1020  } else { // simulate a jump
1021  ss << handleJump(op);
1022  }
1023 
1024  return ss.str();
1025 }
1026 
1027 /**
1028  * Generates code for reading a guard value before an instruction
1029  * with moves guarded with the value is simulated.
1030  *
1031  * @param move guarded move
1032  * @return a std::string containing generated code for the guard check
1033  */
1034 string
1036  const TTAProgram::Move& move) {
1037 
1038  std::stringstream ss;
1039  string guardSymbolName;
1040 
1041  const TTAMachine::Guard& guard = move.guard().guard();
1042 
1043  const TTAMachine::RegisterGuard* rg =
1044  dynamic_cast<const RegisterGuard*>(&guard);
1045  // Find out the guard type
1046  if (rg != NULL) {
1047  const RegisterGuard& rg = dynamic_cast<const RegisterGuard&>(guard);
1048  const RegisterFile& rf = *rg.registerFile();
1049  guardSymbolName = symbolGen_.registerSymbol(rf, rg.registerIndex());
1050  } else if (dynamic_cast<const PortGuard*>(&guard) != NULL) {
1051  const PortGuard& pg = dynamic_cast<const PortGuard&>(guard);
1052  guardSymbolName = symbolGen_.portSymbol(*pg.port());
1053  } else {
1054  ss << endl << "#error unknown guard type!" << endl;
1055  }
1056 
1057  lastGuardBool_ = "";
1058 
1059  // Make sure to create only one bool per guard read and store the symbol
1060  if (usedGuardSymbols_.find(guardSymbolName) == usedGuardSymbols_.end()) {
1061 
1062  // read from the guard pipeline? then use the pipeline ar directly
1063  if (needGuardPipeline_ && rg != NULL) {
1064  std::string guardSym = guardPipelineTopSymbol(*rg);
1065  lastGuardBool_ = usedGuardSymbols_[guardSymbolName] = guardSym;
1066  } else {
1068  usedGuardSymbols_[guardSymbolName] = lastGuardBool_;
1069 
1070  // red from the register.
1071  ss << "const bool " << lastGuardBool_ <<
1072  " = !(MathTools::fastZeroExtendTo("
1073  << guardSymbolName << ".uIntWordValue(), " <<
1074  guardSymbolName << ".width()) == 0u);";
1075  }
1076  } else {
1077  lastGuardBool_ = usedGuardSymbols_[guardSymbolName];
1078  }
1079  return ss.str();
1080 }
1081 
1082 /**
1083  * Generates the condition simulation code for a guarded move.
1084  *
1085  * @param move guarded move
1086  * @return a std::string containing generated code for the guard check
1087  */
1088 string
1090  const TTAProgram::Move& move) {
1091 
1092  std::stringstream ss;
1093  string guardSymbolName;
1094 
1095  const TTAMachine::Guard& guard = move.guard().guard();
1096 
1097  // Find out the guard type
1098  if (dynamic_cast<const RegisterGuard*>(&guard) != NULL) {
1099  const RegisterGuard& rg = dynamic_cast<const RegisterGuard&>(guard);
1100  const RegisterFile& rf = *rg.registerFile();
1101  guardSymbolName = symbolGen_.registerSymbol(rf, rg.registerIndex());
1102  } else if (dynamic_cast<const PortGuard*>(&guard) != NULL) {
1103  const PortGuard& pg = dynamic_cast<const PortGuard&>(guard);
1104  guardSymbolName = symbolGen_.portSymbol(*pg.port());
1105  } else {
1106  ss << endl << "#error unknown guard type!" << endl;
1107  }
1108 
1109  lastGuardBool_ = "";
1110 
1111  // Make sure to create only one bool per guard read and store the symbol
1112  if (usedGuardSymbols_.find(guardSymbolName) == usedGuardSymbols_.end()) {
1114  usedGuardSymbols_[guardSymbolName] = lastGuardBool_;
1115  } else {
1116  lastGuardBool_ = usedGuardSymbols_[guardSymbolName];
1117  }
1118 
1119  // Handle inverted guards
1120  ss << endl << "if (";
1121  if (guard.isInverted()) {
1123  }
1124  ss << lastGuardBool_ << ") { ";
1125 
1126  return ss.str();
1127 }
1128 
1129 
1130 /**
1131  * Generates simulation code of the given instruction
1132  *
1133  * @param instruction instruction to generate the code from
1134  */
1135 void
1137 
1138  InstructionAddress address = instruction.address().location();
1139  usedGuardSymbols_.clear();
1140 
1141  // Are we at the start of a new basic block?
1142  if (bbStarts_.find(address) != bbStarts_.end()) {
1143  // Should we start with a new file?
1147 
1148  if (currentFile_.is_open()) {
1149  currentFile_.close();
1150  }
1151 
1152  // Generate a new file to begin to work with
1153  const string DS = FileSystem::DIRECTORY_SEPARATOR;
1155  + symbolGen_.basicBlockSymbol(address) + ".cpp";
1156  currentFile_.open(currentFileName_.c_str(), fstream::out);
1158  os_ = &currentFile_;
1159  *os_ << "// " << className_
1160  << " Generated automatically by ttasim" << endl
1161  << "#include \"" << headerFile_ << "\"" << endl << endl;
1162  }
1163 
1164  lastInstructionOfBB_ = bbStarts_.find(address)->second;
1166 
1167  // Save basic block<->procedure related information
1168  InstructionAddress procedureStart = currentProcedure_->
1169  startAddress().location();
1170  procedureBBRelations_.procedureStart[address] = procedureStart;
1172  procedureBBRelations_.basicBlockStarts.insert(std::make_pair(
1173  procedureStart, address));
1174 
1175  // Start a new C++ function for the basic block
1176  if (isProcedureBegin_) {
1177  *os_ << "/* Procedure " << currentProcedure_->name()
1178  << " */" << endl;
1179  }
1180  *os_ << endl << "extern \"C\" EXPORT void "
1181  << symbolGen_.basicBlockSymbol(address)
1182  << "(void* eng) {" << endl;
1183  *os_ << className_ << "& engine = *(" << className_ << "*)eng;" << endl;
1184  symbolGen_.enablePrefix("engine.");
1185  lastFUWrites_.clear();
1186 
1187  // initialize jump target to next BB.
1188  int bbEndAddr = -1;
1189  for (int addr = address; bbEndAddr == -1; addr++) {
1190  if (AssocTools::containsKey(bbEnds_, addr)) {
1191  bbEndAddr = addr;
1192  }
1193  }
1194 
1195  *os_ << "/* First instruction of BB - initialize address of next BB"
1196  << " */" << endl;
1197  *os_ << "engine.jumpTarget_ = " << bbEndAddr + 1 << ";" << endl;
1198  }
1199 
1200  *os_ << endl << "/* Instruction " << instructionNumber_ << " */" << endl;
1201 
1202  // Advance clocks of the conflict detectors
1205  *os_ << "engine.advanceClocks();" << endl;
1206  }
1207 
1208  // Do immediate assignments per instruction for FU ports
1209  for (int i = 0; i < instruction.immediateCount(); ++i) {
1210  const Immediate& immediate = instruction.immediate(i);
1211 
1212  if (!immediate.destination().isFUPort()) {
1213  continue;
1214  }
1215 
1217  int value = immediate.value().value().unsignedValue();
1218  *os_ << " = " << value << "u;";
1219  }
1220 
1221  // Get FU Results if there are any ready
1222  std::set<std::string> gotResults; // used to get FU results only once/instr.
1223  DelayedAssignments::iterator it =
1225  while (it != delayedFUResultWrites_.end()) {
1226  *os_ << "engine.clearFUResults(" << it->second.fuResultSymbol << ");" << endl;
1227  *os_ << it->second.targetSymbol << " = " << it->second.sourceSymbol
1228  << ";" << std::endl;
1229  gotResults.insert(it->second.targetSymbol);
1230  delayedFUResultWrites_.erase(it);
1232  }
1233 
1234  bool endGuardBracket = false;
1235 
1236  // Do moves
1237  std::vector<CompiledSimMove> lateMoves; // moves with buses
1238 
1239  // generate the possible guard value reads before the
1240  // actual moves
1241  for (int i = 0; i < instruction.moveCount(); ++i) {
1242  const Move& move = instruction.move(i);
1243  if (!move.isUnconditional()) {
1244  *os_ << generateGuardRead(move) << std::endl;
1245  }
1246  }
1247 
1248  for (int i = 0; i < instruction.moveCount(); ++i, moveCounter_++) {
1249  const Move& move = instruction.move(i);
1250  string moveSource = symbolGen_.moveOperandSymbol(
1251  move.source(), move);
1252  string moveDestination = symbolGen_.moveOperandSymbol(
1253  move.destination(), move);
1254 
1255  lastGuardBool_.clear();
1256 
1257  if (move.source().isFUPort() && gotResults.find(moveSource) == gotResults.end() &&
1258  dynamic_cast<const ControlUnit*>(&move.source().functionUnit()) == NULL) {
1259  *os_
1261  moveSource, symbolGen_.FUResultSymbol(move.source().port()))
1262  << endl;
1263  gotResults.insert(moveSource);
1264  }
1265 
1266  if (!move.isUnconditional()) { // has a guard?
1267  *os_ << generateGuardCondition(move);
1268  endGuardBracket = true;
1269  }
1270 
1271  // increase move count if the move is guarded or it is an exit point
1272  if (!move.isUnconditional() || exitPoints_.find(
1273  instruction.address().location()) != exitPoints_.end()) {
1274  *os_ << " ++engine.moveExecCounts_[" << moveCounter_ << "]; ";
1275  }
1276 
1277  // Find all moves that depend on others i.e. those moves that have to
1278  // be done last.
1279  bool dependingMove = false;
1280  for (int j = instruction.moveCount() - 1; j > 0 && i != j; --j) {
1281  if (moveDestination == symbolGen_.moveOperandSymbol(
1282  instruction.move(j).source(), move)) {
1283  dependingMove = true;
1284  CompiledSimMove lateMove(move, lastGuardBool_, symbolGen_);
1285  lateMoves.push_back(lateMove);
1286  *os_ << lateMove.copyToBusCode();
1287  }
1288  }
1289 
1290  // Assign the values directly instead of through
1291  // the SimValue assignment in case:
1292  if ((move.source().isGPR() || move.source().isFUPort()
1293  || move.source().isImmediateRegister()) &&
1294  (move.source().port().width() <= static_cast<int>(sizeof(UIntWord)*8)) &&
1295  move.source().port().width() == move.destination().port().width()) {
1296  if (move.source().isImmediateRegister() && move.source().immediateUnit().signExtends()) {
1297  moveSource += ".sIntWordValue()";
1298  } else {
1299  moveSource += ".uIntWordValue()";
1300  }
1301  }
1302 
1303  if (!dependingMove) {
1304  *os_ << moveDestination << " = " << moveSource << "; ";
1305  if (needGuardPipeline_) {
1306  handleRegisterWrite(moveDestination, *os_);
1307  }
1308  }
1309 
1310  if (endGuardBracket) {
1311  *os_ << "}";
1312  endGuardBracket = false;
1313  }
1314  }
1315 
1316  endGuardBracket = false;
1317 
1318  // Do moves with triggers, except stores.
1319  for (int i = 0; i < instruction.moveCount(); ++i) {
1320  const Move& move = instruction.move(i);
1321  if (!move.isTriggering()) {
1322  continue;
1323  }
1324 
1325  const TerminalFUPort& tfup =
1326  static_cast<const TerminalFUPort&>(move.destination());
1327  const HWOperation& hwOperation = *tfup.hwOperation();
1328 
1329  if (isStoreOperation(hwOperation.name())) {
1330  continue;
1331  }
1332 
1333  string moveSource = symbolGen_.moveOperandSymbol(
1334  move.source(), move);
1335  string moveDestination = symbolGen_.moveOperandSymbol(
1336  move.destination(), move);
1337 
1338  if (!move.isUnconditional()) { // has a guard?
1339  *os_ << generateGuardCondition(move);
1340  endGuardBracket = true;
1341  }
1342 
1343  if (move.source().isFUPort() && gotResults.find(moveSource) ==
1344  gotResults.end() && dynamic_cast<const ControlUnit*>(
1345  &move.source().functionUnit()) == NULL) {
1346  *os_
1348  moveDestination,
1350  << endl;
1351 
1352  gotResults.insert(
1353  symbolGen_.moveOperandSymbol(move.source(), move));
1354  }
1355 
1356  *os_ << handleOperation(hwOperation)
1358 
1359  if (endGuardBracket) {
1360  *os_ << "}" << endl;
1361  endGuardBracket = false;
1362  }
1363  } // end for
1364 
1365 
1366 
1367 
1368  // Do moves with store triggers.
1369  for (int i = 0; i < instruction.moveCount(); ++i) {
1370  const Move& move = instruction.move(i);
1371  if (!move.isTriggering()) {
1372  continue;
1373  }
1374 
1375  const TerminalFUPort& tfup =
1376  static_cast<const TerminalFUPort&>(move.destination());
1377  const HWOperation& hwOperation = *tfup.hwOperation();
1378 
1379  if (!isStoreOperation(hwOperation.name())) {
1380  continue;
1381  }
1382 
1383  string moveSource = symbolGen_.moveOperandSymbol(
1384  move.source(), move);
1385  string moveDestination = symbolGen_.moveOperandSymbol(
1386  move.destination(), move);
1387 
1388  if (!move.isUnconditional()) { // has a guard?
1389  *os_ << generateGuardCondition(move);
1390  endGuardBracket = true;
1391  }
1392 
1393  if (move.source().isFUPort() && gotResults.find(moveSource) ==
1394  gotResults.end() && dynamic_cast<const ControlUnit*>(
1395  &move.source().functionUnit()) == NULL) {
1396  *os_
1398  moveDestination,
1400  << endl;
1401 
1402  gotResults.insert(
1403  symbolGen_.moveOperandSymbol(move.source(), move));
1404  }
1405 
1406  *os_ << handleOperation(hwOperation)
1408 
1409  if (endGuardBracket) {
1410  *os_ << "}" << endl;
1411  endGuardBracket = false;
1412  }
1413  } // end for
1414 
1415 
1416 
1417  // Do immediate assignments for everything else
1418  for (int i = 0; i < instruction.immediateCount(); ++i) {
1419  const Immediate& immediate = instruction.immediate(i);
1420 
1421  if (immediate.destination().isFUPort()) {
1422  continue;
1423  }
1424 
1426  if (immediate.destination().immediateUnit().signExtends()) {
1427  int value = immediate.value().value().intValue();
1428  *os_ << " = SIntWord("<< value << ");";
1429  } else {
1430  unsigned int value = immediate.value().value().unsignedValue();
1431  *os_ << " = " << value << "u;";
1432  }
1433  }
1434 
1435  // Do bus moves
1436  for (std::vector<CompiledSimMove>::const_iterator it = lateMoves.begin();
1437  it != lateMoves.end(); ++it) {
1438  *os_ << it->copyFromBusCode();
1439  if (needGuardPipeline_) {
1440  if (it->destination().isGPR()) {
1442  symbolGen_.registerSymbol(it->destination()), *os_);
1443  }
1444  }
1445  }
1446 
1447  // No operation?
1448  if (instruction.moveCount() == 0 && instruction.immediateCount() == 0) {
1449  *os_ << "/* NOP */" << endl;
1450  }
1451 
1452  // Let frontend handle cycle end?
1453  if (handleCycleEnd_) {
1454  *os_ << "engine.cycleEnd();" << endl;
1455  }
1456 
1457  *os_ << "engine.cycleCount_++;" << endl;
1458 
1459  AddressMap::iterator bbEnd = bbEnds_.find(address);
1460 
1461  // Increase basic block execution count
1462  if (bbEnd != bbEnds_.end()) {
1463  InstructionAddress bbStart =
1464  bbEnds_.lower_bound(instructionNumber_)->second;
1465  *os_ << "++engine.bbExecCounts_[" << bbStart << "];" << endl;
1466  }
1467 
1468  // generate exit code if this is a return instruction
1469  if (exitPoints_.find(address) != exitPoints_.end()) {
1470  generateShutdownCode(address);
1471  }
1472 
1473  // Create code for a possible exit after the basic block
1474  if (bbEnd != bbEnds_.end()) {
1475  *os_
1476  << "if (engine.cycleCount_ >= engine.cyclesToSimulate_) {" << endl
1477  << "\t" << "engine.stopRequested_ = true;" << endl
1478  << "\t" << "updateFUOutputs_" << globalSymbolSuffix_
1479  << "(engine);" << endl
1480  << "}" << endl;
1481 
1482  *os_ << "{ engine.programCounter_ = engine.jumpTarget_; "
1483  << "engine.lastExecutedInstruction_ = " << address
1484  << "; return; }" << endl;
1485  // Generate shutdown code after the last instruction
1486  if (address == program_.lastInstruction().address().location()) {
1487  generateShutdownCode(address);
1488  }
1489 
1490  *os_ << endl << "} /* end function */" << endl << endl;
1491  }
1492 }
1493 
1494 /**
1495  * Generates code for calling triggered operations
1496  *
1497  * @param op The operation to be triggered
1498  * @return A string containing the generated C++ code
1499  */
1500 string
1502  const TTAMachine::HWOperation& op) {
1503 
1504  vector<string> operands;
1505  string source = "EXEC_OPERATION(";
1506 
1507  // grab all operands and initialize them to the operand table
1508  for (int i = 1; op.port(i) != NULL; ++i) {
1509  if (op.port(i)->isInput()) {
1510  operands.push_back(symbolGen_.portSymbol(*op.port(i)));
1511  } else {
1512  operands.push_back(std::string("outputvalue")+Conversion::toString(i));
1513  }
1514  }
1515 
1516  if (isStoreOperation(op.name())) {
1517  return generateStoreTrigger(op);
1518  } else if (isLoadOperation(op.name())) {
1519  return generateLoadTrigger(op);
1520  }
1521  OperationDAG* dag = &operationPool_.operation(op.name().c_str()).dag(0);
1522 
1523  std::string simCode =
1525 
1526  for (int i = 1, tmp = 1; op.port(i) != NULL; ++i) {
1527  if (op.port(i)->isOutput()) {
1528 
1529  std::string outValueStr;
1530  // add output values as delayed assignments
1531  std::string outputStr = std::string("outputvalue") + Conversion::toString(i);
1532  size_t ovLen = outputStr.length() + 3;
1533  while (simCode.find(outputStr + " = ") != string::npos) {
1534  std::size_t begin = simCode.find(outputStr+" = ");
1535  std::size_t end = simCode.find(";", begin);
1536  outValueStr = simCode.substr(begin+ovLen,(end-begin-ovLen));
1537  simCode.erase(begin, end-begin);
1538  }
1539 
1540  if (outValueStr.empty()) {
1541  std::string msg = "Machine has bound outport not used by op: ";
1542  msg += op.name();
1543  msg += " port index: ";
1544  msg += Conversion::toString(i);
1545  throw IllegalMachine(__FILE__,__LINE__,__func__,msg);
1546  }
1547 
1548  // generate new unique name for it
1549  string tempVariable = symbolGen_.generateTempVariable();
1550 
1551  if (simCode.find(outValueStr) == string::npos) {
1552  continue;
1553  }
1554 
1555  while(simCode.find(outValueStr) != string::npos) {
1556  string::iterator it = simCode.begin() + simCode.find(outValueStr);
1557  simCode.replace(it, it + outValueStr.length(), tempVariable);
1558  }
1559 
1560  simCode.append("\n" + generateAddFUResult(*op.port(i),
1561  tempVariable, op.latency()));
1562  tmp++;
1563  } // end isOutput
1564  } // end for
1565 
1566  // fix the names of the tmp[n] values to unique ones so there can be
1567  // multiple in same BB.
1568  while (simCode.find("SimValue tmp") != string::npos) {
1569  std::size_t begin = simCode.find("SimValue tmp");
1570  std::size_t end = simCode.find(";", begin);
1571  std::string tmpName = simCode.substr(begin+9,(end-begin-9));
1572  string tempVariable = symbolGen_.generateTempVariable();
1573 
1574  while(simCode.find(tmpName) != string::npos) {
1575  string::iterator it = simCode.begin() + simCode.find(tmpName);
1576  simCode.replace(it,it + tmpName.length(), tempVariable);
1577  }
1578  }
1579 
1580  return simCode;
1581 }
1582 
1583 /**
1584  * Generates a faster version of specific store triggers
1585  * @param o The store operation (either stw, sth or stq)
1586  */
1587 string
1589  const TTAMachine::HWOperation& op) {
1590  string address = symbolGen_.portSymbol(*op.port(1)) + ".uIntWordValue()";
1591  string dataToWrite = symbolGen_.portSymbol(*op.port(2)) + ".uIntWordValue()";
1592  string memory = symbolGen_.DAMemorySymbol(op.parentUnit()->name());
1593  string method;
1594 
1595  const MemoryOperationDescription& memOpDesc = supportedMemoryOps.at(
1596  op.name());
1597  method = "fastWrite";
1598  if (memOpDesc.mauCount > 1) {
1599  method += std::to_string(memOpDesc.mauCount) + "MAUs";
1600  if (memOpDesc.mauOrder == MAUOrder::littleEndian) {
1601  method += "LE";
1602  } else { // big-endian
1603  method += "BE";
1604  }
1605  } else {
1606  method += "MAU";
1607  }
1608 
1609  return memory + "." + method + "(" + address + ", " + dataToWrite + ");";
1610 }
1611 
1612 /**
1613  * Generates a faster version of specific load triggers
1614  * @param op The load operation (either ldw, ldq, ldh, ldhu, or ldqu)
1615  */
1616 string
1618  const TTAMachine::HWOperation& op) {
1619  const FunctionUnit& fu = *op.parentUnit();
1620  std::stringstream ss;
1621  string address = symbolGen_.portSymbol(*op.port(1)) + ".uLongWordValue()";
1622  string memory = symbolGen_.DAMemorySymbol(op.parentUnit()->name());
1623  string MAUSize = Conversion::toString(fu.addressSpace()->width());
1624  string method;
1625  string extensionMode = "SIGN_EXTEND";
1626  string resultSignExtend;
1627  string temp = symbolGen_.generateTempVariable();
1628 
1629  const MemoryOperationDescription& memOpDesc = supportedMemoryOps.at(
1630  op.name());
1631  method = "fastRead";
1632  if (memOpDesc.mauCount > 1) {
1633  method += std::to_string(memOpDesc.mauCount) + "MAUs";
1634  if (memOpDesc.mauOrder == MAUOrder::littleEndian) {
1635  method += "LE";
1636  } else { // big-endian
1637  method += "BE";
1638  }
1639  } else {
1640  method += "MAU";
1641  }
1642 
1643  if (memOpDesc.extensionMode == ExtensionMode::sign) {
1644  extensionMode = "SIGN_EXTEND";
1645  } else {
1646  extensionMode = "ZERO_EXTEND";
1647  }
1648 
1649  resultSignExtend = temp + " = " + extensionMode
1650  + "(" + temp + ", (" + MAUSize + "*"
1651  + std::to_string(memOpDesc.mauCount) +"));";
1652 
1653  ss << "ULongWord " << temp << "; " << memory + "." << method << "("
1654  << address << ", " << temp << "); ";
1655 
1656  ss << resultSignExtend << " ";
1657 
1658  ss << generateAddFUResult(*op.port(2), temp, op.latency());
1659 
1660  return ss.str();
1661 }
1662 
1663 /**
1664  * Generates code for adding a result to FU's output port
1665  *
1666  * Handles static latency simulation in case it is possible, otherwise
1667  * reverts back to older dynamic model.
1668  *
1669  * The case this function tracks is the following:
1670  *
1671  * 1) Instruction address > basic block start + latency
1672  * 2) Trigger not inside a guard
1673  * 3) Result must be ready in the same basic block
1674  * 4) No overlapping writes of any kind
1675  *
1676  * @param resultPort FU result port to set the value to
1677  * @param value value to set as a result
1678  * @param latency latency of the operation
1679  * @return the generated code for putting the results.
1680  */
1681 std::string
1683  const TTAMachine::FUPort& resultPort,
1684  const std::string& value,
1685  int latency) {
1686 
1687  std::stringstream ss;
1688  const FunctionUnit& fu = *resultPort.parentUnit();
1689  const int writeTime = instructionNumber_ + latency;
1690 
1691  AddressMap::iterator bbEnd = bbEnds_.lower_bound(instructionNumber_);
1692 
1693  const bool resultInSameBasicBlock = bbEnd->first ==
1694  bbEnds_.lower_bound(writeTime)->first;
1695 
1696  const int bbStart = bbEnd->second;
1697  bool staticSimulationPossible = false;
1698  const std::string destination = symbolGen_.portSymbol(resultPort);
1699 
1700  int lastWrite = 0;
1701  if (lastFUWrites_.find(destination) != lastFUWrites_.end()) {
1702  lastWrite = lastFUWrites_[destination];
1703  }
1704 
1705  // If no more pending results are coming outside or inside the basic block,
1706  // no guard of any kind and result will be ready in the same basic block,
1707  // then static latency simulation can be done.
1708  if ((writeTime >= bbStart + fu.maxLatency())
1709  && lastGuardBool_.empty() && resultInSameBasicBlock
1710  && (writeTime > lastWrite)) {
1711  staticSimulationPossible = true;
1712 
1713  for (int i = instructionNumber_ + 1; i < writeTime
1714  && staticSimulationPossible; ++i) {
1715 
1716  Instruction& instr = program_.instructionAt(i);
1717  for (int j = 0; j < instr.moveCount(); ++j) {
1718  if ((instr.move(j).isTriggering() && fu.name()
1719  == instr.move(j).destination().functionUnit().name()) ||
1720  (instr.move(j).source().isGPR() &&
1721  instr.move(j).source().port().name()==resultPort.name())) {
1722  staticSimulationPossible = false;
1723  break;
1724  }
1725  }
1726  }
1727  }
1728 
1729  if (staticSimulationPossible) { // Add a new delayed assignment
1730  DelayedAssignment assignment = { value, destination,
1731  symbolGen_.FUResultSymbol(resultPort) };
1732  delayedFUResultWrites_.insert(std::make_pair(writeTime, assignment));
1733  } else { // revert to old dynamic FU result model
1734  ss << "engine.addFUResult(" << symbolGen_.FUResultSymbol(resultPort)
1735  << ", " << "engine.cycleCount_, " << value << ", " << latency << ");";
1736  if (writeTime > lastWrite) {
1737  lastFUWrites_[destination] = writeTime;
1738  }
1739  }
1740 
1741  return ss.str();
1742 }
1743 
1744 /**
1745  * Generates code for reading FU results from result symbol to result port
1746  *
1747  * @param destination destination port symbol
1748  * @param resultSymbol results symbol
1749  * @return generated code for getting the result
1750  */
1751 std::string
1753  const std::string& destination,
1754  const std::string& resultSymbol) {
1755  std::stringstream ss;
1756 
1757  ss << "engine.FUResult(" << destination << ", " << resultSymbol
1758  << ", engine.cycleCount_);" << endl;
1759 
1760  return ss.str();
1761 }
1762 
1763 /**
1764  * Returns the maximum possible latency from the FUs & GCU
1765  *
1766  * @return the maximum possible latency from the FUs & GCU
1767  */
1768 int
1772  for (int i = 0; i < fus.count(); ++i) {
1773  if (maxLatency < fus.item(i)->maxLatency()) {
1774  maxLatency = fus.item(i)->maxLatency();
1775  }
1776  }
1777  return maxLatency;
1778 }
1779 
1780 /**
1781  * Returns the output ports of a function unit
1782  *
1783  * @param fu The function unit
1784  *
1785  * @return A vector of output ports of a function unit
1786  */
1787 std::vector<TTAMachine::Port*>
1789  const TTAMachine::FunctionUnit& fu) const {
1790  std::vector<TTAMachine::Port*> ports;
1791  for (int i = 0; i < fu.portCount(); ++i) {
1792  if (fu.port(i)->isOutput()) {
1793  ports.push_back(fu.port(i));
1794  }
1795  }
1796  return ports;
1797 }
1798 
1800  std::ostream& stream) {
1801  for (GuardPipeline::iterator i = guardPipeline_.begin();
1802  i != guardPipeline_.end(); i++) {
1803  const std::string& regName = i->first;
1804  for (int j = i->second -1 ; j > 0; j--) {
1805  stream << "guard_pipeline_" << regName << "_" << j << " = "
1806  << "guard_pipeline_" << regName << "_" << j -1
1807  << ";" << std::endl;
1808  }
1809  }
1810 }
1811 
1813  std::ostream& stream) {
1814  for (GuardPipeline::iterator i = guardPipeline_.begin();
1815  i != guardPipeline_.end(); i++) {
1816  const std::string& regName = i->first;
1817  for (int j = 0; j < i->second ; j++) {
1818  stream << "bool guard_pipeline_" + regName << "_" << j <<
1819  ";" << std::endl;
1820  }
1821  }
1822 }
1823 
1825  const TTAMachine::RegisterGuard& rg) {
1826  const RegisterFile* rf = rg.registerFile();
1827  std::string regName = "RF_" + rf->name() + "_" +
1829  GuardPipeline::iterator i = guardPipeline_.find(regName);
1830  assert(i!= guardPipeline_.end());
1831  return "engine.guard_pipeline_RF_" +
1833  "_" + Conversion::toString(i->second -1);
1834 }
1835 
1836 // if register found from guard registe list. put the value if the just written
1837 // register into the guard pipeline.
1839  const std::string& regSymbolName, std::ostream& stream) {
1840  std::string tmpString;
1841  std::string tmpString2;
1842 
1843  const string tmpRef1 = regSymbolName;
1844 
1845  // drop ".engine" from beginning
1846  // if found, copy to tmp and take ref to tmp. not found, ref to original
1847  const string& tmpRef2 = (tmpRef1.find("engine.") == 0) ?
1848  tmpString2 = tmpRef1.substr(7) :
1849  tmpRef1;
1850 
1851  GuardPipeline::iterator i = guardPipeline_.find(tmpRef2);
1852  if ( i != guardPipeline_.end()) {
1853  stream << "engine.guard_pipeline_" << tmpRef2 << "_0 "
1854  << " = !(MathTools::fastZeroExtendTo("
1855  << tmpRef1 << ".uIntWordValue(), "
1856  << tmpRef1 << ".width()) == 0u);" << std::endl;
1857  return true;
1858  }
1859  return false;
1860 }
1861 
1862 
1863 /**
1864  * Returns list of all supported memory accessing operations for compiled
1865  * simulation.
1866  */
1869  TCETools::CIStringSet result;
1870  for (auto& pair : supportedMemoryOps) {
1871  result.insert(pair.first);
1872  }
1873  return result;
1874 }
1875 
1876 
1877 bool
1879  auto it = supportedMemoryOps.find(opName);
1880  if (it == supportedMemoryOps.end()) return false;
1881 
1882  return (it->second.accessMode == AccessMode::write);
1883 }
1884 
1885 bool
1886 CompiledSimCodeGenerator::isLoadOperation(const std::string& opName) {
1887  auto it = supportedMemoryOps.find(opName);
1888  if (it == supportedMemoryOps.end()) return false;
1889 
1890  return (it->second.accessMode == AccessMode::read);
1891 }
1892 
CompiledSimCodeGenerator::headerFile_
std::string headerFile_
Header filename.
Definition: CompiledSimCodeGenerator.hh:276
CompiledSimCodeGenerator::usedGuardSymbols_
std::map< std::string, std::string > usedGuardSymbols_
Temporary list of the used guard bool symbols per instruction.
Definition: CompiledSimCodeGenerator.hh:253
CompiledSimCodeGenerator::exitPoints_
std::set< InstructionAddress > exitPoints_
Program exit point addresses.
Definition: CompiledSimCodeGenerator.hh:255
TTAMachine::Guard
Definition: Guard.hh:55
CompiledSimCompiler::COMPILED_SIM_SO_FLAGS
static const char * COMPILED_SIM_SO_FLAGS
flags used when compiling .so files
Definition: CompiledSimCompiler.hh:66
CompiledSimSymbolGenerator::immediateRegisterSymbol
std::string immediateRegisterSymbol(const TTAProgram::Terminal &terminal) const
Definition: CompiledSimSymbolGenerator.cc:178
TTAProgram::Terminal::isFUPort
virtual bool isFUPort() const
Definition: Terminal.cc:118
CompiledSimCodeGenerator::updateSymbolsMap
void updateSymbolsMap()
Definition: CompiledSimCodeGenerator.cc:859
CompiledSimCodeGenerator::guardPipelineTopSymbol
std::string guardPipelineTopSymbol(const TTAMachine::RegisterGuard &guard)
Definition: CompiledSimCodeGenerator.cc:1824
SimValue::intValue
int intValue() const
Definition: SimValue.cc:895
CompiledSimCodeGenerator::supportedMemoryOperations
static TCETools::CIStringSet supportedMemoryOperations()
Definition: CompiledSimCodeGenerator.cc:1868
TTAProgram
Definition: Estimator.hh:65
TTAProgram::Immediate::value
TerminalImmediate & value() const
Definition: Immediate.cc:103
UIntWord
Word UIntWord
Definition: BaseType.hh:144
CompiledSimCodeGenerator::instructionNumber_
int instructionNumber_
Absolute instruction # being processed.
Definition: CompiledSimCodeGenerator.hh:238
TTAProgram::Program
Definition: Program.hh:63
CompiledSimCodeGenerator::generateInstruction
void generateInstruction(const TTAProgram::Instruction &instruction)
Definition: CompiledSimCodeGenerator.cc:1136
TTAProgram::Move::isTriggering
bool isTriggering() const
Definition: Move.cc:284
ProcedureBBRelations::procedureStart
std::map< InstructionAddress, InstructionAddress > procedureStart
Procedure start per basic block starts.
Definition: CompiledSimCodeGenerator.hh:80
OperationPool::operation
Operation & operation(const char *name)
Definition: OperationPool.cc:99
CompiledSimCodeGenerator::isProcedureBegin_
bool isProcedureBegin_
Are we at the beginning of a new procedure?
Definition: CompiledSimCodeGenerator.hh:244
InstructionAddress
UInt32 InstructionAddress
Definition: BaseType.hh:175
CompiledSimSymbolGenerator::disablePrefix
void disablePrefix()
Definition: CompiledSimSymbolGenerator.cc:87
CompiledSimCodeGenerator::basicBlocks
virtual AddressMap basicBlocks() const
Definition: CompiledSimCodeGenerator.cc:317
FileSystem.hh
CompiledSimCodeGenerator::handleOperationWithoutDag
std::string handleOperationWithoutDag(const TTAMachine::HWOperation &op)
Definition: CompiledSimCodeGenerator.cc:974
CompiledSimCodeGenerator::createdFiles
virtual StringSet createdFiles() const
Definition: CompiledSimCodeGenerator.cc:307
BaseType.hh
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
CompiledSimCodeGenerator::guardPipeline_
GuardPipeline guardPipeline_
Definition: CompiledSimCodeGenerator.hh:301
TTAProgram::Instruction::move
Move & move(int i) const
Definition: Instruction.cc:193
TTAMachine::PortGuard::port
FUPort * port() const
CompiledSimCodeGenerator::generateConstructorCode
void generateConstructorCode()
Definition: CompiledSimCodeGenerator.cc:513
TTAProgram::Program::procedureCount
int procedureCount() const
Definition: Program.cc:610
machine
TTAMachine::Machine * machine
the architecture definition of the estimated processor
Definition: EstimatorCmdLineUI.cc:59
CompiledSimCodeGenerator::AddressMap
std::map< InstructionAddress, InstructionAddress > AddressMap
A type for storing address-to-address combinations.
Definition: CompiledSimCodeGenerator.hh:104
TTAMachine::HWOperation
Definition: HWOperation.hh:52
BoostGraph::node
Node & node(const int index) const
ConflictDetectionCodeGenerator::detectConflicts
std::string detectConflicts(const TTAMachine::HWOperation &op)
Definition: ConflictDetectionCodeGenerator.cc:257
TTAMachine::RegisterGuard::registerIndex
int registerIndex() const
TTAMachine::BaseFUPort::parentUnit
FunctionUnit * parentUnit() const
Definition: BaseFUPort.cc:96
BasicBlockNode::originalEndAddress
InstructionAddress originalEndAddress() const
Definition: BasicBlockNode.cc:174
OperationDAGConverter.hh
TTAMachine::Bus::width
int width() const
Definition: Bus.cc:149
CompiledSimCodeGenerator::generateTriggerCode
std::string generateTriggerCode(const TTAMachine::HWOperation &op)
Definition: CompiledSimCodeGenerator.cc:1501
CompiledSimCodeGenerator::procedureBBRelations_
ProcedureBBRelations procedureBBRelations_
Basic blocks relations to procedures and vice versa.
Definition: CompiledSimCodeGenerator.hh:262
CompiledSimSymbolGenerator::portSymbol
std::string portSymbol(const TTAMachine::Port &port) const
Definition: CompiledSimSymbolGenerator.cc:117
AssocTools::containsKey
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
TTAProgram::Instruction
Definition: Instruction.hh:57
TTAProgram::Move::isUnconditional
bool isUnconditional() const
Definition: Move.cc:154
CompiledSimCodeGenerator::lastGuardBool_
std::string lastGuardBool_
name of the last used guard variable
Definition: CompiledSimCodeGenerator.hh:251
CompiledSimCodeGenerator::generateConstructorParameters
void generateConstructorParameters()
Definition: CompiledSimCodeGenerator.cc:497
CompiledSimSymbolGenerator::operationSymbol
std::string operationSymbol(const std::string &operationName, const TTAMachine::FunctionUnit &fu) const
Definition: CompiledSimSymbolGenerator.cc:333
MapTools.hh
Procedure.hh
NullRegisterFile.hh
TTAMachine::Bus
Definition: Bus.hh:53
CompiledSimCodeGenerator::generateGuardRead
std::string generateGuardRead(const TTAProgram::Move &move)
Definition: CompiledSimCodeGenerator.cc:1035
CompiledSimCodeGenerator.hh
CompiledSimSymbolGenerator::busSymbol
std::string busSymbol(const TTAMachine::Bus &bus) const
Definition: CompiledSimSymbolGenerator.cc:205
TTAMachine::Port::width
virtual int width() const =0
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
CompiledSimCodeGenerator::generateFUOutputUpdater
void generateFUOutputUpdater()
Definition: CompiledSimCodeGenerator.cc:721
TTAMachine::ImmediateUnit::signExtends
bool signExtends() const
Definition: ImmediateUnit.hh:62
MachineInfo.hh
TTASimulationController.hh
CompiledSimCodeGenerator::generateJumpTableCode
void generateJumpTableCode()
Definition: CompiledSimCodeGenerator.cc:889
CompiledSimCodeGenerator::machine_
const TTAMachine::Machine & machine_
The machine used for simulation.
Definition: CompiledSimCodeGenerator.hh:208
CompiledSimSymbolGenerator::DAMemorySymbol
std::string DAMemorySymbol(const TTAMachine::FunctionUnit &fu) const
Definition: CompiledSimSymbolGenerator.cc:294
CompiledSimCodeGenerator::generateAdvanceClockCode
void generateAdvanceClockCode()
Definition: CompiledSimCodeGenerator.cc:783
CompiledSimCodeGenerator::handleCycleEnd_
bool handleCycleEnd_
Should we let frontend handle each cycle end.
Definition: CompiledSimCodeGenerator.hh:217
CompiledSimSymbolGenerator::returnAddressSymbol
std::string returnAddressSymbol(const TTAMachine::ControlUnit &gcu) const
Definition: CompiledSimSymbolGenerator.cc:215
CompiledSimCompiler::COMPILED_SIM_CPP_FLAGS
static const char * COMPILED_SIM_CPP_FLAGS
cpp flags used for compiled simulation
Definition: CompiledSimCompiler.hh:63
CompiledSimSymbolGenerator::operationContextSymbol
std::string operationContextSymbol(const TTAMachine::FunctionUnit &fu) const
Definition: CompiledSimSymbolGenerator.cc:258
TTAMachine::FunctionUnit::port
virtual BaseFUPort * port(const std::string &name) const
Definition: FunctionUnit.cc:145
TTAMachine::FunctionUnit::addressSpace
virtual AddressSpace * addressSpace() const
Definition: FunctionUnit.cc:580
CompiledSimCodeGenerator::isStoreOperation
static bool isStoreOperation(const std::string &opName)
Definition: CompiledSimCodeGenerator.cc:1878
Terminal.hh
Application::logStream
static std::ostream & logStream()
Definition: Application.cc:155
CompiledSimCodeGenerator::currentProcedure_
const TTAProgram::Procedure * currentProcedure_
Pointer to the current Procedure being processed.
Definition: CompiledSimCodeGenerator.hh:246
CompiledSimCodeGenerator::fuOutputPorts
std::vector< TTAMachine::Port * > fuOutputPorts(const TTAMachine::FunctionUnit &fu) const
Definition: CompiledSimCodeGenerator.cc:1788
ConflictDetectionCodeGenerator::conflictDetectionEnabled
bool conflictDetectionEnabled() const
Definition: ConflictDetectionCodeGenerator.cc:288
TTAMachine::Machine::Navigator::count
int count() const
TTAMachine::FunctionUnit::maxLatency
virtual int maxLatency() const
Definition: FunctionUnit.cc:443
DataLabel.hh
Conversion::toString
static std::string toString(const T &source)
CompiledSimCodeGenerator::maxInstructionsPerFile_
unsigned maxInstructionsPerFile_
Maximum number of instructions per engine source code file, computed from the instruction width (bus ...
Definition: CompiledSimCodeGenerator.hh:296
CompiledSimCodeGenerator::createdFiles_
StringSet createdFiles_
A list of the code files created during the process.
Definition: CompiledSimCodeGenerator.hh:233
ConflictDetectionCodeGenerator::includes
std::string includes()
Definition: ConflictDetectionCodeGenerator.cc:139
TTAMachine::BaseRegisterFile::numberOfRegisters
virtual int numberOfRegisters() const
TCEString.hh
CompiledSimCodeGenerator::currentFileName_
std::string currentFileName_
Name of the current file being processed.
Definition: CompiledSimCodeGenerator.hh:282
TTAProgram::Immediate::destination
const Terminal & destination() const
Definition: Immediate.cc:92
assert
#define assert(condition)
Definition: Application.hh:86
TTAProgram::TerminalImmediate::value
virtual SimValue value() const
Definition: TerminalImmediate.cc:75
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
CompiledSimSymbolGenerator::guardBoolSymbol
std::string guardBoolSymbol() const
Definition: CompiledSimSymbolGenerator.cc:305
CompiledSimCodeGenerator::handleJump
std::string handleJump(const TTAMachine::HWOperation &op)
Definition: CompiledSimCodeGenerator.cc:921
TTAProgram::Program::instructionAt
Instruction & instructionAt(InstructionAddress address) const
Definition: Program.cc:374
TTAMachine::HWOperation::port
virtual FUPort * port(int operand) const
Definition: HWOperation.cc:320
CompiledSimCodeGenerator::generateGuardCondition
std::string generateGuardCondition(const TTAProgram::Move &move)
Definition: CompiledSimCodeGenerator.cc:1089
TTAProgram::Terminal::isImmediateRegister
virtual bool isImmediateRegister() const
Definition: Terminal.cc:97
CompiledSimCodeGenerator::declaredSymbols_
SimValueSymbolDeclarations declaredSymbols_
A list of all symbols that are declared after the program code is ready.
Definition: CompiledSimCodeGenerator.hh:228
TTAMachine::FUPort
Definition: FUPort.hh:46
CompiledSimCodeGenerator::CompiledSimCodeGenerator
CompiledSimCodeGenerator(const TTAMachine::Machine &machine, const TTAProgram::Program &program, const TTASimulationController &controller, bool fuResourceConflictDetection, bool handleCycleEnd, bool dynamicCompilation, bool basicBlockPerFile=false, bool functionPerFile=true, const TCEString &globalSymbolPrefix="")
Definition: CompiledSimCodeGenerator.cc:160
TTASimulationController
Definition: TTASimulationController.hh:69
TTAProgram::Immediate
Definition: Immediate.hh:54
TTAMachine::Machine::controlUnit
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:345
CompiledSimCodeGenerator::moveCounter_
int moveCounter_
How many moves have we been through with?
Definition: CompiledSimCodeGenerator.hh:242
CompiledSimCodeGenerator::generateSymbolDeclarations
void generateSymbolDeclarations()
Definition: CompiledSimCodeGenerator.cc:874
HWOperation.hh
CompiledSimCodeGenerator::generateMakefile
void generateMakefile()
Definition: CompiledSimCodeGenerator.cc:245
TTAMachine::SpecialRegisterPort
Definition: SpecialRegisterPort.hh:48
CompiledSimCodeGenerator::handleRegisterWrite
bool handleRegisterWrite(const std::string &regSymbolName, std::ostream &stream)
Definition: CompiledSimCodeGenerator.cc:1838
TTAMachine::HWOperation::name
const std::string & name() const
Definition: HWOperation.cc:141
CompiledSimCodeGenerator::lastInstructionOfBB_
InstructionAddress lastInstructionOfBB_
last instruction of the current basic block
Definition: CompiledSimCodeGenerator.hh:249
Instruction.hh
CompiledSimSymbolGenerator::basicBlockSymbol
std::string basicBlockSymbol(InstructionAddress startAddress) const
Definition: CompiledSimSymbolGenerator.cc:320
TTAProgram::CodeSnippet::instructionCount
virtual int instructionCount() const
Definition: CodeSnippet.cc:205
ControlFlowGraph.hh
TTAMachine::Machine::immediateUnitNavigator
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition: Machine.cc:416
TTASimulationController::findProgramExitPoints
virtual std::set< InstructionAddress > findProgramExitPoints(const TTAProgram::Program &program, const TTAMachine::Machine &machine) const
Definition: TTASimulationController.cc:209
CompiledSimCodeGenerator::generateFUResultRead
std::string generateFUResultRead(const std::string &destination, const std::string &resultSymbol)
Definition: CompiledSimCodeGenerator.cc:1752
Environment::includeDirPaths
static std::vector< std::string > includeDirPaths()
Definition: Environment.cc:348
TTAMachine::ControlUnit
Definition: ControlUnit.hh:50
TTAMachine::RegisterGuard
Definition: Guard.hh:137
CompiledSimMove::copyToBusCode
std::string copyToBusCode() const
Definition: CompiledSimMove.cc:95
ProcedureBBRelations::basicBlockFiles
std::map< InstructionAddress, std::string > basicBlockFiles
Basic block starts and their corresponding .cpp files.
Definition: CompiledSimCodeGenerator.hh:89
TTAMachine::ControlUnit::specialRegisterPort
SpecialRegisterPort * specialRegisterPort(int index) const
Definition: ControlUnit.cc:211
CompiledSimCodeGenerator::lastFUWrites_
FUResultWrites lastFUWrites_
Last known FU result writes.
Definition: CompiledSimCodeGenerator.hh:266
CompiledSimCodeGenerator::conflictDetectionGenerator_
ConflictDetectionCodeGenerator conflictDetectionGenerator_
Conflict detection code generator.
Definition: CompiledSimCodeGenerator.hh:290
CompiledSimCodeGenerator::needGuardPipeline_
bool needGuardPipeline_
Definition: CompiledSimCodeGenerator.hh:303
CompiledSimSymbolGenerator::registerSymbol
std::string registerSymbol(const TTAProgram::Terminal &terminal) const
Definition: CompiledSimSymbolGenerator.cc:150
CompiledSimCodeGenerator::delayedFUResultWrites_
DelayedAssignments delayedFUResultWrites_
Delayed FU Result assignments.
Definition: CompiledSimCodeGenerator.hh:264
TTAProgram::Move::guard
MoveGuard & guard() const
Definition: Move.cc:345
OperationDAG
Definition: OperationDAG.hh:43
NullInstruction.hh
CompiledSimCodeGenerator::generateAddFUResult
std::string generateAddFUResult(const TTAMachine::FUPort &resultPort, const std::string &value, int latency)
Definition: CompiledSimCodeGenerator.cc:1682
CompiledSimCodeGenerator::generateGuardPipelineVariables
void generateGuardPipelineVariables(std::ostream &stream)
Definition: CompiledSimCodeGenerator.cc:1812
TTAMachine::ControlUnit::specialRegisterPortCount
int specialRegisterPortCount() const
Definition: ControlUnit.cc:185
__func__
#define __func__
Definition: Application.hh:67
CompiledSimCodeGenerator::handleOperation
std::string handleOperation(const TTAMachine::HWOperation &op)
Definition: CompiledSimCodeGenerator.cc:941
TTAMachine::Machine::functionUnitNavigator
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition: Machine.cc:380
BasicBlockNode
Definition: BasicBlockNode.hh:64
TCETools::CIStringSet
std::set< TCEString, CaseInsensitiveCmp > CIStringSet
Definition: CIStringSet.hh:49
ConflictDetectionCodeGenerator::notifyOfConflicts
std::string notifyOfConflicts()
Definition: ConflictDetectionCodeGenerator.cc:192
CompiledSimCodeGenerator::maxLatency
int maxLatency() const
Definition: CompiledSimCodeGenerator.cc:1769
CompiledSimCodeGenerator::generateShutdownCode
void generateShutdownCode(InstructionAddress address)
Definition: CompiledSimCodeGenerator.cc:710
BasicBlockNode::isNormalBB
bool isNormalBB() const
Definition: BasicBlockNode.cc:239
TTAProgram::Terminal::isGPR
virtual bool isGPR() const
Definition: Terminal.cc:107
CompiledSimCodeGenerator::gcu_
const TTAMachine::ControlUnit & gcu_
GCU.
Definition: CompiledSimCodeGenerator.hh:214
Guard.hh
TTAMachine::FunctionUnit::operationCount
virtual int operationCount() const
Definition: FunctionUnit.cc:419
Operation.hh
CompiledSimCodeGenerator::generateHeaderAndMainCode
void generateHeaderAndMainCode()
Definition: CompiledSimCodeGenerator.cc:345
TTAProgram::Terminal::immediateUnit
virtual const TTAMachine::ImmediateUnit & immediateUnit() const
Definition: Terminal.cc:240
CompiledSimSymbolGenerator::enablePrefix
void enablePrefix(const std::string &prefix)
Definition: CompiledSimSymbolGenerator.cc:79
TerminalFUPort.hh
CompiledSimMove
Definition: CompiledSimMove.hh:53
TTAProgram::Address::location
InstructionAddress location() const
CompiledSimCodeGenerator::mainFile_
std::string mainFile_
Main source filename. This includes the constructor and the simulateCycle().
Definition: CompiledSimCodeGenerator.hh:278
TTAProgram::Move
Definition: Move.hh:55
CompiledSimSymbolGenerator::FUResultSymbol
std::string FUResultSymbol(const TTAMachine::Port &port) const
Definition: CompiledSimSymbolGenerator.cc:346
OperationDAGConverter::createSimulationCode
static std::string createSimulationCode(const OperationDAG &dag, std::vector< std::string > *varReplacements=NULL)
Definition: OperationDAGConverter.cc:534
TTAMachine::ControlUnit::delaySlots
int delaySlots() const
Machine.hh
MachineInfo::longestGuardLatency
static int longestGuardLatency(const TTAMachine::Machine &mach)
Definition: MachineInfo.cc:202
CompiledSimCodeGenerator::operationPool_
OperationPool operationPool_
The operation pool.
Definition: CompiledSimCodeGenerator.hh:269
ProcedureBBRelations::basicBlockStarts
BasicBlockStarts basicBlockStarts
All basic block start addresses per procedure start.
Definition: CompiledSimCodeGenerator.hh:86
TTAMachine::FunctionUnit::operationPortCount
virtual int operationPortCount() const
Definition: FunctionUnit.cc:182
SimulatorFrontend.hh
TTAMachine::Bus::guardCount
int guardCount() const
Definition: Bus.cc:441
TTAMachine::Port::isOutput
virtual bool isOutput() const
Definition: Port.cc:308
TTAMachine::Bus::guard
Guard * guard(int index) const
Definition: Bus.cc:456
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
TTAProgram::Instruction::immediate
Immediate & immediate(int i) const
Definition: Instruction.cc:285
CompiledSimCompiler.hh
FileSystem::DIRECTORY_SEPARATOR
static const std::string DIRECTORY_SEPARATOR
Definition: FileSystem.hh:189
TTAProgram::TerminalFUPort
Definition: TerminalFUPort.hh:56
TTAProgram::Terminal::functionUnit
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition: Terminal.cc:251
CompiledSimCodeGenerator::os_
std::ostream * os_
Current output stream i.e. the above file.
Definition: CompiledSimCodeGenerator.hh:284
SimValue::unsignedValue
unsigned int unsignedValue() const
Definition: SimValue.cc:919
TTAMachine::AddressSpace::width
virtual int width() const
Definition: AddressSpace.cc:155
Operation::dagCount
virtual int dagCount() const
Definition: Operation.cc:134
CompiledSimSymbolGenerator::generateTempVariable
std::string generateTempVariable() const
Definition: CompiledSimSymbolGenerator.cc:356
TTAMachine::Machine::registerFileNavigator
virtual RegisterFileNavigator registerFileNavigator() const
Definition: Machine.cc:450
ConflictDetectionCodeGenerator::updateSymbolDeclarations
std::string updateSymbolDeclarations()
Definition: ConflictDetectionCodeGenerator.cc:213
DisassemblyRegister.hh
CompiledSimCodeGenerator::className_
std::string className_
Name of the class to be created.
Definition: CompiledSimCodeGenerator.hh:274
CompiledSimCodeGenerator::currentFile_
std::fstream currentFile_
Current file being processed.
Definition: CompiledSimCodeGenerator.hh:280
IllegalMachine
Definition: Exception.hh:878
TTAMachine::Guard::isInverted
virtual bool isInverted() const
CompiledSimCodeGenerator::StringSet
std::set< std::string > StringSet
A type for std::string sets.
Definition: CompiledSimCodeGenerator.hh:102
Program.hh
TerminalImmediate.hh
Immediate.hh
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
CompiledSimCodeGenerator::findBasicBlocks
void findBasicBlocks() const
Definition: CompiledSimCodeGenerator.cc:621
CompiledSimCodeGenerator::usedOperations_
OperationSymbolDeclarations usedOperations_
A list of used operations.
Definition: CompiledSimCodeGenerator.hh:235
CompiledSimCodeGenerator::maxInstructionsPerSimulationFunction_
unsigned maxInstructionsPerSimulationFunction_
Max for each simulation function.
Definition: CompiledSimCodeGenerator.hh:298
CompiledSimCodeGenerator::functionPerFile_
bool functionPerFile_
Should the generator start with a new file after function end.
Definition: CompiledSimCodeGenerator.hh:223
TTAMachine::Port::name
virtual std::string name() const
Definition: Port.cc:141
TCEString
Definition: TCEString.hh:53
FUPort.hh
TTAMachine::HWOperation::parentUnit
FunctionUnit * parentUnit() const
Definition: HWOperation.cc:190
CompiledSimCodeGenerator::targetDirectory_
std::string targetDirectory_
Directory where to write the source files of the engine.
Definition: CompiledSimCodeGenerator.hh:272
CompiledSimCodeGenerator::bbStarts_
AddressMap bbStarts_
The basic block map referred by start of the block as a key.
Definition: CompiledSimCodeGenerator.hh:258
TTAProgram::Instruction::immediateCount
int immediateCount() const
Definition: Instruction.cc:267
ControlUnit.hh
TTAProgram::TerminalFUPort::hwOperation
virtual const TTAMachine::HWOperation * hwOperation() const
Definition: TerminalFUPort.cc:379
TTAMachine::Machine::busNavigator
virtual BusNavigator busNavigator() const
Definition: Machine.cc:356
SpecialRegisterPort.hh
PipelineElement.hh
ExecutableInstruction.hh
ConflictDetectionCodeGenerator::symbolDeclaration
std::string symbolDeclaration(const TTAMachine::FunctionUnit &fu)
Definition: ConflictDetectionCodeGenerator.cc:156
TTAProgram::Procedure::name
TCEString name() const
Definition: Procedure.hh:66
CompiledSimCodeGenerator::generateToDirectory
virtual void generateToDirectory(const std::string &dirName)
Definition: CompiledSimCodeGenerator.cc:231
TTAMachine::Port::isInput
virtual bool isInput() const
Definition: Port.cc:298
CompiledSimCodeGenerator::isLoadOperation
static bool isLoadOperation(const std::string &opName)
Definition: CompiledSimCodeGenerator.cc:1886
TTAProgram::CodeSnippet::instructionAtIndex
virtual Instruction & instructionAtIndex(int index) const
Definition: CodeSnippet.cc:285
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
CompiledSimCodeGenerator::dynamicCompilation_
bool dynamicCompilation_
Is this a dynamic compiled simulation?
Definition: CompiledSimCodeGenerator.hh:219
CompiledSimCodeGenerator::symbolGen_
CompiledSimSymbolGenerator symbolGen_
The symbol generator.
Definition: CompiledSimCodeGenerator.hh:287
TTAProgram::Terminal::port
virtual const TTAMachine::Port & port() const
Definition: Terminal.cc:378
CompiledSimCodeGenerator::bbEnds_
AddressMap bbEnds_
The basic block map referred by end of the block as a key.
Definition: CompiledSimCodeGenerator.hh:260
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
DisassemblyRegister::registerName
static TCEString registerName(const TTAMachine::RegisterFile &rf, int index, char delim='.')
Definition: DisassemblyRegister.cc:95
TTAMachine::PortGuard
Definition: Guard.hh:99
TTAMachine::FunctionUnit::operation
virtual HWOperation * operation(const std::string &name) const
Definition: FunctionUnit.cc:363
program
find Finds info of the inner loops in the program
Definition: InnerLoopFinder.cc:80
CompiledSimCodeGenerator::procedureBBRelations
virtual ProcedureBBRelations procedureBBRelations() const
Definition: CompiledSimCodeGenerator.cc:330
TTAMachine::RegisterFile::guardLatency
virtual int guardLatency() const
Definition: RegisterFile.cc:333
TTAMachine::HWOperation::latency
int latency() const
Definition: HWOperation.cc:216
TTAMachine::RegisterFile
Definition: RegisterFile.hh:47
ProcedureBBRelations
A struct for tracking basic blocks and their relation to their procedures.
Definition: CompiledSimCodeGenerator.hh:78
CompiledSimCodeGenerator::generateGuardPipelineAdvance
void generateGuardPipelineAdvance(std::ostream &stream)
Definition: CompiledSimCodeGenerator.cc:1799
TTAProgram::Program::lastInstruction
Instruction & lastInstruction() const
Definition: Program.cc:463
CompiledSimCodeGenerator::generateSimulationGetter
void generateSimulationGetter()
Definition: CompiledSimCodeGenerator.cc:749
TTAProgram::MoveGuard::guard
const TTAMachine::Guard & guard() const
Definition: MoveGuard.cc:86
TTAMachine::FunctionUnit::operationPort
virtual FUPort * operationPort(const std::string &name) const
Definition: FunctionUnit.cc:224
Move.hh
CompiledSimCodeGenerator::simController_
const TTASimulationController & simController_
The simulator frontend.
Definition: CompiledSimCodeGenerator.hh:212
TTAMachine
Definition: Assembler.hh:48
TTAMachine::ControlUnit::globalGuardLatency
int globalGuardLatency() const
CompiledSimCodeGenerator::basicBlockPerFile_
bool basicBlockPerFile_
Should the generator generate only one basic block per code file.
Definition: CompiledSimCodeGenerator.hh:221
CompiledSimSymbolGenerator::moveOperandSymbol
std::string moveOperandSymbol(const TTAProgram::Terminal &terminal, const TTAProgram::Move &move) const
Definition: CompiledSimSymbolGenerator.cc:228
DS
#define DS
Definition: LLVMBackend.cc:124
CompiledSimCodeGenerator::generateLoadTrigger
std::string generateLoadTrigger(const TTAMachine::HWOperation &op)
Definition: CompiledSimCodeGenerator.cc:1617
CompiledSimCodeGenerator::DelayedAssignment
Definition: CompiledSimCodeGenerator.hh:135
CompiledSimMove.hh
TTAMachine::BaseRegisterFile::width
virtual int width() const
BoostGraph::nodeCount
int nodeCount() const
CompiledSimCodeGenerator::generateStoreTrigger
std::string generateStoreTrigger(const TTAMachine::HWOperation &op)
Definition: CompiledSimCodeGenerator.cc:1588
TTAMachine::RegisterGuard::registerFile
const RegisterFile * registerFile() const
CompiledSimCodeGenerator::instructionCounter_
int instructionCounter_
Istruction counter for checking how many instructions to put per file.
Definition: CompiledSimCodeGenerator.hh:240
CompiledSimCodeGenerator::generateSimulationCode
void generateSimulationCode()
Definition: CompiledSimCodeGenerator.cc:598
TTAProgram::Program::procedure
Procedure & procedure(int index) const
Definition: Program.cc:622
TTAProgram::Procedure
Definition: Procedure.hh:55
OperationPool.hh
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
CodeLabel.hh
OperationContext.hh
ConflictDetectionCodeGenerator::advanceClockCode
std::string advanceClockCode()
Definition: ConflictDetectionCodeGenerator.cc:234
Operation::dag
virtual OperationDAG & dag(int index) const
Definition: Operation.cc:148
CompiledSimCodeGenerator::updateDeclaredSymbolsList
void updateDeclaredSymbolsList()
Definition: CompiledSimCodeGenerator.cc:799
BasicBlockNode::originalStartAddress
InstructionAddress originalStartAddress() const
Definition: BasicBlockNode.cc:162
TTAProgram::Instruction::moveCount
int moveCount() const
Definition: Instruction.cc:176
CompiledSimCodeGenerator::globalSymbolSuffix_
TCEString globalSymbolSuffix_
Definition: CompiledSimCodeGenerator.hh:305
CompiledSimCodeGenerator::generateHaltCode
std::string generateHaltCode(const std::string &message="")
Definition: CompiledSimCodeGenerator.cc:775
CompiledSimCodeGenerator::program_
const TTAProgram::Program & program_
The simulated program.
Definition: CompiledSimCodeGenerator.hh:210
CompiledSimCodeGenerator::generateProcedureCode
void generateProcedureCode(const TTAProgram::Procedure &procedure)
Definition: CompiledSimCodeGenerator.cc:691
TTAProgram::Instruction::address
Address address() const
Definition: Instruction.cc:327
TTAMachine::BaseFUPort::width
virtual int width() const
Definition: BaseFUPort.cc:109
CompiledSimSymbolGenerator.hh
ControlFlowGraph
Definition: ControlFlowGraph.hh:100
CompiledSimCodeGenerator::declaredFunctions_
StringSet declaredFunctions_
A set of all the declared functions.
Definition: CompiledSimCodeGenerator.hh:231
ConflictDetectionCodeGenerator::extraInitialization
std::string extraInitialization()
Definition: ConflictDetectionCodeGenerator.cc:174
TTAMachine::Machine
Definition: Machine.hh:73
FunctionUnit.hh
CompiledSimCodeGenerator::~CompiledSimCodeGenerator
virtual ~CompiledSimCodeGenerator()
Definition: CompiledSimCodeGenerator.cc:221
MoveGuard.hh
CompiledSimCodeGenerator::addDeclaredSymbol
void addDeclaredSymbol(const std::string &name, int width)
Definition: CompiledSimCodeGenerator.cc:909
TTAMachine::ImmediateUnit
Definition: ImmediateUnit.hh:50