/* Copyright Universite de Versailles Saint-Quentin en Yvelines 2009 AUTHORS: Sebastien Briais, Sid Touati This file is part of GDD. GDD is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GDD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GDD. If not, see . */ #include #include #include #include #include #include #include "util.h" #include "opcode.h" #include "arch.h" #include "arch_xml.h" /** Include xml utilities functions */ #include "xmlutil.h" typedef struct { GDD_Arch *arch; // arch being built GDD_Opcode *op; // current opcode int error; } BuildCtxt; static void beginElement(void *user_data, const xmlChar *name, const xmlChar **attrs) { BuildCtxt *ctxt = (BuildCtxt *)user_data; if(ctxt->error) { return; } int i; if(xmlStrEqual(name, (xmlChar *)"arch")) { i = findAttr("version", attrs); int version = atoi_xml(attrs[i]); if(version != 1) { fprintf(stderr,"wrong arch version: %d\n",version); ctxt->error = TRUE; return; } } else if(xmlStrEqual(name, (xmlChar *)"regtype")) { i = findAttr("type", attrs); char *type = (char *)attrs[i]; i = findAttr("number", attrs); int nb = atoi_xml(attrs[i]); safe_call(GDD_arch_add_regtype(ctxt->arch, type, nb)); } else if(xmlStrEqual(name, (xmlChar *)"instruction")) { i = findAttr("opcode", attrs); char *mnemo = (char *)attrs[i]; if(strcmp(mnemo, "dummy") == 0) { fprintf(stderr, "error: dummy is a reserved mnemonic\n"); exit(1); } i = findAttr("latency", attrs); int latency = atoi_xml(attrs[i]); i = findAttr("delta_r", attrs); int delta_r = atoi_xml(attrs[i]); GDD_Opcode *op = GDD_opcode_create(mnemo, latency, delta_r); ctxt->op = op; safe_call(GDD_arch_add_opcode(ctxt->arch, op)); } else if(xmlStrEqual(name, (xmlChar *)"write")) { i = findAttr("regtype", attrs); char *type = (char *)attrs[i]; i = findAttr("delta_w", attrs); int delta_w = atoi_xml(attrs[i]); GDD_Opcode *op = ctxt->op; if(op == NULL) { ctxt->error = TRUE; return; } safe_call(GDD_opcode_extend_delta_w(op, type, delta_w)); } else { fprintf(stderr,"ignoring %s tag\n", name); } } /** Parse an architecture from an XML file stream. @param[in] stream = file stream @return the parsed architecture */ GDD_Arch *GDD_arch_of_xml_stream(FILE *stream) { BuildCtxt ctxt; ctxt.arch = GDD_arch_create(); ctxt.op = NULL; ctxt.error = FALSE; xmlParserCtxtPtr xmlctxt; xmlSAXHandler sax = { 0 }; // initialise SAX callbacks sax.startElement = beginElement; // create SAX context if ((xmlctxt = xmlCreateIOParserCtxt(&sax, &ctxt, sax_read, sax_close, stream, XML_CHAR_ENCODING_NONE)) == NULL) { fprintf(stderr,"error while creating SAX context\n"); GDD_arch_delete(ctxt.arch); return NULL; } /* safe_call(GDD_arch_add_opcode(ctxt.arch, GDD_opcode_create("dummy",0,0))); */ // parse stream if(xmlParseDocument(xmlctxt) != 0) { ctxt.error = TRUE; } // xmlFreeParserCtxt(xmlctxt); // fprint_arch(stderr, ctxt.arch); if(ctxt.error) { fprintf(stderr,"error while parsing arch file\n"); GDD_arch_delete(ctxt.arch); return NULL; } return ctxt.arch; } /** Parse an architecture from a file. @param[in] filename = filename @return the parsed architecture */ GDD_Arch *GDD_arch_of_xml_file(const char *filename) { FILE *f = fopen(filename, "r"); if(f == NULL) { fprintf(stderr,"error while opening %s\n", filename); return NULL; } GDD_Arch *arch = GDD_arch_of_xml_stream(f); fclose(f); return arch; }