OpenASIP 2.2
Loading...
Searching...
No Matches
SimulatorFrontend.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2012 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 SimulatorFrontend.cc
26 *
27 * Implementation of SimulatorFrontend class
28 *
29 * @author Pekka Jääskeläinen 2005,2010-2012 (pjaaskel-no.spam-cs.tut.fi)
30 *
31 * @note rating: red
32 */
33
34#include <string>
35#include <fstream>
36#include <sstream>
37#include <iomanip>
38#include <ctime>
39#include <iostream>
40
41#include "CompilerWarnings.hh"
42IGNORE_CLANG_WARNING("-Wkeyword-macro")
43#include <boost/regex.hpp>
45#include <boost/thread.hpp>
46#include <boost/bind.hpp>
47#include <boost/version.hpp>
48
49#include "Binary.hh"
50#include "BinaryReader.hh"
51#include "BinaryStream.hh"
52#include "ADFSerializer.hh"
53#include "SimulatorFrontend.hh"
54#include "FileSystem.hh"
55#include "Application.hh"
56#include "Conversion.hh"
57#include "SimulatorToolbox.hh"
62#include "UniversalMachine.hh"
64#include "HWOperation.hh"
65#include "RegisterFileState.hh"
66#include "StringTools.hh"
67#include "MachineState.hh"
69#include "ControlUnit.hh"
70#include "FUPort.hh"
71#include "GCUState.hh"
72#include "NullMachine.hh"
74#include "TPEFProgramFactory.hh"
75#include "POMDisassembler.hh"
77#include "MemorySystem.hh"
78#include "TPEFBaseType.hh"
79#include "Program.hh"
80#include "NullProgram.hh"
81#include "Procedure.hh"
82#include "Instruction.hh"
83#include "ExecutionTracker.hh"
84#include "ExecutionTrace.hh"
85#include "SimulatorConstants.hh"
86#include "StopPointManager.hh"
87#include "TPEFTools.hh"
88#include "UtilizationStats.hh"
90#include "RFAccessTracker.hh"
91#include "BusTracker.hh"
92#include "InstructionMemory.hh"
95#include "POMValidator.hh"
97#include "Exception.hh"
98#include "DataMemory.hh"
99#include "DataDefinition.hh"
101#include "TCEDBGController.hh"
102#include "CustomDBGController.hh"
105#include "MachineInfo.hh"
106#include "DirectAccessMemory.hh"
107#include "IdealSRAM.hh"
108#include "RemoteMemory.hh"
109#include "MemoryProxy.hh"
110#include "DisassemblyFUPort.hh"
111
112using namespace TTAMachine;
113using namespace TTAProgram;
114using namespace TPEF;
115
116
117/**
118 * Constructor.
119 */
121 currentMachine_(NULL), simCon_(NULL),
122 machineOwnedByFrontend_(false), currentProgram_(NULL),
123 programFileName_(""), programOwnedByFrontend_(false),
124 currentBackend_(backendType),
125 disassembler_(NULL), executionTracing_(false),
126 busTracing_(false),
127 rfAccessTracing_(false), procedureTransferTracing_(false),
128 saveProfileData_(false), saveUtilizationData_(false),
129 stopPointManager_(NULL), tpef_(NULL),
130 fuResourceConflictDetection_(true),
131 printNextInstruction_(true), printSimulationTimeStatistics_(false),
132 staticCompilation_(true), traceFileNameSetByUser_(false), outputStream_(0),
133 memoryAccessTracking_(false), eventHandler_(NULL), lastRunCycleCount_(0),
134 lastRunTime_(0.0), simulationTimeout_(0), leaveCompiledDirty_(false),
135 callHistoryLength_(0), zeroFillMemoriesOnReset_(true) {
136
137 if (backendType == SIM_COMPILED) {
139 setFUResourceConflictDetection(false); // disabled by default
141 } else {
143 }
144}
145
146/**
147 * Destructor.
148 */
150
152
154 delete currentMachine_;
155 currentMachine_ = NULL;
156 }
157
159 delete currentProgram_;
160 currentProgram_ = NULL;
161 programFileName_ = "";
162 }
163
164 delete disassembler_;
165 disassembler_ = NULL;
166 delete simCon_;
167 simCon_ = NULL;
168 delete stopPointManager_;
169 stopPointManager_ = NULL;
170 delete tpef_;
171 tpef_ = NULL;
172 delete eventHandler_;
173 eventHandler_ = NULL;
174 delete simCon_;
175 simCon_ = NULL;
177
179
180}
181
182/**
183 * Loads a new program to be simulated.
184 *
185 * The loaded program is not owned by SimulatorFrontend and thus won't be
186 * deleted by it when not needed anymore. Simulation is initialized using
187 * the previously loaded machine. This function assumes that machine is
188 * loaded before calling it. Program is aborted otherwise.
189 *
190 * @param program The program to be loaded.
191 * @exception IOException If tracing is enabled and could not be initialized.
192 * @exception Exception Any exception thrown while building the simulation
193 * models are passed on.
194 * @todo Throw when machine is not loaded.
195 * @todo Implement checking for already running simulation.
196 */
197void
199
200 if (currentMachine_ == NULL)
201 throw Exception(
202 __FILE__, __LINE__, __func__,
203 "Cannot load a program without loading a machine first.");
204
206 delete currentProgram_;
207 currentProgram_ = NULL;
208 }
209
212
216}
217
218/**
219 * Loads a new machine to be simulated.
220 *
221 * The loaded machine is not owned by SimulatorFrontend and thus won't be
222 * deleted by it when not needed anymore.
223 *
224 * @param program The machine to be loaded.
225 */
226void
229 delete currentMachine_;
230 currentMachine_ = NULL;
231 }
234
237 delete currentProgram_;
238 currentProgram_ = NULL;
239 }
240 delete simCon_;
241 simCon_ = NULL;
242
243 // compiled sim does not handle long guard latencies nor 64 bits correctly
244 // remove when fixed.
245 if (isCompiledSimulation() &&
247 machine.is64bit())) {
249 // TODO: warn about this, when the warning can be ignored
250 // by tests.
251 }
254}
255
256/**
257 * Returns a read-only reference to the currently loaded machine.
258 *
259 * @return A read-only reference to the currently loaded machine, if none,
260 * returns a NullMachine instance.
261 */
262const Machine&
264 if (currentMachine_ == NULL)
265 return NullMachine::instance();
266 return *currentMachine_;
267}
268
269/**
270 * Returns a read-only reference to the currently loaded program.
271 *
272 * @return A read-only reference to the currently loaded program, if none,
273 * returns a NullProgram instance.
274 */
275const Program&
277 if (currentProgram_ == NULL)
278 return NullProgram::instance();
279 return *currentProgram_;
280}
281
282/**
283 * Loads a new program to be simulated from a TPEF file.
284 *
285 * The loaded program will be owned by SimulatorFrontend and thus be
286 * deleted by it when not needed anymore.
287 *
288 * @param fileName The name of the TPEF file to be loaded.
289 * @exception FileNotFound If the file cannot be found.
290 * @exception SimulationStillRunning If an old simulation is still running.
291 * @exception IllegalProgram If the TPEF was erroneus or the program invalid.
292 * @exception Exception Any exception thrown while building the simulation
293 * models are passed on.
294 * @todo Implement after Program builder is done.
295 * @todo Throw when machine is not loaded.
296 * @todo Implement checking for already running simulation.
297 */
298void
299SimulatorFrontend::loadProgram(const std::string& fileName) {
300
301 if (currentMachine_ == NULL)
302 throw Exception(
303 __FILE__, __LINE__, __func__,
304 "Cannot load a program without loading a machine first.");
305
307
308 if (!FileSystem::fileExists(fileName)) {
309 throw FileNotFound(
310 __FILE__, __LINE__, __func__,
311 textGen.text(Texts::TXT_FILE_NOT_FOUND).str());
312 }
313
314 if (!FileSystem::fileIsReadable(fileName)) {
315 throw IOException(__FILE__, __LINE__, __func__, "File not readable.");
316 }
317
318 BinaryStream binaryStream(fileName);
319
320 const Program* oldProgram = currentProgram_;
321
322 try {
323 // read to TPEF Handler Module
324 tpef_ = BinaryReader::readBinary(binaryStream);
325
326 assert(tpef_ != NULL);
327 assert(currentMachine_ != NULL);
328
329 // convert the loaded TPEF to POM
331 TTAProgram::Program* program = factory.build();
332 program->finalize();
334 } catch (const Exception& e) {
335 delete tpef_;
336 tpef_ = NULL;
337 delete simCon_;
338 simCon_ = NULL;
339 std::string errorMsg = textGen.text(
341
342 if (e.errorMessage() != "")
343 errorMsg += " " + e.errorMessage();
344
345 IllegalProgram illegp(__FILE__, __LINE__, __func__, errorMsg);
346 illegp.setCause(e);
347 throw illegp;
348 }
349
350 // Validate the program against the current machine using POMValidator.
351 // TODO: this should be refactored -- the loadProgram(Program) is not
352 // checking these?
353 POMValidator validator(*currentProgram_);
354 std::set<POMValidator::ErrorCode> checks;
358
359 if (isCompiledSimulation()) {
361 }
362
363#if (!defined(HAVE_CXX11) && !defined(HAVE_CXX0X))
364 std::auto_ptr<POMValidatorResults> results(validator.validate(checks));
365#else
366 std::unique_ptr<POMValidatorResults> results(validator.validate(checks));
367#endif
368
369 if (results->errorCount() > 0) {
370 std::string errorMsg = textGen.text(
372
373 for (int i = 0; i < results->errorCount(); i++) {
374 errorMsg += "\n" + results->error(i).second;
375 }
376
377 if (isCompiledSimulation()) {
378 // Attempt without compiled simulator
381 results.reset(validator.validate(checks));
382 }
383
384 if (results->errorCount() > 0) {
385 delete tpef_;
386 tpef_ = NULL;
387 delete simCon_;
388 simCon_ = NULL;
389
390 for (int i = 0; i < results->errorCount(); i++) {
391 errorMsg += "\n" + results->error(i).second;
392 }
393
394 throw IllegalProgram(__FILE__, __LINE__, __func__, errorMsg);
395 } else {
397 << errorMsg << std::endl
398 << "Warning! Reverting to interpretive simulation engine."
399 << std::endl;
400 }
401 }
402
404 delete oldProgram;
405 oldProgram = NULL;
406 }
407
408 delete disassembler_;
409 disassembler_ = NULL;
410
412
415
416 // Dump simulation traces in the same directory as loaded program file
417 // or user-defined directory
418 std::string traceDir = Environment::simTraceDirPath();
419 if (traceDir == "") {
420 programFileName_ = fileName;
421 } else {
424 FileSystem::fileOfPath(fileName);
425 }
426
427 // tracing can't be enabled before loading program so try to initialize
428 // the tracing after program is loaded
430}
431
432/**
433 * Resets and writes initial data to the memory system stored in simulation
434 * controller from loaded TPEF.
435 *
436 * @param onlyOne initialize the data memory of the given address space only.
437 * If onlyOne is NULL, tries to intialize all data memories.
438 */
439void
441 const TTAMachine::AddressSpace* onlyOne) {
442
443 // we need tpef to get the initialization data and simcon to fetch
444 // the memory system from
445 if (currentProgram_ == NULL || simCon_ == NULL)
446 return;
447
451
452 const int dataSections = currentProgram_->dataMemoryCount();
453
454 if (dataSections < 0)
455 return;
456
457 for (int core = 0; core < 1; ++core) {
458 // data memory initialization
459 for (int i = 0; i < dataSections; ++i) {
460
461 // initialize the data memory
462 const DataMemory& data = currentProgram_->dataMemory(i);
463 const std::string addressSpaceName =
464 data.addressSpace().name();
465
466 try {
467 MemorySystem::MemoryPtr dataMemory =
468 simCon_->memorySystem(core).memory(addressSpaceName);
469
470 const AddressSpace& addressSpace =
472 addressSpaceName);
473
474 if ((onlyOne != NULL && &addressSpace != onlyOne) ||
475 (addressSpace.isShared() && core != 0)) continue;
476
477 for (int d = 0; d < data.dataDefinitionCount(); ++d) {
478 const DataDefinition& def = data.dataDefinition(d);
479 if (!def.isInitialized()) {
480 continue;
481 }
482
483 Address startAddress = def.startAddress();
484 // Check that the defined data is inside the address
485 // space.
486 if (def.startAddress().space().name() !=
487 addressSpaceName ||
488 startAddress.location() < addressSpace.start() ||
489 (startAddress.location() + def.size() - 1)
490 > addressSpace.end()) {
491
492 throw IllegalProgram(
493 __FILE__, __LINE__, __func__,
494 std::string("Initialization data for ") +
495 addressSpace.name() +
496 " is out of address space bounds.");
497 }
498 for (int m = 0; m < def.size(); m++) {
499 dataMemory->write(
500 startAddress.location() + m, def.MAU(m));
501 }
502 }
503
504 } catch (const InstanceNotFound& inf) {
505 std::string errorMsg =
508 if (inf.errorMessage() != "")
509 errorMsg += " Reason: " + inf.errorMessage();
510 delete tpef_;
511 tpef_ = NULL;
512 delete simCon_;
513 simCon_ = NULL;
514 throw IllegalProgram(
515 __FILE__, __LINE__, __func__, errorMsg);
516 }
517 }
518 }
519}
520
521/**
522 * Loads a new machine to be simulated from an ADF file.
523 *
524 * The loaded machine will be owned by SimulatorFrontend and will be
525 * deleted by it when not needed anymore.
526 *
527 * @param fileName The name of the ADF file to be loaded.
528 * @exception FileNotFound If the file cannot be found.
529 * @exception SimulationStillRunning If an old simulation is still running.
530 * @exception IllegalMachine If the ADF was erroneus.
531 *
532 */
533void
534SimulatorFrontend::loadMachine(const std::string& fileName) {
536
537 if (!FileSystem::fileExists(fileName)) {
538 throw FileNotFound(
539 __FILE__, __LINE__, __func__,
540 (textGen.text(Texts::TXT_FILE_X_NOT_FOUND) % fileName).str());
541 }
542
543 if (!FileSystem::fileIsReadable(fileName)) {
544 throw IOException(__FILE__, __LINE__, __func__, "File not readable.");
545 }
546
547 ADFSerializer serializer;
548 serializer.setSourceFile(fileName);
549
550 const Machine* oldMachine = currentMachine_;
551 try {
552 currentMachine_ = serializer.readMachine();
553 } catch (const Exception& e) {
554 IllegalMachine ime(
555 __FILE__, __LINE__, __func__,
556 textGen.text(Texts::TXT_ILLEGAL_ADF_FILE).str());
557 ime.setCause(e);
558 throw ime;
559 }
561 delete oldMachine;
562 oldMachine = NULL;
563 }
565
568 delete currentProgram_;
569 currentProgram_ = NULL;
570 }
571 delete simCon_;
572 simCon_ = NULL;
573
574 // compiled sim does not handle long guard latencies correctly.
575 // remove when fixed.
576 if (isCompiledSimulation() &&
580 // TODO: warn about this, when the warning can be ignored
581 // by tests.
582 }
585}
586
587/**
588 * Loads a new machine to be simulated from a processor configuration file.
589 *
590 * The loaded machine will be owned by SimulatorFrontend and thus be
591 * deleted by it when not needed anymore.
592 *
593 * @param fileName The name of the PCF to be loaded.
594 * @exception FileNotFound If the file cannot be found.
595 * @exception SimulationStillRunning If an old simulation is still running.
596 * @exception IllegalMachine If the ADF was erroneus.
597 *
598 */
599void
602
603 if (!FileSystem::fileExists(fileName)) {
604 throw FileNotFound(
605 __FILE__, __LINE__, __func__,
606 textGen.text(Texts::TXT_FILE_NOT_FOUND).str());
607 }
608
609 if (!FileSystem::fileIsReadable(fileName)) {
610 throw IOException(__FILE__, __LINE__, __func__, "File not readable.");
611 }
612
613 std::ifstream inputFile(fileName.c_str());
614 ProcessorConfigurationFile pcf(inputFile);
616
617 std::string adfName = "";
618 try {
619 adfName = pcf.architectureName();
620 } catch (const KeyNotFound&) {
621 throw FileNotFound(
622 __FILE__, __LINE__, __func__,
624 }
625
626 loadMachine(adfName);
627}
628
629/* Because memory models are initialized before the controller,
630 * and RemoteMemory accesses its physical memory via the controller,
631 * RemoteMemories must be further initialized here.
632 */
633void
635
636 int num_mems = memorySystem(0).memoryCount();
637 for (int i = 0; i < num_mems; i++) {
639 boost::shared_ptr<RemoteMemory> rmem =
640 boost::static_pointer_cast<RemoteMemory>(memptr);
641 assert(rmem != NULL && "not a RemoteMemory!");
642 rmem->setController(con);
643 }
644}
645
646/**
647 * Initializes a new simulation.
648 *
649 * Creates the SimulationController and initializes the program counter to
650 * point to the first executed instruction. Assumes the simulation is not
651 * running and the possible old simulation data is freed.
652 *
653 * @exception Exception There can be several types of exceptions thrown
654 * when building the simulation machine model or the preprocessed program.
655 */
656void
658
659 delete simCon_;
660 simCon_ = NULL;
661 switch(currentBackend_) {
662 case SIM_REMOTE:
663 simCon_ =
664 new TCEDBGController(
667 break;
668 case SIM_CUSTOM:
669 simCon_ =
673 break;
674 case SIM_COMPILED:
675 simCon_ =
679 break;
680 case SIM_OTA:
681 simCon_ =
684 break;
685 case SIM_NORMAL:
686 default:
687 simCon_ =
691 }
692
693 delete stopPointManager_;
695}
696
697/**
698 * Finds the state connected to the boolean register.
699 *
700 * Currently boolean register is expected to be the first register in
701 * a register file with only one register of width 1.
702 *
703 * @todo Improve evaluation when the correct way is known.
704 *
705 * @return State connected to the bool register.
706 * @exception InstanceNotFound If bool register cannot be found.
707 */
710 assert(currentMachine_ != NULL);
711
714
715 // go through all the register files in the machine
716 for (int i = 0; i < navigator.count(); ++i) {
717 RegisterFile* rf = navigator.item(i);
718 if (rf->width() == 1 && rf->numberOfRegisters() == 1) {
719 RegisterFileState& rfState =
721 return rfState.registerState(0);
722 }
723 }
724
725 throw InstanceNotFound(
726 __FILE__, __LINE__, __func__, "No boolean register found.");
727}
728
729/**
730 * Returns a string containing the value(s) of the register file
731 *
732 * @param rfName name of the register file to search for
733 * @param registerIndex index of the register. if -1, all registers are listed
734 * @return A string containing the value(s) of the register file
735 * @exception InstanceNotFound If the register cannot be found.
736 */
737std::string
739 const std::string& rfName, int registerIndex) {
740
741 return simCon_->registerFileValue(rfName, registerIndex);
742}
743
744/**
745 * Returns the current value of a IU register
746 *
747 * @param iuName name of the immediate unit
748 * @param index index of the register
749 * @return Current value of a IU register
750 */
753 const std::string& iuName, int index) {
754 assert(currentMachine_ != NULL);
755
756 return simCon_->immediateUnitRegisterValue(iuName, index);
757}
758
759/**
760 * Returns the current value of a FU port
761 *
762 * @param fuName name of the function unit
763 * @param portName name of the FU port
764 * @return Current value of a FU port
765 */
768 const std::string& fuName, const std::string& portName) {
769 assert(currentMachine_ != NULL);
770
771 return simCon_->FUPortValue(fuName, portName);
772}
773
774/**
775 * Finds the state connected to a register.
776 *
777 * @todo Improve evaluation when the parallel assembler syntax is known.
778 *
779 * @param rfName The name of the register file.
780 * @param registerIndex Index of the register in the register file.
781 * @return State connected to the register.
782 * @exception InstanceNotFound If the register cannot be found.
783 */
785SimulatorFrontend::findRegister(const std::string& rfName, int registerIndex) {
786 assert(currentMachine_ != NULL);
787
790
791 std::string regFileName = rfName;
792 if (!navigator.hasItem(rfName)) {
793 throw InstanceNotFound(
794 __FILE__, __LINE__, __func__,
795 "Register file " + rfName + " not found.");
796 }
797 try {
799 regFileName).registerState(registerIndex);
800 } catch (const OutOfRange&) {
801 throw InstanceNotFound(
802 __FILE__, __LINE__, __func__,
803 "Register index out of range");
804 }
805}
806
807/**
808 * Finds the port using a search string.
809 *
810 * The search string supported currently is of format
811 * {function unit name].{port name}.
812 *
813 * @param fuName The name of the operation or the function unit.
814 * @param portName The name of the operand or the port.
815 * @return State connected to the register.
816 * @exception InstanceNotFound If the register cannot be found.
817 */
820 const std::string& fuName, const std::string& portName) {
821 assert(currentMachine_ != NULL);
822
823 const std::string exceptionMessage =
824 std::string("No port ") + fuName + "." + portName + " found.";
825
826 // first try to fetch the port from GCU
827 PortState& foundState =
829 portName, currentMachine_->controlUnit()->name());
830
831 if (&foundState != &NullPortState::instance()) {
832 return foundState;
833 }
834
835 /// @todo Get the list of control operations from GCU instead of
836 /// hard coding like this
837 if (StringTools::ciEqual(fuName, "call") ||
838 StringTools::ciEqual(fuName, "jump")) {
839
840 // we'll try converting the port name to an operand number
841 int operandNumber = -1;
842 try {
843 operandNumber = Conversion::toInt(portName);
844 } catch (const NumberFormatException&) {
845 // portName was not a number, we cannot find it in the
846 // GCU for sure
847 throw InstanceNotFound(
848 __FILE__, __LINE__, __func__, exceptionMessage);
849 }
850
851 // it's a control flow operand, we should get the port from GCU
852 return machineState().portState(
854 operandNumber)->name(),
856 }
857
858 return machineState().portState(
861 throw InstanceNotFound(
862 __FILE__, __LINE__, __func__, exceptionMessage);
863}
864
865/**
866 * Tries to locate a readable machine state part using a search string.
867 *
868 * For a syntax of valid search strings, consult the TCE TTA assembler
869 * syntax description. All valid sources and destinations except
870 * immediate sources are valid search strings.
871 *
872 * @param searchString The string to use in search, e.g., (alu.p3).
873 * @return Current value of the state (read-only).
874 * @exception InstanceNotFound In case state couldn't be found using the
875 * search string.
876 */
877const SimValue&
878SimulatorFrontend::stateValue(std::string searchString) {
879 return state(searchString).value();
880}
881
882/**
883 * Tries to locate a readable machine state part using a search string.
884 *
885 * See stateValue() for further comment.
886 *
887 * @param searchString The string to use in search, e.g., (alu.p3 or add.3).
888 * @return The StateData object.
889 * @exception InstanceNotFound In case state couldn't be found using the
890 * search string.
891 *
892 */
894SimulatorFrontend::state(std::string searchString) {
895 if (currentMachine_ == NULL)
896 throw InstanceNotFound(
897 __FILE__, __LINE__, __func__, "State not found.");
898
899 boost::smatch parsed;
900
901 if (StringTools::ciEqual(searchString, "bool") ||
902 StringTools::ciEqual(searchString, "boolean")) {
903 return findBooleanRegister();
904 } else
905 if (StringTools::ciEqual(searchString, "ra") ||
906 StringTools::ciEqual(searchString, "return-address")) {
907 return findPort(
910 } else
911 if (regex_match(
912 searchString, parsed,
914 /// @todo Parallel fu port access (syntax?)
915 return findPort(parsed[1], parsed[2]);
916 }
917
918 throw InstanceNotFound(
919 __FILE__, __LINE__, __func__,
920 std::string("No state found with the search string '") +
921 std::string(searchString) + "'.");
922}
923
924/**
925 * Starts the wall-clock timer.
926 */
927void
932
933/**
934 * Saves the value of the wall-clock timer initialized with startTimer() to lastRunTime_ and
935 * the count of simulated cycles after startTimer() to lastRunCycleCount_.
936 */
937void
939 std::time_t now = time(NULL);
940 lastRunTime_ = now - startTime_;
941 CycleCount cycles = cycleCount();
943}
944
945/**
946 * A thread function for handling simulation timeout
947 *
948 * @param timeout timeout in seconds
949 */
950void
951timeoutThread(unsigned int timeout, SimulatorFrontend* simFE) {
952 if (timeout == 0) {
953 return;
954 }
955
956 TTASimulationController* simCon = simFE->simCon_;
957 boost::xtime xt;
958 boost::xtime xtPoll;
959#if BOOST_VERSION < 105000
960 boost::xtime_get(&xt, boost::TIME_UTC);
961#else
962 /* TIME_UTC was replaced by TIME_UTC_ in boost 1.50, to avoid
963 * clashing with a similarly named C11 macro. */
964 boost::xtime_get(&xt, boost::TIME_UTC_);
965#endif
966 unsigned int pollTime = 5; // poll time in seconds
967 xtPoll = xt;
968 xt.sec += timeout;
969
970 xtPoll.sec += pollTime;
971 while (xt.sec > xtPoll.sec) {
972 boost::thread::sleep(xtPoll);
973 xtPoll.sec += pollTime;
974 if (simCon != simFE->simCon_) {
975 return;
976 }
977 }
978 boost::thread::sleep(xt);
979
980 if (simCon != simFE->simCon_) {
981 return;
982 }
983
984 if (!simFE->hasSimulationEnded()) {
986 }
987}
988
989/**
990 * Run simulation until it's stopped for some reason.
991 *
992 * @exception SimulationExecutionError If a runtime error occurs in
993 * the simulated program.
994 * @todo Throw exception if simulation is not initialized.
995 */
996void
998 startTimer();
999 boost::thread timeout(
1000 boost::bind(timeoutThread, simulationTimeout_, this));
1001 simCon_->run();
1002 stopTimer();
1004}
1005
1006/**
1007 * Run simulation until given address.
1008 *
1009 * @exception SimulationExecutionError If a runtime error occurs in
1010 * the simulated program.
1011 * @todo Throw exception if simulation is not initialized.
1012 */
1013void
1015 startTimer();
1016 boost::thread timeout(boost::bind(timeoutThread,
1017 simulationTimeout_, this));
1018 simCon_->runUntil(address);
1019 stopTimer();
1020 // invalidate utilization statistics (they are not fresh anymore)
1022}
1023
1024/**
1025 * Advance simulation by a given amout of cycles.
1026 *
1027 * @note Does not create a timeout thread. Does not make sense here as
1028 * the step() always finishes.
1029 * @exception SimulationExecutionError If a runtime error occurs in
1030 * the simulated program.
1031 * @todo Throw exception if simulation is not initialized.
1032 */
1033void
1035 assert(simCon_ != NULL);
1036
1037 simCon_->step(count);
1038 // invalidate utilization statistics (they are not fresh anymore)
1040}
1041
1042/**
1043 * Advance simulation by a given amout of steps and skip procedure
1044 * calls.
1045 *
1046 * @param count The number of steps the simulation is advanced.
1047 * @exception SimulationExecutionError If a runtime error occurs in
1048 * the simulated program.
1049 * @todo Throw exception if simulation is not initialized.
1050 */
1051void
1053 assert(simCon_ != NULL);
1054
1055 startTimer();
1056 boost::thread timeout(boost::bind(timeoutThread,
1057 simulationTimeout_, this));
1058 simCon_->next(count);
1059 stopTimer();
1060
1061 // invalidate utilization statistics (they are not fresh anymore)
1063}
1064
1065/**
1066 * Returns the disassembly of instruction at given address.
1067 *
1068 * @param instructionAddress Address (index) of the instruction wanted to
1069 * disassemble.
1070 * @return Disassembly of an instruction.
1071 */
1072std::string
1074
1075 const Instruction& theInstruction =
1076 currentProgram_->instructionAt(instructionAddress);
1077 const Procedure& currentProc = dynamic_cast<const Procedure&>(
1078 theInstruction.parent());
1079
1080 bool firstInstructionInProcedure =
1081 (currentProc.startAddress().location() == instructionAddress);
1082
1083 std::string disassembly = "";
1084
1085 /// @todo print all labels associated at address
1086
1087 if (firstInstructionInProcedure) {
1088 disassembly += "\n" + currentProc.name() + ":\n";
1089 }
1090
1092
1093 disassembly +=
1094 Conversion::toString(instructionAddress) + ":\t\t" +
1095 disassembler_->disassembleInstruction(theInstruction);
1096 return disassembly;
1097}
1098
1099/**
1100 * Returns a string describing the current location of simulation in the
1101 * simulated program.
1102 *
1103 * If simulation has ended, returns an empty string.
1104 *
1105 * @return A description as defined in Simulator specs.
1106 */
1107std::string
1109
1110 if (hasSimulationEnded()) {
1111 return "";
1112 }
1113
1114 InstructionAddress instructionAddress = programCounter();
1115
1116 const InstructionAddress programLastAddress =
1118
1119 if (instructionAddress >= programLastAddress) {
1120 return "";
1121 }
1122
1123 const Instruction& theInstruction =
1124 currentProgram_->instructionAt(instructionAddress);
1125 const Procedure& currentProc =
1126 dynamic_cast<const Procedure&>(theInstruction.parent());
1127
1128 InstructionAddress distanceFromStart =
1129 instructionAddress - currentProc.startAddress().location();
1130
1132
1133 std::stringstream tempStream;
1134
1135 tempStream << std::setw(7) << std::right << instructionAddress << " ";
1136 tempStream
1137 << std::setw(30) << std::right <<
1138 std::string("<") + currentProc.name() + "+" +
1139 Conversion::toString(distanceFromStart) + ">" << ": "
1140 << disassembler_->disassembleInstruction(theInstruction);
1141
1142 return tempStream.str();
1143}
1144
1145/**
1146 * Initializes the disassembler.
1147 *
1148 * Creates a new POMDisassembler for the loaded program if it was not
1149 * loaded already.
1150 */
1151void
1153
1154 if (disassembler_ != NULL || currentProgram_ == NULL) {
1155 // already initialized or no program to disassemble
1156 return;
1157 }
1160}
1161
1162/**
1163 * Returns the program counter value.
1164 *
1165 * @return Program counter value.
1166 * @todo Throw exception if simulation is not initialized
1167 */
1170 assert(simCon_ != NULL);
1171 return simCon_->programCounter();
1172}
1173
1174/**
1175 * Returns the address of the last executed instruction.
1176 *
1177 * @param coreId Look at the given processor core. If -1, the currently
1178 * selected core will be used.
1179 * @return Address of the last executed instruction.
1180 */
1183 assert(simCon_ != NULL);
1184 return simCon_->lastExecutedInstruction(coreId);
1185}
1186
1187/**
1188 * Returns the current count of simulated cycles.
1189 *
1190 * @return The count of cycles.
1191 * @todo Throw exception if simulation is not initialized
1192 */
1195 assert(simCon_ != NULL);
1196 return simCon_->clockCount();
1197}
1198
1199
1200/**
1201 * Returns the current procedure.
1202 *
1203 * The current procedure is expected to be the nearest procedure behind
1204 * the program counter.
1205 *
1206 * @return The current procedure.
1207 * @todo Throw exception if simulation is not initialized
1208 */
1209const Procedure&
1211 assert(simCon_ != NULL);
1212 assert(currentProgram_ != NULL);
1214 if (address > currentProgram_->lastInstruction().address().location()) {
1216 } else {
1217 return dynamic_cast<const Procedure&>(
1219 }
1220}
1221
1222/**
1223 * Returns true if the simulation initialized and ready to run.
1224 *
1225 * @return True if simulation is initialized.
1226 */
1227bool
1232
1233/**
1234 * Returns true if the simulation has been initialized with a
1235 * program successfully.
1236 *
1237 * @return True if simulation has been initialized.
1238 */
1239bool
1241 return (simCon_ != NULL && currentProgram_ != NULL);
1242}
1243
1244/**
1245 * Returns true if a machine has been loaded for the simulation
1246 *
1247 * @return True if machine has been loaded.
1248 */
1249bool
1251 return (currentMachine_ != NULL);
1252}
1253
1254/**
1255 * Returns true if the simulation is running.
1256 *
1257 * @return True if simulation running.
1258 */
1259bool
1264
1265/**
1266 * Returns true if the simulation is stopped.
1267 *
1268 * @return True if simulation stopped.
1269 */
1270bool
1275
1276/**
1277 * Returns true if the simulation has ended, that is, the last instruction
1278 * have been executed.
1279 *
1280 * @return True if simulation has ended.
1281 */
1282bool
1287
1288
1289/**
1290 * Returns true if the current simulation engine uses compiled simulation
1291 *
1292 * @return true if the current simulation engine uses compiled simulation
1293 */
1294bool
1298
1299/**
1300 * Check if we are currently using a TCE built-in debugger. This returns true if
1301 * we are attached to a FPGA or an ASIC with on-circuit debug hardware.
1302 *
1303 * @return true if we are using a TCE debug target.
1304 */
1305bool
1309
1310/**
1311 * Check if we are currently using a custom debugger. This returns true if
1312 * we are attached to a FPGA or an ASIC with on-circuit debug hardware.
1313 *
1314 * @return true if we are using a custom debugger target.
1315 */
1316bool
1320
1321/**
1322 * Signals the simulator engine to stop simulation after the current
1323 * simulated clock cycle.
1324 *
1325 * Does nothing if simulation is not initialized or simulation is not
1326 * running.
1327 *
1328 * @param reason The reason for stopping.
1329 */
1330void
1332 if (simCon_ == NULL || !isSimulationRunning()) {
1333 return;
1334 }
1335 simCon_->prepareToStop(reason);
1336}
1337
1338/**
1339 * Returns the count of stop reasons.
1340 *
1341 * @return The count of stop reasons.
1342 */
1343unsigned int
1345 return (simCon_ != NULL && simCon_->stopReasonCount());
1346}
1347
1348/**
1349 * Returns the stop reason with the given index.
1350 *
1351 * @param index The wanted index.
1352 * @return The stop reason at the given index.
1353 * @exception OutOfRange If the given index is out of range.
1354 */
1356SimulatorFrontend::stopReason(unsigned int index) const {
1357 assert(simCon_ != NULL);
1358 return simCon_->stopReason(index);
1359}
1360
1361/**
1362 * Helper function which tells whether simulation has stopped because of
1363 * the given reason.
1364 *
1365 * @return True if the given reason was one of the reasons the simulation
1366 * was stopped.
1367 */
1368bool
1370
1371 if (simCon_ == NULL) {
1372 return false;
1373 }
1374
1375 for (size_t i = 0; i < stopReasonCount(); ++i) {
1376 if (stopReason(i) == reason) {
1377 return true;
1378 }
1379 }
1380 return false;
1381}
1382
1383/**
1384 * Returns true if simulation is stopped because of user set reason, i.e.,
1385 * breakpoint, watchpoint, memory write watchpoint, explicit (ctrl-c) stop,
1386 * etc.
1387 *
1388 * Also returns true if a runtime error was the reason for stopping, to
1389 * avoid infinite loops.
1390 *
1391 * @param true If simulation stopped because of user set stop point.
1392 */
1393bool
1395
1396 if (simCon_ == NULL) {
1397 return false;
1398 }
1399
1400 return
1403}
1404
1405/**
1406 * Initializes the trace database(s).
1407 *
1408 * In case no traces are enabled, this method does nothing. Making
1409 * multiple calls to this method is not harmful.
1410 *
1411 * @exception IOException In case trace database file could not be accessed.
1412 */
1413void
1418
1419 int coreCount = 1;
1420
1421 traceDBs_.resize(coreCount, NULL);
1422 traceDBOwned_.resize(coreCount, true);
1423 executionTrackers_.resize(coreCount, NULL);
1424 rfAccessTrackers_.resize(coreCount, NULL);
1425 procedureTransferTrackers_.resize(coreCount, NULL);
1426 busTrackers_.resize(coreCount, NULL);
1427 for (int core = 0; core < 1; ++core) {
1428
1429 ExecutionTrace* traceDB = traceDBs_.at(core);
1430 // initialize the data base for each core
1431 if (traceDB == NULL) {
1432 TCEString traceFileName;
1433 if (forcedTraceDBFileName_ == "") {
1434 // generate the file name
1435
1436 TCEString coreMarker = "";
1437 if (coreCount > 1) {
1438 coreMarker << ".core";
1439 coreMarker << core;
1440 }
1442 if (coreCount > 1) {
1443 fname << ".core";
1444 fname << core;
1445 }
1446 fname << ".trace";
1447
1448 int runningNumber = 1;
1449 while (FileSystem::fileExists(fname)) {
1450 // append ".n" where n is a running number, in case the
1451 // file exists
1452 fname = programFileName_;
1453 if (coreCount > 1) {
1454 fname << ".core";
1455 fname << core;
1456 }
1457 fname << ".trace";
1458 fname << "." << runningNumber;
1459 ++runningNumber;
1460 }
1461 traceFileName = fname;
1462 } else {
1463 traceFileName = forcedTraceDBFileName_;
1464 }
1465
1466 /// @note May throw IOException.
1467 traceDB = ExecutionTrace::open(traceFileName);
1468 traceDBs_[core] = traceDB;
1469 traceDBOwned_[core] = true;
1470 }
1471
1472 ExecutionTracker* executionTracker = executionTrackers_.at(core);
1473 if (executionTracing_ && executionTracker == NULL) {
1474 executionTracker =
1475 new ExecutionTracker(*simCon_, *traceDB);
1476 executionTrackers_[core] = executionTracker;
1477 }
1478
1479 if (rfAccessTracing_) {
1480 rfAccessTrackers_[core] =
1481 new RFAccessTracker(
1482 *this,
1483 dynamic_cast<SimulationController*>(
1484 simCon_)->instructionMemory(core));
1485 }
1488 new ProcedureTransferTracker(*this, *traceDB);
1489 }
1490
1491 if (busTracing_) {
1492 // generate the file name
1493 TCEString busTraceFileName = programFileName_;
1494 if (coreCount > 1)
1495 busTraceFileName << ".core" << core;
1496
1497 busTraceFileName << ".bustrace";
1498
1499 int runningNumber = 1;
1500 while (FileSystem::fileExists(busTraceFileName)) {
1501 // append ".n" where n is a running number, in case the
1502 // file exists
1503
1504 busTraceFileName = programFileName_;
1505 if (coreCount > 1)
1506 busTraceFileName << ".core" << core;
1507
1508 busTraceFileName << ".bustrace";
1509 busTraceFileName << "." << runningNumber;
1510 ++runningNumber;
1511 }
1512
1513 std::ostream* busTraceStream =
1514 new std::ofstream(busTraceFileName.c_str(), std::ios::out);
1515 if (!busTraceStream) {
1516 std::string errorMessage =
1517 "Unable to open bus trace file " + busTraceFileName +
1518 " for writing.";
1519 throw IOException(
1520 __FILE__, __LINE__, __func__, errorMessage);
1521 }
1522 busTrackers_[core] =
1523 new BusTracker(*this, busTraceStream);
1524 }
1525 }
1526 }
1528}
1529
1530/**
1531 * Finishes the currently running simulation.
1532 *
1533 * Flushes any simulation traces etc., but does not unload nor dealloacate
1534 * the loaded machine and the program. This is to allow restarting the
1535 * simulation without needing to reinitialize the machine and program.
1536 */
1537void
1539
1540 if (simCon_ == NULL)
1541 return;
1542
1544 if (traceDBs_.size() == 0)
1545 return;
1546
1547 for (int core = 0; core < 1; ++core) {
1548 // flush the concurrent RF access trace data
1549 ExecutionTrace* traceDB = traceDBs_.at(core);
1550 if (rfAccessTracing_) {
1552 assert(rfAccessTracker != NULL);
1555 for (RFAccessTracker::ConcurrentRFAccessIndex::const_iterator i =
1556 accesses.begin(); i != accesses.end(); ++i) {
1557 const RFAccessTracker::ConcurrentRFAccess& access = (*i).first;
1558 const std::string& rfName = access.get<0>();
1559 const std::size_t& reads = access.get<2>();
1560 const std::size_t& writes = access.get<1>();
1561 const ClockCycleCount& count = (*i).second;
1563 rfName, reads, writes, count);
1564 }
1565 }
1566
1568 const UtilizationStats& stats = utilizationStatistics(core);
1569 // save the function unit operation execution counts
1572 for (int i = 0; i <= fuNav.count(); ++i) {
1573 TTAMachine::FunctionUnit* fu = NULL;
1574 if (i < fuNav.count())
1575 fu = fuNav.item(i);
1576 else
1577 fu = machine().controlUnit();
1578 assert(fu != NULL);
1579 const ClockCycleCount totalTriggersOfFU =
1580 stats.triggerCount(fu->name());
1581
1582 if (totalTriggersOfFU == 0)
1583 continue;
1584
1585 for (int j = 0; j < fu->operationCount(); ++j) {
1586 const TTAMachine::HWOperation* op = fu->operation(j);
1587 assert(op != NULL);
1588 const std::string operationUpper =
1590
1591 const ClockCycleCount executions =
1592 stats.operationExecutions(fu->name(), operationUpper);
1593
1594 if (executions == 0)
1595 continue;
1596
1598 fu->name(), operationUpper, executions);
1599 }
1600 }
1601
1602
1603 // save the socket write counts
1604 const TTAMachine::Machine::SocketNavigator& socketNav =
1606 for (int i = 0; i < socketNav.count(); ++i) {
1607
1608 TTAMachine::Socket* socket = socketNav.item(i);
1609 assert(socket != NULL);
1610 const ClockCycleCount writes =
1611 stats.socketWrites(socket->name());
1612
1613 traceDB->addSocketWriteCount(socket->name(), writes);
1614 }
1615
1616 // save the bus write counts
1617 const TTAMachine::Machine::BusNavigator& busNav =
1619 for (int i = 0; i < busNav.count(); ++i) {
1620 TTAMachine::Bus* bus = busNav.item(i);
1621 assert(bus != NULL);
1622 const ClockCycleCount writes = stats.busWrites(bus->name());
1623
1624 traceDB->addBusWriteCount(bus->name(), writes);
1625 }
1626
1627 // save the register access stats
1630 for (int i = 0; i < rfNav.count(); ++i) {
1631 TTAMachine::RegisterFile* rf = rfNav.item(i);
1632 assert(rf != NULL);
1633
1634 int maxRegs = 0;
1635 maxRegs = rf->numberOfRegisters();
1636 for (int reg = 0; reg < maxRegs; ++reg) {
1637 ClockCycleCount reads =
1638 stats.registerReads(rf->name(), reg);
1639 ClockCycleCount writes =
1640 stats.registerWrites(rf->name(), reg);
1641 traceDB->addRegisterAccessCount(
1642 rf->name(), reg, reads, writes);
1643 }
1644 }
1645
1646 }
1647
1648 if (saveProfileData_) {
1649
1650 // save the instruction execution counts (profile data)
1651 const InstructionMemory& instructions =
1652 dynamic_cast<SimulationController*>(simCon_)->
1653 instructionMemory(core);
1654
1655 InstructionAddress firstAddress =
1657 InstructionAddress lastAddress =
1660
1661 for (InstructionAddress a = firstAddress; a <= lastAddress; ++a) {
1663 a, instructions.instructionAtConst(a).executionCount());
1664 }
1665 }
1666
1668 // save the start addresses of procedures in order to provide
1669 // possibility for more readable query outputs with traces
1670 // that include procedure data in them
1671 for (int i = 0; i < currentProgram_->procedureCount(); ++i) {
1672 const Procedure& procedure = currentProgram_->procedure(i);
1673 traceDB->addProcedureAddressRange(
1674 procedure.startAddress().location(),
1675 procedure.endAddress().location() - 1, procedure.name());
1676 }
1677 }
1678
1680
1681 if (traceDBOwned_[core]) {
1682 delete traceDBs_[core];
1683 traceDBs_[core]=NULL;
1684 }
1685 }
1686
1692}
1693
1694/**
1695 * Initializes the memory system according to the address spaces in the
1696 * loaded machine.
1697 */
1698void
1700
1701 assert (currentMachine_ != NULL);
1703 MemorySystem* firstMemorySystem = NULL;
1704
1705 for (int core = 0; core < 1; ++core) {
1706
1707 MemorySystem* memorySystem_ = new MemorySystem(machine);
1708
1709 // create a memory system for the loaded machine by going
1710 // through all address spaces in the machine and create a memory model
1711 // for each of them, except for the one of GCU's
1713
1714 std::string controlUnitASName = "";
1715 if (machine.controlUnit() != NULL &&
1717 controlUnitASName = machine.controlUnit()->addressSpace()->name();
1718 }
1719
1720 for (int i = 0; i < nav.count(); ++i) {
1721 const AddressSpace& space = *nav.item(i);
1722
1723 if (space.name() == controlUnitASName)
1724 continue;
1725
1726 const bool shared = space.isShared();
1727
1729
1730 if (shared && firstMemorySystem != NULL) {
1731 // the memory model should have been created previously
1732 // because all cores share the same memory
1733 mem = firstMemorySystem->memory(space.name());
1734 assert(mem != NULL);
1735 } else {
1736 switch (currentBackend_) {
1737 case SIM_COMPILED:
1740 space.start(), space.end(), space.width(), machine.isLittleEndian()));
1741 break;
1742 case SIM_OTA:
1743 case SIM_NORMAL:
1745 new IdealSRAM(
1746 space.start(), space.end(), space.width(), machine.isLittleEndian()));
1747 break;
1748 case SIM_REMOTE:
1749 case SIM_CUSTOM:
1751 new RemoteMemory( space, machine.isLittleEndian()));
1752
1753 break;
1754 default:
1755 throw Exception(
1756 __FILE__, __LINE__, __func__,
1757 "Internal error: memory model not specified");
1758 }
1759 // If memory tracking is enabled, memories are wrapped by
1760 // a proxy that tracks memory access.
1763 new MemoryProxy(*this, mem.get()));
1764 }
1765 }
1766 memorySystem_->addAddressSpace(space, mem, shared);
1767 }
1768 memorySystems_.push_back(memorySystem_);
1769 if (firstMemorySystem == NULL)
1770 firstMemorySystem = memorySystem_;
1771 }
1772}
1773
1774
1775/**
1776 * Kills the currently running simulation.
1777 *
1778 * Allows restarting the simulation with the loaded machine and program.
1779 * Flushes data collected during simulation to the trace file, if tracing is
1780 * enabled, and reinitializes everything that needs to be reinitialized,
1781 * such as the data memory initial values.
1782 */
1783void
1791
1792/**
1793 * Returns true in case execution tracing is enabled.
1794 *
1795 * @return True in case execution tracing is enabled.
1796 */
1797bool
1801
1802/**
1803 * Returns true in case bus tracing is enabled.
1804 *
1805 * @return True in case bus tracing is enabled.
1806 */
1807bool
1809 return busTracing_;
1810}
1811
1812/**
1813 * Returns true in case register file access tracing is enabled.
1814 *
1815 * @return True in case RF access tracing is enabled.
1816 */
1817bool
1821/**
1822 * Returns true in case procedure transfer tracing is enabled.
1823 *
1824 * @return True in case procedure transfer tracing is enabled.
1825 */
1826bool
1830
1831/**
1832 * Returns true in case profile data saving is enabled.
1833 *
1834 * @return True in case profile data saving is enabled.
1835 */
1836bool
1840
1841/**
1842 * Returns true in case utilization data saving is enabled.
1843 *
1844 * @return True in case utilization data saving is enabled.
1845 */
1846bool
1850
1851/**
1852 * Returns true if the compiled simulation uses static compilation
1853 *
1854 * @return true if the compiled simulation uses static compilation
1855 */
1856bool
1860
1861
1862/**
1863 * Returns the register file access tracker.
1864 *
1865 * @return The register file access tracker.
1866 * @exception InstanceNotFound If RF access tracking is not enabled.
1867 */
1868const RFAccessTracker&
1870 if (rfAccessTrackers_.size() == 0) {
1871 throw InstanceNotFound(
1872 __FILE__, __LINE__, __func__, "RF access tracing is disabled.");
1873 }
1874 return *rfAccessTrackers_.at(0);
1875}
1876
1877/**
1878 * Sets compiled simulation on or off
1879 *
1880 * @param value Is compiled simulation enabled or not.
1881 */
1882void
1884 // This legacy function assumes we use a simulator engine, not a
1885 // remote target.
1886 if (currentBackend_ == SIM_REMOTE) return;
1887 if (currentBackend_ == SIM_CUSTOM) return;
1888 if (value)
1890 else
1892}
1893
1894/**
1895 * Sets the execution tracing on or off.
1896 *
1897 * @param value Is execution tracing enabled or not.
1898 */
1899void
1903
1904/**
1905 * Sets the bus tracing on or off.
1906 *
1907 * @param value Is bus tracing enabled or not.
1908 */
1909void
1911 busTracing_ = value;
1912}
1913
1914/**
1915 * Sets the register file access tracing on or off.
1916 *
1917 * @param value Is register file access tracing enabled or not.
1918 */
1919void
1923
1924/**
1925 * Sets the procedure transfer tracing on or off.
1926 *
1927 * @param value Is procedure transfer tracing on or off.
1928 */
1929void
1933
1934/**
1935 * Sets the profile saving on or off.
1936 *
1937 * @param value Is profile saving on or off.
1938 */
1939void
1943
1944#if 0
1945/**
1946 * Sets the base file name of the TraceDB.
1947 *
1948 * The base file name is appended with a ".coreN" suffix for
1949 * multicore simulation.
1950 * @param fileName The file name to set.
1951 */
1952void
1953SimulatorFrontend::setTraceDBBaseFileName(const std::string& fileName) {
1954 traceFileBaseName_ = fileName;
1955 traceFileBaseNameSetByUser_ = true;
1956}
1957#endif
1958
1959/**
1960 * Sets the simulation timeout in seconds. Use zero for no timeout.
1961 *
1962 * @param value Simulation timeout in seconds.
1963 */
1964void
1966 simulationTimeout_ = value;
1967}
1968
1969/**
1970 * Sets the compiled simulator to use static or dynamic compilation.
1971 *
1972 * Has no effect when running interpretive simulation.
1973 *
1974 * @param value new value to be set
1975 */
1976void
1980
1981/**
1982 * Returns the output stream
1983 *
1984 * @return the output stream
1985 */
1986std::ostream&
1991
1992/**
1993 * Sets the default output stream
1994 *
1995 * @param stream the output stream
1996 */
1997void
1999 outputStream_ = &stream;
2000}
2001
2002/**
2003 * Sets the utilization data saving on or off.
2004 *
2005 * @param value Is utilization data saving on or off.
2006 */
2007void
2011
2012/**
2013 * Sets the FU resource conflict detection on or off.
2014 *
2015 * NOTE: this affects future simulations only. That is, if a simulation is
2016 * already initialized (program loaded), the old setting is used for that
2017 * simulation.
2018 *
2019 * @param value Should the resource conflict detection be used.
2020 */
2021void
2025
2026/**
2027 * Returns true if FU resource conflict detection is on, false if not.
2028 *
2029 * @return Returns current fu conflict detection setting.
2030 */
2031bool
2035
2036
2037/**
2038 * Sets the memory access tracking on or off.
2039 *
2040 * NOTE: this affects future simulations only. That is, if a simulation is
2041 * already initialized (program loaded), the old setting is used for that
2042 * simulation.
2043 *
2044 * @param value Should the memory access tracking be used.
2045 */
2046void
2050
2051/**
2052 * Returns true if memory access tracking is enabled.
2053 *
2054 * @return Returns current memory access tracking setting.
2055 */
2056bool
2060
2061/**
2062 * Sets the printing of the next simulated instruction to the console.
2063 *
2064 * The instruction is printed when stopping simulation.
2065 *
2066 * @param value True if the instruction should be printed.
2067 */
2068void
2072
2073/**
2074 * Returns true if the next simulated instruction will be printed to the
2075 * simulator console at simulation stop.
2076 *
2077 * @return True if the instruction should be printed.
2078 */
2079bool
2083
2084/** Sets the printing of simulation time statistics
2085 *
2086 * @param value True if the statistics should be printed out
2087 */
2091
2092/**
2093 * Returns true if the time statistics are to be printed after a command
2094 *
2095 * @return True, if the time statistics are to be printed after a command
2096 */
2100
2101/**
2102 * Returns the StopPointManager.
2103 *
2104 * Asserts if no StopPointManager is initiated.
2105 * @return The used StopPointManager.
2106 */
2112
2113/**
2114 * Returns the memory system of the currently loaded machine.
2115 *
2116 * Asserts if no simulation is initialized.
2117 * @todo Throw instead.
2118 * @return The used MemorySystem.
2119 */
2122 if (coreId == -1)
2123 return *memorySystems_.at(selectedCore());
2124 else
2125 return *memorySystems_.at(coreId);
2126}
2127
2128/**
2129 * Returns a reference to the state model of the currently loaded machine.
2130 *
2131 * @note: This should be called only for interpretive simulation which
2132 * uses the SimulationController engine. Asserts if another engine (compiled)
2133 * is used.
2134 *
2135 * @return State model of the simulated machine.
2136 */
2139 SimulationController* simCon =
2140 dynamic_cast<SimulationController*>(simCon_);
2141 assert(simCon != NULL && "Wrong TTASimulationController implementation.");
2142 return simCon->machineState(core);
2143}
2144
2145/**
2146 * Returns the current utilization statistics of the processor.
2147 *
2148 * Recalculates the statistics in case they are old, that is, simulation
2149 * has been continued or restarted since it was calculated. Should not be
2150 * called in case simulation is not initialized!
2151 *
2152 * @todo: unimplemented for remote debuggers
2153 */
2154const UtilizationStats&
2156 if (core == -1)
2157 core = selectedCore();
2158
2159 utilizationStats_.resize(1);
2160
2161 UtilizationStats* utilizationStats = utilizationStats_.at(core);
2162
2163 if (utilizationStats == NULL) {
2164 // stats calculation differs slightly for compiled & interpretive sims.
2165 if (!isCompiledSimulation()) {
2166 utilizationStats = new UtilizationStats();
2169 dynamic_cast<SimulationController*>(
2170 simCon_)->instructionMemory(core));
2171 stats.addStatistics(*utilizationStats);
2172 stats.calculate();
2173 } else {
2174 CompiledSimUtilizationStats* compiledSimUtilizationStats =
2176 CompiledSimController& compiledSimCon =
2177 dynamic_cast<CompiledSimController&>(*simCon_);
2178 compiledSimUtilizationStats->calculate(program(),
2179 *compiledSimCon.compiledSimulation());
2180 utilizationStats = compiledSimUtilizationStats;
2181 }
2182 utilizationStats_[core] = utilizationStats;
2183 }
2184 return *utilizationStats;
2185}
2186
2187
2188/**
2189 * Returns a reference to the last executed instruction.
2190 *
2191 * @return Last instruction executed.
2192 */
2195 assert(simCon_ != NULL);
2196 const InstructionMemory& memory = dynamic_cast<SimulationController*>(
2197 simCon_)->instructionMemory();
2199}
2200
2201
2202/**
2203 * Returns reference to the instruction at given address.
2204 *
2205 * @return Instruction at the given address.
2206 */
2209 InstructionAddress address) const {
2210
2211 assert(simCon_ != NULL);
2212 const InstructionMemory& memory = dynamic_cast<SimulationController*>(
2213 simCon_)->instructionMemory();
2214 return memory.instructionAtConst(address);
2215}
2216
2217/**
2218 * Returns true in case simulation with the currently loaded program
2219 * cannot be finished automatically.
2220 *
2221 * In order for this method to return false, it means that while loading
2222 * the simulated program, a *probable* ending point in the program was
2223 * detected and it is possible that when running the simulation it is possible
2224 * to finish it automatically at that position. If this method returns true
2225 * it is *impossible* to finish simulation automatically.
2226 *
2227 * @return True if it's not possible to end simulation automatically.
2228 */
2229bool
2233
2234/**
2235 * Returns the last produced execution trace database.
2236 *
2237 * The ownership of the TraceDB is transferred to the caller. That is,
2238 * it should delete it after use.
2239 *
2240 * @return The traceDB instance.
2241 */
2244 if (core == -1)
2245 core = selectedCore();
2246
2247 ExecutionTrace* last = traceDBs_[core];
2248 traceDBOwned_[core] = false;
2249 return last;
2250}
2251
2252/**
2253 * Returns the instance of SimulationEventHandler.
2254 *
2255 * @return The instance of SimulationEventHandler.
2256 * @todo This should probably be an inline function as it used to be in
2257 * the SimulatorToolbox class...
2258 */
2261 if (eventHandler_ == NULL) {
2263 }
2264 return *eventHandler_;
2265}
2266
2267/**
2268 * Returns the count of cycles simulated in the last simulation run.
2269 *
2270 * For example, if run was executed and then interrupted by the user
2271 * or a breakpoint, returns how long the run was in simulation cycles.
2272 *
2273 * @return The cycle count.
2274 */
2279
2280/**
2281 * Returns the runtime of the last simulation session in seconds.
2282 *
2283 * For example, if run was executed and then interrupted by the user
2284 * or a breakpoint, returns how long the run was in wall clock time.
2285 *
2286 * @return Simulation wall clock time in seconds.
2287 */
2288double
2292
2293/**
2294 * This method is used to report a runtime error detected in
2295 * the simulated program.
2296 *
2297 * An SE_RUNTIME_ERROR event is announced after storing the report.
2298 *
2299 * @param eventHandler Simulation event handler for the error
2300 * @param severity Severity classification of the runtime error.
2301 * @param description Textual description of the error.
2302 */
2303void
2305 RuntimeErrorSeverity severity, const std::string& description) {
2307 report.first = severity;
2308 report.second = description;
2309 programErrorReports_.push_back(report);
2311}
2312
2313/**
2314 * Returns a program error report with given severity and index.
2315 *
2316 * @param severity Severity.
2317 * @param index Index.
2318 * @return The error report text.
2319 */
2320std::string
2322 RuntimeErrorSeverity severity, std::size_t index) {
2323
2324 size_t count = 0;
2325 for (ProgramErrorDescriptionList::iterator i =
2326 programErrorReports_.begin(); i != programErrorReports_.end();
2327 ++i) {
2328 if ((*i).first == severity) {
2329 if (count == index)
2330 return (*i).second;
2331 ++count;
2332 }
2333 }
2334 return "";
2335}
2336
2337/**
2338 * Returns the count of program error reports with given severity.
2339 *
2340 * @param severity The error report severity interested in.
2341 * @return The count of error reports.
2342 */
2343std::size_t
2345 RuntimeErrorSeverity severity) {
2346 size_t count = 0;
2347 for (ProgramErrorDescriptionList::iterator i =
2348 programErrorReports_.begin(); i != programErrorReports_.end();
2349 ++i) {
2350 if ((*i).first == severity)
2351 ++count;
2352 }
2353 return count;
2354}
2355
2356/**
2357 * Clears the runtime error report list.
2358 */
2359void
2363
2364/**
2365 * Sets the length of the call history stored in memory to be used
2366 * for the simulator's debugging commands that need it.
2367 *
2368 * Setting this to 0 disables the call history tracking thus speeding
2369 * up simulation. It's disabled by default.
2370 */
2371void
2376
2377void
2379 if (callHistoryLength_ == 0 || !isMachineLoaded()) {
2381 return;
2382 } else {
2383 for (int core = 0; core < 1;
2384 ++core) {
2385 CallPathTracker* tracker =
2386 new CallPathTracker(*this, core, callHistoryLength_);
2387 callPathTrackers_.push_back(tracker);
2388 }
2389 }
2390}
2391
2392const CallPathTracker&
2394 assert(callPathTrackers_.size() > 0);
2395 if (core == -1) {
2396 return *callPathTrackers_.at(selectedCore());
2397 } else {
2398 return *callPathTrackers_.at(core);
2399 }
2400}
2401
2402/**
2403 * Compares the states of two simulator engines.
2404 *
2405 * This is useful in debugging bugs in an simulator engine implementation.
2406 * It assumes the engines have been stepped equal amount of instruction cycles
2407 * and, thus, the TTA programmer visible context should be equal.
2408 *
2409 * @param other A frontend to the other engine to compare this one to.
2410 * @param differences An optional output stream where to output information
2411 * of the possible differences.
2412 * @return true in case the states are equal, false otherwise.
2413 */
2414bool
2416 SimulatorFrontend& other, std::ostream* differences) {
2417
2418 static InstructionAddress previousPC = 0;
2419
2420 if (programCounter() != other.programCounter()) {
2421 if (differences != NULL)
2422 *differences
2423 << "SIMULATION ERROR DETECTED (PCs DIFFER)" << std::endl
2424 << "--------------------------------------" << std::endl
2425 << " cycle: " << cycleCount() << std::endl
2426 << " other's PC: " << other.programCounter() << std::endl
2427 << " this' PC: " << programCounter() << std::endl;
2428 return false;
2429 }
2430
2431 bool errorLocationPrinted = false;
2432 bool equal = true;
2433
2436 for (int i = 0; i < rfNav.count(); ++i) {
2437 TTAMachine::RegisterFile& rf = *rfNav.item(i);
2438 for (int reg = 0; reg < rf.size(); ++reg) {
2439 std::string thisReg =
2440 registerFileValue(rf.name(), reg);
2441 std::string otherReg =
2442 other.registerFileValue(rf.name(), reg);
2443 if (thisReg != otherReg) {
2444 equal = false;
2445 if (!errorLocationPrinted && differences != NULL) {
2446 std::string procedureName =
2447 (dynamic_cast<TTAProgram::Procedure&>(
2449
2450 *differences
2451 << "DIFFERING REGISTER FILE VALUES" << std::endl
2452 << "------------------------------" << std::endl
2453 << " cycle: " << cycleCount() << std::endl
2454 << " PC: " << programCounter() << std::endl
2455 << "previous PC: " << previousPC << std::endl
2456 << " function: " << procedureName << std::endl
2457 << "disassembly around previous PC:" << std::endl;
2458 int start =
2459 std::max(0, (int)previousPC - 5);
2460 int end = previousPC + 5;
2461 for (int instr = start; instr <= end; ++instr) {
2462 if (instr == (int)previousPC)
2463 *differences << "==> ";
2464 *differences
2466 program().instructionAt(instr),
2467 true)
2468 << std::endl;
2469 }
2470 errorLocationPrinted = true;
2471 }
2472 if (differences != NULL)
2473 *differences
2474 << rf.name() << "." << reg << ": "
2475 << thisReg << " (this) vs. "
2476 << otherReg << " (other)" << std::endl;
2477 }
2478 }
2479 }
2480
2481 errorLocationPrinted = false;
2482
2485 for (int i = 0; i < fuNav.count(); ++i) {
2486 TTAMachine::FunctionUnit& fu = *fuNav.item(i);
2487
2488 for (int port = 0; port < fu.portCount(); ++port) {
2489 // skip output ports as compiled sim is not exact with them at BB boundaries
2490 if (fu.port(port)->isOutput())
2491 continue;
2492 std::string portName = fu.port(port)->name();
2493 DisassemblyFUPort portString(fu.name(), portName);
2494 SimValue thisReg =
2495 FUPortValue(fu.name(), portName);
2496 SimValue otherReg =
2497 other.FUPortValue(fu.name(), portName);
2498 if (thisReg.intValue() != otherReg.intValue()) {
2499 equal = false;
2500 if (!errorLocationPrinted && differences != NULL) {
2501 std::string procedureName =
2502 (dynamic_cast<TTAProgram::Procedure&>(
2504
2505 *differences
2506 << "DIFFERING FUNCTION UNIT PORT VALUES" << std::endl
2507 << "-----------------------------------" << std::endl
2508 << " cycle: " << cycleCount() << std::endl
2509 << " PC: " << programCounter() << std::endl
2510 << "previous PC: " << previousPC << std::endl
2511 << " function: " << procedureName << std::endl
2512 << "disassembly around previous PC:" << std::endl;
2513 int start =
2514 std::max(0, (int)previousPC - 5);
2515 int end = previousPC + 5;
2516 for (int instr = start; instr <= end; ++instr) {
2517 if (instr == (int)previousPC)
2518 *differences << "==> ";
2519 *differences
2521 program().instructionAt(instr), true)
2522 << std::endl;
2523 }
2524 errorLocationPrinted = true;
2525 }
2526 if (differences != NULL)
2527 *differences
2528 << portString.toString() << ": "
2529 << thisReg.intValue() << " (this) vs. "
2530 << otherReg.intValue() << " (other)" << std::endl;
2531 }
2532
2533 }
2534
2535
2536 }
2537
2538 previousPC = programCounter();
2539
2540 return equal;
2541}
2542/* vim: set ts=4 expandtab: */
#define __func__
#define assert(condition)
long long CycleCount
Type for storing simulation cycle counts.
Definition BaseType.hh:187
Word UIntWord
Definition BaseType.hh:144
UInt32 InstructionAddress
Definition BaseType.hh:175
#define POP_CLANG_DIAGS
#define IGNORE_CLANG_WARNING(X)
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.
StopReason
The reasons to stop simulation.
@ SRE_AFTER_TIMEOUT
Stopped after simulation timeout instruction.
@ SRE_BREAKPOINT
Stopped because of at least one breakpoint.
@ SRE_USER_REQUESTED
User requested the simulation to stop explicitly, e.g., by pressing ctrl-c in the CLI.
@ SRE_RUNTIME_ERROR
A fatal runtime error occured in the simulated program.
void timeoutThread(unsigned int timeout, SimulatorFrontend *simFE)
TTAMachine::Machine * readMachine()
virtual boost::shared_ptr< CompiledSimulation > compiledSimulation()
virtual void calculate(const TTAProgram::Program &program, const CompiledSimulation &compiledSim)
static std::string toString(const T &source)
static int toInt(const T &source)
virtual std::string toString() const
static std::string simTraceDirPath()
std::string errorMessage() const
Definition Exception.cc:123
void setCause(const Exception &cause)
Definition Exception.cc:75
ClockCycleCount executionCount() const
void addFunctionUnitOperationTriggerCount(FunctionUnitID functionUnit, OperationID operation, OperationTriggerCount count)
void addConcurrentRegisterFileAccessCount(RegisterFileID registerFile, RegisterAccessCount reads, RegisterAccessCount writes, ClockCycleCount count)
void addProcedureAddressRange(InstructionAddress firstAddress, InstructionAddress lastAddress, const std::string &procedureName)
void addBusWriteCount(BusID socket, ClockCycleCount count)
void addInstructionExecutionCount(InstructionAddress address, ClockCycleCount count)
void addRegisterAccessCount(RegisterFileID registerFile, RegisterID registerIndex, ClockCycleCount reads, ClockCycleCount writes)
void setSimulatedCycleCount(ClockCycleCount count)
void addSocketWriteCount(SocketID socket, ClockCycleCount)
static bool fileIsReadable(const std::string fileName)
static const std::string DIRECTORY_SEPARATOR
static std::string fileOfPath(const std::string pathName)
static std::string directoryOfPath(const std::string fileName)
Definition FileSystem.cc:79
static bool fileExists(const std::string fileName)
void handleEvent(int event)
const ExecutableInstruction & instructionAtConst(InstructionAddress address) const
PortState & portState(const std::string &portName, const std::string &fuName)
RegisterFileState & registerFileState(const std::string &name)
MemoryPtr memory(const TTAMachine::AddressSpace &as)
unsigned int memoryCount() const
void fillAllMemoriesWithZero()
boost::shared_ptr< Memory > MemoryPtr
void addAddressSpace(const TTAMachine::AddressSpace &as, MemoryPtr mem, bool shared=true)
const TTAMachine::AddressSpace & addressSpace(unsigned int i)
void resetAllMemories()
static NullPortState & instance()
Definition PortState.cc:96
static POMDisassembler * disassembler(const TTAMachine::Machine &mach, const TTAProgram::Program &program)
virtual TCEString disassembleInstruction(const TTAProgram::Instruction &instruction, int addr=-1)
"Template methods" that can be overridden in the derived assemblers.
static std::string disassemble(const TTAProgram::Move &move)
@ CONNECTION_MISSING
Connection required for a move is missing.
@ LONG_IMMEDIATE_NOT_SUPPORTED
Instruction template missing for a long immediate.
@ SIMULATION_NOT_POSSIBLE
Program contains operations with unknown behaviour.
@ COMPILED_SIMULATION_NOT_POSSIBLE
Compiled simulation is not possible.
POMValidatorResults * validate(const std::set< ErrorCode > &errorsToCheck)
void setPCFDirectory(const std::string &path)
boost::tuple< std::string, std::size_t, std::size_t > ConcurrentRFAccess
type to be used as a key for storing concurrent access info
const ConcurrentRFAccessIndex & accessDataBase() const
std::map< ConcurrentRFAccess, ClockCycleCount > ConcurrentRFAccessIndex
concurrent accesses and their counts
virtual const SimValue & value() const =0
virtual RegisterState & registerState(int index)
static void deleteAllItems(SequenceType &aSequence)
int intValue() const
Definition SimValue.cc:895
virtual MachineState & machineState(int core=-1)
@ SE_RUNTIME_ERROR
Sent when a runtime error is detected in the simulated program.
void addStatistics(SimulationStatisticsCalculator &statisticsType)
bool hasSimulationEnded() const
virtual void initializeSimulation()
void setFUResourceConflictDetection(bool value)
void initializeDataMemories(const TTAMachine::AddressSpace *onlyOne=NULL)
TTASimulationController * simCon_
If simulation is initialized, this contains a pointer to the simulation controller.
bool compareState(SimulatorFrontend &other, std::ostream *differences=NULL)
POMDisassembler * disassembler_
The disassembler used to print out instructions. This is initialized on demand.
const TTAProgram::Procedure & currentProcedure() const
bool simulationTimeStatistics() const
SimulationEventHandler & eventHandler()
void setCallHistoryLength(std::size_t length)
bool automaticFinishImpossible() const
ExecutionTrace * lastTraceDB(int core=-1)
SimulationType
Which type of simulation this SimulatorFrontend controls or connects to.
@ SIM_REMOTE
Remote debugger, not a simulator at all.
@ SIM_CUSTOM
User-implemented remote HW debugger.
@ SIM_OTA
Simulation with operation-triggered implicit data transports.
@ SIM_COMPILED
Compiled, faster simulation.
@ SIM_NORMAL
Default, interpreted simulation (debugging engine).
bool saveUtilizationData_
Is saving of utilization data to TraceDB enabled.
std::ostream * outputStream_
Default output stream.
virtual void loadMachine(const std::string &fileName)
virtual void runUntil(UIntWord address)
const TTAMachine::Machine & machine() const
const UtilizationStats & utilizationStatistics(int core=-1)
void setOutputStream(std::ostream &stream)
void setMemoryAccessTracking(bool value)
double lastRunTime() const
std::vector< MemorySystem * > memorySystems_
The simulation models of the memories in the currently loaded machine for each core.
void setSimulationTimeStatistics(bool value)
virtual std::string registerFileValue(const std::string &rfName, int registerIndex=-1)
std::vector< CallPathTracker * > callPathTrackers_
The call path trackers for each core, in case tracking is enabled.
bool busTracing_
Is bus tracing, i.e., storing the values of buses in each clock cycle enabled.
bool printNextInstruction_
If true, the next simulated instructions is printed to stdout when simulation stops.
bool isCustomDebugger() const
virtual SimValue immediateUnitRegisterValue(const std::string &iuName, int index=-1)
bool executionTracing_
Is execution tracing, i.e., storing the executed instruction addresses to the trace database,...
SimulatorFrontend(SimulationType backend=SIM_NORMAL)
bool staticCompilation() const
ClockCycleCount cycleCount() const
bool memoryAccessTracking() const
bool utilizationDataSaving() const
CycleCount startCycleCount_
The cycle count when the latest simulation was started. Used to compute simulation speed.
void loadProcessorConfiguration(const std::string &fileName)
void setCompiledSimulation(bool value)
void setProfileDataSaving(bool value)
std::ostream & outputStream()
bool isSimulationInitialized() const
unsigned int stopReasonCount() const
void setNextInstructionPrinting(bool value)
const ExecutableInstruction & lastExecInstruction() const
bool programOwnedByFrontend_
Is the program owned by SimulatorFrontend or by the client?
SimulationType currentBackend_
Type of "backend" this Frontend has.
void reportSimulatedProgramError(RuntimeErrorSeverity severity, const std::string &description)
std::string disassembleInstruction(UIntWord instructionAddress) const
MachineState & machineState(int core=-1)
ProgramErrorDescriptionList programErrorReports_
Runtime error reports.
void setUtilizationDataSaving(bool value)
bool fuResourceConflictDetection() const
virtual InstructionAddress lastExecutedInstruction(int coreId=-1) const
double lastRunTime_
The wall clock time of the last non-interrupted simulation phase in seconds.
StopReason stopReason(unsigned int index) const
bool procedureTransferTracing_
Is procedure transfer access tracking enabled.
bool isSimulationStopped() const
ClockCycleCount lastRunCycleCount_
The cycle count of the last non-interrupted simulation phase.
bool profileDataSaving() const
std::string programFileName_
The source file of the program to be simulated. Used to generate the file name of the trace data base...
friend void timeoutThread(unsigned int timeout, SimulatorFrontend *simFE)
std::vector< UtilizationStats * > utilizationStats_
Processor utilization statistics.
std::vector< ExecutionTrace * > traceDBs_
The database to use for execution trace data.
std::size_t programErrorReportCount(RuntimeErrorSeverity severity)
bool detailedSimulation_
Set to true in case should build a detailed model which simulates FU stages, possibly with an externa...
bool staticCompilation_
True if the compiled simulation should use static compilation.
void setControllerForMemories(RemoteController *con)
void initializeDisassembler() const
const TTAProgram::Program * currentProgram_
Program to be simulated.
const TTAMachine::Machine * currentMachine_
Machine to run simulation with.
const CallPathTracker & callPathTracker(int core=-1) const
bool saveProfileData_
Is saving of profile data to TraceDB enabled.
std::string forcedTraceDBFileName_
If set, forces the SQLite filename of trace DB to this name.
std::time_t startTime_
The time of the last simulation start. Used to compute simulation speed.
bool hasStopReason(StopReason reason) const
void setStaticCompilation(bool value)
void setRFAccessTracing(bool value)
void setBusTracing(bool value)
virtual void next(int count=1)
const TTAProgram::Program & program() const
TPEF::Binary * tpef_
The source TPEF file.
StopPointManager & stopPointManager()
const RFAccessTracker & rfAccessTracker() const
CycleCount lastRunCycleCount() const
void setTimeout(unsigned int value)
bool zeroFillMemoriesOnReset_
Set to true in case the memories should be set to zero at reset.
RuntimeErrorSeverity
The severities of runtime errors.
StateData & findPort(const std::string &fuName, const std::string &portName)
bool memoryAccessTracking_
If this is enabled before initialization, memory access tracking is enabled. (slows down simulation)
bool executionTracing() const
StopPointManager * stopPointManager_
The breakpoint manager to be used to bookkeep breakpoints.
StateData & state(std::string searchString)
std::vector< bool > traceDBOwned_
Whether traceDB at index is owned by simulator (or taken away by client using lastTraceDB())
std::string programLocationDescription() const
virtual void loadProgram(const std::string &fileName)
virtual void step(double count=1)
const ExecutableInstruction & executableInstructionAt(InstructionAddress address) const
bool isSimulationRunning() const
void setProcedureTransferTracing(bool value)
std::vector< BusTracker * > busTrackers_
The tracker for saving bus trace.
bool leaveCompiledDirty_
True in case the compilation simulation should not cleanup at destruction the engine source files.
virtual void killSimulation()
std::size_t callHistoryLength_
The length of call history to store in memory for the commands that need it.
bool procedureTransferTracing() const
StateData & findRegister(const std::string &rfName, int registerIndex)
bool machineOwnedByFrontend_
Is the machine owned by SimulatorFrontend or by the client?
std::vector< ProcedureTransferTracker * > procedureTransferTrackers_
The procedure transfer tracker.
StateData & findBooleanRegister()
const SimValue & stateValue(std::string searchString)
MemorySystem & memorySystem(int coreId=-1)
virtual SimValue FUPortValue(const std::string &fuName, const std::string &portName)
void setExecutionTracing(bool value)
std::vector< ExecutionTracker * > executionTrackers_
The simple execution tracker for storing trace of executed instructions.
SimulationEventHandler * eventHandler_
Per simulation instance of SimulationEventHandler.
bool printSimulationTimeStatistics_
True if the simulation time statistics should be printed out.
std::vector< RFAccessTracker * > rfAccessTrackers_
The register file access tracker.
bool fuResourceConflictDetection_
If this is enabled before initialization, FU resource conflicts are detected (slows down simulation).
InstructionAddress programCounter() const
bool nextInstructionPrinting() const
unsigned int simulationTimeout_
Simulation timeout in seconds.
bool isCompiledSimulation() const
std::string programErrorReport(RuntimeErrorSeverity severity, std::size_t index)
void prepareToStop(StopReason reason)
std::pair< RuntimeErrorSeverity, std::string > ProgramErrorDescription
A type for storing a program error description.
bool rfAccessTracing_
Is register file (concurrent) access tracking enabled.
static SimulatorTextGenerator & textGenerator()
static boost::regex fuPortRegex()
static std::string stringToUpper(const std::string &source)
static std::string stringToLower(const std::string &source)
static bool ciEqual(const std::string &a, const std::string &b)
static Binary * readBinary(BinaryStream &stream)
virtual ULongWord end() const
virtual bool isShared() const
virtual int width() const
virtual ULongWord start() const
virtual int numberOfRegisters() const
virtual int size() const
virtual int width() const
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
int globalGuardLatency() const
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual bool hasAddressSpace() const
virtual BaseFUPort * port(const std::string &name) const
virtual FUPort * port(int operand) const
const std::string & name() const
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
bool isLittleEndian() const
Definition Machine.hh:258
virtual SocketNavigator socketNavigator() const
Definition Machine.cc:368
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual AddressSpaceNavigator addressSpaceNavigator() const
Definition Machine.cc:392
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
bool is64bit() const
Definition Machine.hh:260
static NullMachine & instance()
virtual bool isOutput() const
Definition Port.cc:308
virtual std::string name() const
Definition Port.cc:141
virtual int portCount() const
Definition Unit.cc:135
const TTAMachine::AddressSpace & space() const
InstructionAddress location() const
virtual Address endAddress() const
virtual Address startAddress() const
virtual Address startAddress() const
virtual bool isInitialized() const
virtual MinimumAddressableUnit MAU(int index) const
DataDefinition & dataDefinition(Address address) const
Definition DataMemory.cc:79
int dataDefinitionCount() const
const TTAMachine::AddressSpace & addressSpace() const
Address address() const
CodeSnippet & parent() const
static NullProgram & instance()
TCEString name() const
Definition Procedure.hh:66
Procedure & procedure(int index) const
Definition Program.cc:622
Instruction & lastInstruction() const
Definition Program.cc:463
Address startAddress() const
Definition Program.cc:286
DataMemory & dataMemory(int index) const
Definition Program.cc:967
Instruction & instructionAt(InstructionAddress address) const
Definition Program.cc:374
int procedureCount() const
Definition Program.cc:610
Procedure & lastProcedure() const
Definition Program.cc:230
int dataMemoryCount() const
Definition Program.cc:942
virtual StopReason stopReason(unsigned int index) const
virtual SimValue FUPortValue(const std::string &fuName, const std::string &portName)=0
virtual bool automaticFinishImpossible() const
virtual void step(double count=1)=0
virtual void reset()=0
virtual unsigned int stopReasonCount() const
virtual SimulationStatus state() const
virtual void prepareToStop(StopReason reason)
@ STA_FINISHED
Simulation ended after executing the last instruction.
@ STA_RUNNING
A run command (run, stepi, until...) given.
@ STA_STOPPED
Simulation stopped for some reason.
@ STA_INITIALIZED
Simulation initialized and ready to run.
virtual std::string registerFileValue(const std::string &rfName, int registerIndex=-1)=0
virtual void next(int count=1)=0
virtual void runUntil(UIntWord address)=0
virtual InstructionAddress lastExecutedInstruction(int coreId=-1) const
virtual ClockCycleCount clockCount() const
virtual SimValue immediateUnitRegisterValue(const std::string &iuName, int index=-1)=0
virtual void run()=0
virtual InstructionAddress programCounter() const =0
virtual MemorySystem & memorySystem(int coreId=-1)
virtual boost::format text(int textId)
ClockCycleCount busWrites(const std::string &busName) const
ClockCycleCount operationExecutions(const std::string &operationName) const
ClockCycleCount triggerCount(const std::string &fuName) const
ClockCycleCount registerReads(const std::string &rfName, int registerIndex) const
ClockCycleCount registerWrites(const std::string &rfName, int registerIndex) const
ClockCycleCount socketWrites(const std::string &socketName) const
void setSourceFile(const std::string &fileName)
@ TXT_ILLEGAL_INPUT_FILE
@ TXT_FILE_X_NOT_FOUND
@ TXT_FILE_NOT_FOUND