43 : m_parentComponent(NULL)
44 , m_className(className)
45 , m_visibleClassName(visibleClassName)
62 return m_visibleClassName;
86 std::cerr <<
"INTERNAL ERROR in Component::Clone(): " 88 throw std::exception();
92 StateVariableMap::const_iterator varIt = m_stateVariables.begin();
93 for ( ; varIt != m_stateVariables.end(); ++varIt) {
94 const string& varName = varIt->first;
97 StateVariableMap::iterator cloneVarIt =
98 clone->m_stateVariables.find(varName);
100 if (cloneVarIt == clone->m_stateVariables.end()) {
101 std::cerr <<
"INTERNAL ERROR in Component::Clone(): " 102 "could not copy variable " << varName <<
"'s " 103 <<
" value to the clone: clone is missing" 106 }
else if (!(cloneVarIt->second).CopyValueFrom(variable)) {
107 std::cerr <<
"INTERNAL ERROR in Component::Clone(): " 108 "could not copy variable " << varName <<
"'s " 109 <<
" value to the clone.\n";
114 for (Components::const_iterator it = m_childComponents.begin();
115 it != m_childComponents.end(); ++it) {
118 std::cerr <<
"INTERNAL ERROR in Component::Clone(): " 119 "could not clone child of class '" <<
141 std::cerr <<
"INTERNAL ERROR in Component::LightCloneInternal(): " 143 throw std::exception();
147 StateVariableMap::const_iterator varIt = m_stateVariables.begin();
148 for ( ; varIt != m_stateVariables.end(); ++varIt) {
149 const string& varName = varIt->first;
152 StateVariableMap::iterator cloneVarIt =
153 clone->m_stateVariables.find(varName);
155 if (cloneVarIt == clone->m_stateVariables.end()) {
156 std::cerr <<
"INTERNAL ERROR in Component::LightCloneInternal(): " 157 "could not copy variable " << varName <<
"'s " 158 <<
" value to the clone: clone is missing" 160 throw std::exception();
167 if (!(cloneVarIt->second).CopyValueFrom(variable)) {
168 std::cerr <<
"INTERNAL ERROR in Component::LightCloneInternal(): " 169 "could not copy variable " << varName <<
"'s " 170 <<
" value to the clone.\n";
171 throw std::exception();
175 for (Components::const_iterator it = m_childComponents.begin();
176 it != m_childComponents.end(); ++it) {
179 std::cerr <<
"INTERNAL ERROR in Component::LightCloneInternal(): " 180 "could not clone child of class '" <<
182 throw std::exception();
194 return LightCloneInternal();
199 ostream& changeMessages)
const 212 StateVariableMap::const_iterator varIt = m_stateVariables.begin();
213 for ( ; varIt != m_stateVariables.end(); ++varIt) {
214 const string& varName = varIt->first;
218 if (varName ==
"step")
233 string varOld = oldVariable->
ToString();
237 << varName <<
": " << varOld <<
" -> " << var <<
"\n";
242 for (
size_t i = 0; i < m_childComponents.size(); ++ i) {
243 string myName = m_childComponents[i]->GetVariable(
"name")->ToString();
248 for (j=0; j<oldChildren.size(); ++j)
250 m_childComponents[i]->DetectChanges(oldChildren[j], changeMessages);
256 changeMessages << m_childComponents[i]->
262 for (
size_t j=0; j<oldChildren.size(); ++j) {
263 string oldName = oldChildren[j]->GetVariable(
"name")->ToString();
266 for (
size_t k=0; k<m_childComponents.size(); ++k) {
267 string newName = m_childComponents[k]->GetVariable(
"name")->ToString();
268 if (newName == oldName) {
275 changeMessages << oldChildren[j]->
286 for (
size_t i = 0; i < m_childComponents.size(); ++ i)
287 m_childComponents[i]->
Reset();
303 for (
size_t i = 0; i < m_childComponents.size(); ++ i)
304 everythingOk &= m_childComponents[i]->
PreRunCheck(gxemul);
322 for (
size_t i = 0; i < m_childComponents.size(); ++ i)
377 m_parentComponent = parentComponent;
383 return m_parentComponent;
389 return m_parentComponent;
407 const string& methodName,
408 const vector<string>& arguments)
410 std::cerr <<
"Internal error: someone tried to execute " 411 "method '" << methodName <<
"' on the Component base" 412 " class. Perhaps you are missing an override?\n";
413 throw std::exception();
423 if (model != NULL && !model->
ToString().empty()) {
424 if (!ss.str().empty())
433 if (!ss.str().empty())
437 ss << freq/1e9 <<
" GHz";
438 else if (freq >= 1e6)
439 ss << freq/1e6 <<
" MHz";
440 else if (freq >= 1e3)
441 ss << freq/1e3 <<
" kHz";
448 if (paused != NULL && paused->
ToInteger() > 0) {
449 if (!ss.str().empty())
460 bool htmlLinksForClassNames,
string prefixForComponentUrls)
const 472 for (
size_t pos=0; pos<branchTemplate.length(); pos++) {
475 if (pos < branchTemplate.length() - 4)
480 if (pos == branchTemplate.length() - 3 ||
481 pos == branchTemplate.length() - 2)
489 string name =
"(unnamed " + className +
")";
498 if (htmlLinksForClassNames) {
500 std::ifstream documentationComponentFile((
501 "doc/components/component_" 502 + className +
".html").c_str());
504 if (documentationComponentFile.is_open())
505 str +=
"<a href=\"" + prefixForComponentUrls +
506 "components/component_" +
507 className +
".html\">" + name +
"</a>";
517 if ((templateName =
GetVariable(
"template")) != NULL &&
520 string tName = templateName->
ToString();
524 if (htmlLinksForClassNames) {
527 std::ifstream documentationMachineFile((
528 "doc/machines/machine_" 529 + tName +
".html").c_str());
531 if (documentationMachineFile.is_open())
532 str +=
"<a href=\"" + prefixForComponentUrls +
533 "machines/machine_" +
534 tName +
".html\">" + tName +
"</a>";
546 if (!details.empty())
547 str +=
" (" + details +
")";
550 string result =
" " + str +
"\n";
554 for (
size_t i=0, n=children.size(); i<n; ++i) {
555 string subBranch = branchTemplate;
561 result += children[i]->GenerateTreeDump(subBranch,
562 htmlLinksForClassNames, prefixForComponentUrls);
576 if (rootComponent == NULL)
591 return gxemul->
GetUI();
596 size_t insertPosition)
598 if (insertPosition == (
size_t) -1) {
599 insertPosition = m_childComponents.size();
600 m_childComponents.push_back(childComponent);
602 m_childComponents.insert(
603 m_childComponents.begin() + insertPosition,
608 assert(childComponent->
GetParent() == NULL);
616 bool collision =
false;
620 if (name->
ToString().empty() || collision) {
633 for (
size_t i=0; i<m_childComponents.size(); ++i) {
634 if (i == insertPosition)
639 m_childComponents[i]->GetVariable(
"name");
640 if (otherName != NULL) {
658 for (Components::iterator it = m_childComponents.begin();
659 it != m_childComponents.end(); ++it, ++index) {
660 if (childToRemove == (*it)) {
662 m_childComponents.erase(it);
676 return m_childComponents;
682 return m_childComponents;
692 if (m_parentComponent != NULL)
699 static vector<string> SplitPathStringIntoVector(
const string &path)
702 vector<string> pathStrings;
705 for (
size_t i=0, n=path.length(); i<n; i++) {
708 pathStrings.push_back(word);
715 pathStrings.push_back(word);
724 vector<string> allComponentPaths;
730 root->AddAllComponentPaths(allComponentPaths);
734 vector<string> myPathParts = SplitPathStringIntoVector(myPath);
736 for (
size_t n=1; n<=myPathParts.size(); ++n) {
738 for (
size_t i=myPathParts.size()-n; i<myPathParts.size(); i++) {
739 if (attempt.length() > 0)
741 attempt += myPathParts[i];
752 string dotAttempt =
"." + attempt;
753 size_t dotAttemptLength = dotAttempt.length();
754 for (
size_t j=0; j<allComponentPaths.size(); ++j) {
755 const string& s = allComponentPaths[j];
756 if (s.length() < attempt.length())
761 else if (s.length() > dotAttemptLength &&
762 s.substr(s.length() - dotAttemptLength, dotAttemptLength) == dotAttempt)
781 while (path.length() > 0 && path[path.length() - 1] ==
' ')
782 path = path.substr(0, path.length() - 1);
790 vector<string> allComponentPaths;
791 AddAllComponentPaths(allComponentPaths);
798 string strToFind =
"." + path;
799 for (
size_t i=0, n=allComponentPaths.size(); i<n; i++) {
800 if (allComponentPaths[i].length() > strToFind.length()) {
801 string subs = allComponentPaths[i].substr(
802 allComponentPaths[i].length() - strToFind.length());
803 if (strToFind == subs) {
805 component = root->
LookupPath(allComponentPaths[i]);
823 if (index > path.size()) {
829 StateVariableMap::const_iterator it = m_stateVariables.find(
"name");
830 if (it == m_stateVariables.end()) {
835 string nameOfThisComponent = (it->second).ToString();
836 bool match = (path[index] == nameOfThisComponent);
839 if (!match || index == path.size() - 1) {
847 const string& pathPartToLookup = path[index+1];
848 for (
size_t i=0, n=m_childComponents.size(); i<n; i++) {
850 m_childComponents[i]->GetVariable(
"name");
851 if (childName != NULL) {
852 if (childName->
ToString() == pathPartToLookup) {
853 component = m_childComponents[i]->
864 void Component::AddAllComponentPaths(vector<string>& allComponentPaths)
const 870 for (
size_t i=0, n=m_childComponents.size(); i<n; i++)
871 m_childComponents[i]->AddAllComponentPaths(allComponentPaths);
875 static bool PartialMatch(
const string& partialPath,
const string& path)
877 if (partialPath.empty())
880 const size_t partialPathLength = partialPath.length();
881 const size_t pathLength = path.length();
886 if (partialPathLength + pathPos > pathLength)
890 if (path.substr(pathPos, partialPathLength) == partialPath) {
893 if (path.find(
'.', pathPos + partialPathLength) ==
901 }
while (pathPos < pathLength && path[pathPos] !=
'.');
903 if (pathPos < pathLength)
906 }
while (pathPos < pathLength);
913 const string& partialPath,
bool shortestPossible)
const 915 vector<string> allComponentPaths;
916 vector<string> matches;
918 AddAllComponentPaths(allComponentPaths);
920 for (
size_t i=0, n=allComponentPaths.size(); i<n; i++)
921 if (PartialMatch(partialPath, allComponentPaths[i])) {
922 string match = allComponentPaths[i];
924 if (shortestPossible) {
934 matches.push_back(match);
943 for (StateVariableMap::const_iterator it = m_stateVariables.begin();
944 it != m_stateVariables.end(); ++it)
945 names.push_back(it->first);
951 StateVariableMap::iterator it = m_stateVariables.find(name);
952 if (it == m_stateVariables.end())
955 return &(it->second);
961 StateVariableMap::const_iterator it = m_stateVariables.find(name);
962 if (it == m_stateVariables.end())
965 return &(it->second);
974 if (gxemul != NULL) {
975 const string& name = var.
GetName();
977 if (name ==
"step") {
986 if (newStep == oldStep)
993 " not be set to lower than zero.\n");
998 if (newStep < oldStep) {
1002 " not be decreased; snapshotting" 1003 " was not enabled prior to\nstarting" 1004 " the emulation. (-B command line" 1019 "this component cannot be set manually.\n");
1034 StateVariableMap::iterator it = m_stateVariables.find(name);
1035 if (it == m_stateVariables.end()) {
1043 stringstream oldValue;
1046 bool success = var.
SetValue(expression);
1050 " not be assigned; type mismatch?\n");
1054 stringstream newValue;
1057 if (oldValue.str() != newValue.str()) {
1073 string tabs = context.
Tabs();
1075 ss << tabs <<
"component " << m_className <<
"\n" << tabs <<
"{\n";
1077 for (StateVariableMap::const_iterator it = m_stateVariables.begin();
1078 it != m_stateVariables.end(); ++it)
1079 (it->second).Serialize(ss, subContext);
1081 for (
size_t i = 0, n = m_childComponents.size(); i < n; ++ i)
1082 m_childComponents[i]->
Serialize(ss, subContext);
1084 ss << tabs <<
"}\n";
1088 static bool GetNextToken(
const string& str,
size_t& pos,
string& token)
1092 size_t len = str.length();
1096 (str[pos] ==
' ' || str[pos] ==
'\t' ||
1097 str[pos] ==
'\r' || str[pos] ==
'\n'))
1104 bool quoted =
false;
1111 if (ch ==
' ' || ch ==
'\t' ||
1112 ch ==
'\r' || ch ==
'\n')
1119 if (ch ==
'\\' && pos < len-1)
1120 token += str[++pos];
1124 }
while (pos < len);
1135 if (!GetNextToken(str, pos, token) || token !=
"component") {
1136 messages <<
"Expecting \"component\".\n";
1137 return deserializedTree;
1141 if (!GetNextToken(str, pos, className)) {
1142 messages <<
"Expecting a class name.\n";
1143 return deserializedTree;
1146 if (!GetNextToken(str, pos, token) || token !=
"{") {
1147 messages <<
"Expecting {.\n";
1148 return deserializedTree;
1153 if (className ==
"root") {
1157 if (deserializedTree.
IsNULL()) {
1158 messages <<
"Could not create a '" << className <<
"' component.\n";
1159 return deserializedTree;
1163 while (pos < str.length()) {
1164 size_t savedPos = pos;
1170 if (!GetNextToken(str, pos, token)) {
1172 messages <<
"Failure. (0)\n";
1173 deserializedTree = NULL;
1182 if (!GetNextToken(str, pos, name)) {
1184 messages <<
"Failure. (1)\n";
1185 deserializedTree = NULL;
1189 if (token ==
"component") {
1195 messages <<
"Failure. (2)\n";
1196 deserializedTree = NULL;
1204 string varType = token;
1206 if (!GetNextToken(str, pos, varValue)) {
1208 messages <<
"Failure. (3)\n";
1209 deserializedTree = NULL;
1215 messages <<
"Warning: variable '" << name <<
1216 "' for component class " << className <<
1217 " could not be deserialized; skipping.\n";
1222 return deserializedTree;
1233 string result = ss.str();
1240 stringstream messages;
1242 if (tmpDeserializedTree.
IsNULL())
1246 tmpDeserializedTree->
AddChecksum(checksumDeserialized);
1249 return checksumOriginal == checksumDeserialized;
1260 checksum.
Add(((uint64_t) 0x12491725 << 32) | 0xabcef011);
1261 checksum.
Add(m_className);
1266 for (StateVariableMap::const_iterator it = m_stateVariables.begin();
1267 it != m_stateVariables.end();
1269 checksum.
Add(((uint64_t) 0x019fb879 << 32) | 0x25addae1);
1272 (it->second).
Serialize(ss, dummyContext);
1273 checksum.
Add(ss.str());
1277 for (
size_t i = 0; i < m_childComponents.size(); ++ i) {
1278 checksum.
Add((((uint64_t) 0xf98a7c7c << 32) | 0x109f0000)
1280 m_childComponents[i]->AddChecksum(checksum);
1283 checksum.
Add(((uint64_t) 0x90a10224 << 32) | 0x97defa7a);
virtual CPUComponent * AsCPUComponent()
Returns the component's CPUComponent interface.
virtual void ShowDebugMessage(const string &msg)=0
Shows a debug message.
SerializationContext Indented()
Constructs a SerializationContext which is indented (1 step) compared to the current context...
StateVariable * GetVariable(const string &name)
Gets a pointer to a state variable.
Component * GetParent()
Gets this component's parent component, if any.
virtual bool PreRunCheckForComponent(GXemul *gxemul)
Checks the state of this component, before starting execution.
static refcount_ptr< Component > Deserialize(ostream &messages, const string &str, size_t &pos)
Deserializes a string into a component tree.
virtual bool MethodMayBeReexecutedWithoutArgs(const string &methodName) const
Returns whether a method name may be re-executed without args.
static refcount_ptr< Component > CreateComponent(const string &componentNameAndOptionalArgs, GXemul *gxemul=NULL)
Creates a component given a short component name.
const string & GetName() const
Gets the name of the variable.
const refcount_ptr< Component > LightClone() const
Makes a light clone of the component and all its children.
vector< string > FindPathByPartialMatch(const string &partialPath, bool shortestPossible=false) const
Finds complete component paths, given a partial path.
string GeneratePath() const
Generates a string representation of the path to the Component.
string Tabs() const
Generates a string of Tab characters, based on the indentation level.
virtual void ExecuteMethod(GXemul *gxemul, const string &methodName, const vector< string > &arguments)
Executes a method on the component.
bool AddVariable(const string &name, T *variablePointer)
Adds a state variable of type T to the Component.
UI * GetUI()
Gets an UI reference for outputting debug messages during runtime.
A Component which is the default root node in the configuration.
Components & GetChildren()
Gets pointers to child components.
void DetectChanges(const refcount_ptr< Component > &oldClone, ostream &changeMessages) const
Compare an older clone to the current tree, to find changes.
void Add(uint64_t x)
Add a uint64_t to the checksum.
string GenerateShortestPossiblePath() const
Generates a short string representation of the path to the Component.
An interface for implementing components that read/write data via an address bus. ...
static string GetAttribute(const string &attributeName)
Creates a Component.
bool ModifyStep(int64_t oldStep, int64_t newStep)
Change step either forwards or backwards.
string GetClassName() const
Gets the class name of the component.
void AddChecksum(Checksum &checksum) const
Adds this component's state, including children, to a checksum.
static uint64_t ParseNumber(const char *str, bool &error)
Parses a string into a 64-bit number.
bool SetValue(const string &expression)
Set the variable's value, using a string expression.
void GetVariableNames(vector< string > &names) const
Retrieves a component's state variable names.
enum Type GetType() const
Gets the type of the variable.
string ToString() const
Returns the variable as a readable string.
virtual void GetMethodNames(vector< string > &names) const
Retrieves a component's implemented method names.
A context used during serialization of objects.
virtual RootComponent * AsRootComponent()
Returns the component's RootComponent interface.
A Component is a node in the configuration tree that makes up an emulation setup. ...
bool PreRunCheck(GXemul *gxemul)
Checks the state of this component and all its children, before starting execution.
bool CheckConsistency() const
Checks consistency by serializing and deserializing the component (including all its child components...
virtual int Execute(GXemul *gxemul, int nrOfCycles)
Execute one or more cycles.
void FlushCachedState()
Resets the cached state of this component and all its children.
Component(const string &className, const string &visibleClassName)
Base constructor for a Component.
void Serialize(ostream &ss, SerializationContext &context) const
Serializes the Component into a string stream.
bool GetSnapshottingEnabled() const
Checks whether snapshots are currently enabled or not.
uint64_t ToInteger() const
Returns the variable as an unsignedinteger value.
StateVariables make up the persistent state of Component objects.
virtual bool CheckVariableWrite(StateVariable &var, const string &oldValue)
Checks whether a write to a variable is OK.
string GetVisibleClassName() const
Gets the visible class name of the component.
size_t RemoveChild(Component *childToRemove)
Removes a reference to a child component.
A helper class for escaping strings using C-style escapes.
A base-class for processors Component implementations.
virtual void FlushCachedStateForComponent()
Resets the cached state of this component.
bool SetVariableValue(const string &name, const string &expression)
Sets a variable to a new value.
refcount_ptr< Component > Clone() const
Clones the component and all its children.
virtual AddressDataBus * AsAddressDataBus()
Returns the component's AddressDataBus interface, if any.
virtual string GenerateDetails() const
Generate details about the component.
void AddChild(refcount_ptr< Component > childComponent, size_t insertPosition=(size_t) -1)
Adds a reference to a child component.
void SetParent(Component *parentComponent)
Sets the parent component of this component.
void Reset()
Resets the state of this component and all its children.
UI * GetUI()
Gets a pointer to the GXemul instance' active UI.
Base class for a User Interface.
const refcount_ptr< Component > LookupPath(string path) const
Looks up a path from this Component, and returns a pointer to the found Component, if any.
vector< refcount_ptr< Component > > Components
string GenerateTreeDump(const string &branchTemplate, bool htmlLinksForClassNames=false, string prefixForComponentUrls="") const
Generates an ASCII tree dump of a component tree.
virtual void ResetState()
Resets the state variables of this component.
GXemul * GetRunningGXemulInstance()
Returns a reference to the current GXemul instance.
bool IsNULL() const
Checks whether or not an object is referenced by the reference counted pointer.
virtual double GetCurrentFrequency() const
Returns the current frequency (in Hz) that the component runs at.
void SerializeValue(ostream &ss) const
Serializes the variable value into a string.