Bug fix: check if vm exists
[avr-sim.git] / DeviceSettings.cpp
blob32335059ca5072509486310a165bc025ee28ab54
1 #include "DeviceSettings.h"
2 #include "Format.h"
3 #include "Device.h"
4 #include "Util.h"
6 #ifdef WIN32
7 # include <io.h>
8 # include <direct.h>
9 # define WIN32_LEAN_AND_MEAN
10 # include <windows.h>
11 #else
12 # include <unistd.h>
13 # include <dirent.h>
14 #endif
16 #include <iostream>
17 #include <libxml/parser.h>
18 #include <libxml/tree.h>
19 #include <libxml/debugXML.h>
21 #define SETTINGS_DIR "./devices/"
23 #ifdef WIN32
24 const char separatorChar = '\\';
25 #else
26 const char separatorChar = '/';
27 #endif
29 namespace avr {
31 void DeviceSettings::listAll() {
32 #ifdef WIN32
33 std::string filter = SETTINGS_DIR;
34 if( filter[filter.length() - 1] != separatorChar )
35 filter += File::separatorChar;
36 filter += '*';
38 _finddata_t fileinfo;
39 long h = _findfirst(filter.c_str(), &fileinfo);
40 if( h != -1 ) {
41 while( true ) {
42 if( (strcmp(fileinfo.name,".") != 0) &&
43 (strcmp(fileinfo.name,"..") != 0) ) {
44 std::cout << fileinfo.name << std::endl;
47 if( _findnext(h,&fileinfo) != 0 )
48 break;
50 _findclose(h);
52 #else
53 DIR *dir = opendir(SETTINGS_DIR);
54 if (dir == 0)
55 return;
57 struct dirent *dp;
58 while ( (dp = readdir(dir)) != 0) {
59 if ( (strcmp(dp->d_name, ".") != 0)&&(strcmp(dp->d_name, "..")!= 0)) {
60 std::cout << dp->d_name<< std::endl;
63 closedir(dir);
64 #endif
67 class XmlHandle {
68 public:
69 XmlHandle(const char *filename) {
71 * this initialize the library and check potential ABI mismatches
72 * between the version it was compiled for and the actual shared
73 * library used.
75 LIBXML_TEST_VERSION
77 int flags = XML_PARSE_DTDATTR | /* default DTD attributes */
78 XML_PARSE_NOENT | /* substitute entities */
79 XML_PARSE_DTDVALID; /* validate with the DTD */
81 /*parse the file and get the DOM */
82 doc = xmlReadFile(filename, NULL, flags);
84 if (doc == 0)
85 throw ParseException( util::format("Unable to open %s") % filename );
88 ~XmlHandle() {
89 /*free the document */
90 xmlFreeDoc(doc);
93 * Cleanup function for the XML library.
95 xmlCleanupParser();
98 operator xmlDocPtr() {
99 return doc;
102 private:
103 xmlDocPtr doc;
106 char *getAttribute(xmlNode *node, const char *name, bool required = false) {
107 char *result = reinterpret_cast<char*>(xmlGetNoNsProp(
108 node, reinterpret_cast<const xmlChar*>(name)));
109 if( required && (result == 0) )
110 throw ParseException(
111 util::format("Expected an attribute %s on node %s") % name % node->name );
113 return result;
116 int getIntAttribute(xmlNode *node, const char *name, int base = 10, bool required = false) {
117 xmlChar *result = xmlGetNoNsProp(node,
118 reinterpret_cast<const xmlChar*>(name));
120 int ret = 0;
121 if( result != 0 ) {
122 ret = strtoul( reinterpret_cast<char*>(result), 0, base);
123 xmlFree( result );
124 } else if( required ) {
125 throw ParseException(
126 util::format("Expected an attribute %s on node %s") % name % node->name );
129 return ret;
132 int getIntAttributeDef(xmlNode *node, const char *name, int def = 0, int base = 10) {
133 xmlChar *result = xmlGetNoNsProp(node,
134 reinterpret_cast<const xmlChar*>(name));
136 int ret = 0;
137 if( result != 0 ) {
138 ret = strtoul( reinterpret_cast<char*>(result), 0, base);
139 xmlFree( result );
140 } else {
141 ret = def;
144 return ret;
147 void freeAttribute(char *attr) {
148 xmlFree( reinterpret_cast<xmlChar*>(attr) );
151 bool compare(const xmlChar *a, const char *b) {
152 return strcmp( reinterpret_cast<const char*>(a), b ) == 0;
155 HardwareSettings::HardwareSettings(XmlHandle & doc, _xmlNode *node)
156 : doc(doc), node(node) {
158 reg = node->children;
159 while( (reg != 0) && (reg->type != XML_ELEMENT_NODE) )
160 reg = reg->next;
163 int HardwareSettings::intAttribute(const char *name, int base /*= 10*/) const {
164 return getIntAttribute(node, name, base, true);
167 int HardwareSettings::intAttributeDef(const char *name,
168 int def /*=0*/, int base /*= 10*/) const {
169 return getIntAttributeDef(node, name, def, base);
172 std::string HardwareSettings::strAttribute(const char *name) const {
173 char *s = getAttribute(node, name, true);
174 std::string str = s;
175 freeAttribute(s);
176 return s;
179 bool HardwareSettings::getBinding(std::string & name, std::string & binding) {
180 if( reg == 0 )
181 return false;
183 name = reinterpret_cast<const char*>( reg->name );
184 stolower( name );
186 // Get binding registers
187 xmlChar *txt = xmlNodeListGetString(doc, reg->children, 1);
188 binding = reinterpret_cast<const char*>( txt );
189 trim(binding);
191 do {
192 reg = reg->next;
193 } while( (reg != 0) && (reg->type != XML_ELEMENT_NODE) );
194 return true;
197 void DeviceSettings::parseMemory(Device *dev, xmlNode *memory) {
198 unsigned int ioSpaceSize = 0;
199 unsigned int flashSize = 0;
200 unsigned int sramSize = 0;
201 unsigned int pcSize = 2;
202 unsigned int stackMask = 0xffff;
204 for(xmlNode *node = memory->children; node != 0; node = node->next) {
205 if( node->type == XML_ELEMENT_NODE ) {
206 if( compare(node->name, "stack") ) {
207 stackMask = getIntAttribute(node, "mask", 16, true);
210 unsigned int *size = 0;
211 if( compare(node->name, "flash") )
212 size = &flashSize;
213 if( compare(node->name, "sram") )
214 size = &sramSize;
215 if( compare(node->name, "pc") )
216 size = &pcSize;
217 if( compare(node->name, "iospace") )
218 size = &ioSpaceSize;
220 if( size != 0 )
221 *size = getIntAttribute(node, "size", 10, true);
225 #ifdef DEBUG
226 std::cout << "ioSpaceSize = " << ioSpaceSize << std::endl;
227 std::cout << "flashSize = " << flashSize << std::endl;
228 std::cout << "sramSize = " << sramSize << std::endl;
229 std::cout << "pcSize = " << pcSize << std::endl;
230 std::cout << "stackMask = " << stackMask << std::endl;
231 #endif
233 dev->buildCore(ioSpaceSize, sramSize, flashSize, stackMask, pcSize);
236 void DeviceSettings::parseRegisters(Device *dev, xmlNode *registers) {
237 for(xmlNode *node = registers->children; node != 0; node = node->next) {
238 if( node->type == XML_ELEMENT_NODE ) {
239 char *n = getAttribute(node, "name", true);
240 unsigned int address = getIntAttribute(node, "address", 16, true);
241 unsigned char initial = getIntAttributeDef(node, "initial", 0, 16);
242 dev->addIOReg(address, std::string(n), initial);
243 #ifdef DEBUG
244 std::cout << "Adding register "<< n
245 << " at address "<< address
246 << ", initial value = "
247 << std::hex << (int)initial << std::dec
248 << std::endl;
249 #endif
251 freeAttribute(n);
256 void DeviceSettings::parseInterrupts(Device *dev, xmlNode *interrupts) {
257 for(xmlNode *node = interrupts->children; node != 0; node = node->next) {
258 if( node->type == XML_ELEMENT_NODE ) {
259 unsigned int vector = getIntAttribute(node, "vector", 10, true);
260 unsigned int address = getIntAttribute(node, "address", 16, true);
261 char *name = getAttribute(node, "name", true);
263 dev->addInterrupt(vector, address, name);
264 #ifdef DEBUG
265 std::cout << "Adding interrupt "<< vector
266 << " at address "<< std::hex << address << std::dec
267 << ", name = " << name
268 << std::endl;
269 #endif
271 freeAttribute(name);
276 void DeviceSettings::parseHardware(Device *dev, XmlHandle & doc, xmlNode *hardware) {
277 for(xmlNode *node = hardware->children; node != 0; node = node->next) {
278 if( node->type == XML_ELEMENT_NODE ) {
279 const char *hwname = reinterpret_cast<const char*>( node->name );
280 HardwareSettings hws( doc, node );
281 dev->buildHardware( hwname, hws );
286 void DeviceSettings::load(Device *dev, const char *devicename) {
287 std::string filename( SETTINGS_DIR);
288 filename += devicename;
290 XmlHandle doc(filename.c_str() );
292 //xmlDebugDumpDocument(stdout, doc);
294 /*Get the root element node */
295 xmlNode *root = xmlDocGetRootElement(doc);
296 for(xmlNode *node = root->children; node != 0; node = node->next) {
297 if( node->type == XML_ELEMENT_NODE ) {
298 if( compare(node->name, "memory") )
299 parseMemory(dev, node);
301 if( compare(node->name, "ioregisters") )
302 parseRegisters(dev, node);
304 if( compare(node->name, "interrupts") )
305 parseInterrupts(dev, node);
307 if( compare(node->name, "hardware") )
308 parseHardware(dev, doc, node);