Adding new standalone DTR parser/driver.

Since there is a new project that need to parse DTR xml file we've decided to set a standalone parser.

  This parser will be extended with a python API (I'm gonna have a look at boost ^^)
This commit is contained in:
Damien Dupuis 2010-04-03 15:52:29 +00:00
parent d1d2a2ea01
commit 8fc0656949
10 changed files with 515 additions and 51 deletions

View File

@ -9,4 +9,5 @@ FIND_PACKAGE(LibXml2 REQUIRED)
ADD_SUBDIRECTORY(agds)
ADD_SUBDIRECTORY(cif)
ADD_SUBDIRECTORY(openChams)
ADD_SUBDIRECTORY(dtr)
ADD_SUBDIRECTORY(cmake_modules)

View File

@ -26,68 +26,44 @@ MACRO(SETUP_SEARCH_DIR project)
ENDIF( NOT("$ENV{${project}_TOP}" STREQUAL "") )
ENDMACRO(SETUP_SEARCH_DIR project)
MACRO(SET_FOUND project)
IF(${project}_INCLUDE_DIR AND ${project}_LIBRARY)
SET(${project}_FOUND TRUE)
ELSE(${project}_INCLUDE_DIR AND ${project}_LIBRARY)
SET(${project}_FOUND FALSE)
ENDIF(${project}_INCLUDE_DIR AND ${project}_LIBRARY)
ENDMACRO(SET_FOUND project)
SETUP_SEARCH_DIR(IO)
IF(IO_DIR_SEARCH)
# AGDS
FIND_PATH(AGDS_INCLUDE_DIR
NAMES io/agds/GdsLibrary.h
PATHS ${IO_DIR_SEARCH}
PATH_SUFFIXES include
)
FIND_LIBRARY(AGDS_LIBRARY
NAMES agds
PATHS ${IO_DIR_SEARCH}
PATH_SUFFIXES lib
)
IF(AGDS_INCLUDE_DIR AND AGDS_LIBRARY)
SET(AGDS_FOUND TRUE)
#SET(IO_FOUND TRUE)
# SET(IO_LIBRARIES ${AGDS_LIBRARY})
ELSE(AGDS_INCLUDE_DIR AND AGDS_LIBRARY)
SET(AGDS_FOUND FALSE)
# SET(IO_LIBRARIES)
ENDIF(AGDS_INCLUDE_DIR AND AGDS_LIBRARY)
FIND_PATH (AGDS_INCLUDE_DIR NAMES io/agds/GdsLibrary.h PATHS ${IO_DIR_SEARCH} PATH_SUFFIXES include)
FIND_LIBRARY(AGDS_LIBRARY NAMES agds PATHS ${IO_DIR_SEARCH} PATH_SUFFIXES lib)
SET_FOUND(AGDS)
# CIF
FIND_PATH(CIF_INCLUDE_DIR
NAMES io/cif/CifCircuit.h
PATHS ${IO_DIR_SEARCH}
PATH_SUFFIXES include
)
FIND_LIBRARY(CIF_LIBRARY
NAMES cif
PATHS ${IO_DIR_SEARCH}
PATH_SUFFIXES lib
)
IF(CIF_INCLUDE_DIR AND CIF_LIBRARY)
SET(CIF_FOUND TRUE)
ELSE(CIF_INCLUDE_DIR AND CIF_LIBRARY)
SET(CIF_FOUND FALSE)
ENDIF(CIF_INCLUDE_DIR AND CIF_LIBRARY)
FIND_PATH (CIF_INCLUDE_DIR NAMES io/cif/CifCircuit.h PATHS ${IO_DIR_SEARCH} PATH_SUFFIXES include)
FIND_LIBRARY(CIF_LIBRARY NAMES cif PATHS ${IO_DIR_SEARCH} PATH_SUFFIXES lib)
SET_FOUND(CIF)
# OPENCHAMS
FIND_PATH(OPENCHAMS_INCLUDE_DIR
NAMES io/openChams/Circuit.h
PATHS ${IO_DIR_SEARCH}
PATH_SUFFIXES include
)
FIND_LIBRARY(OPENCHAMS_LIBRARY
NAMES openChams
PATHS ${IO_DIR_SEARCH}
PATH_SUFFIXES lib
)
IF(OPENCHAMS_INCLUDE_DIR AND OPENCHAMS_LIBRARY)
SET(OPENCHAMS_FOUND TRUE)
ELSE(OPENCHAMS_INCLUDE_DIR AND OPENCHAMS_LIBRARY)
SET(OPENCHAMS_FOUND FALSE)
ENDIF(OPENCHAMS_INCLUDE_DIR AND OPENCHAMS_LIBRARY)
FIND_PATH (OPENCHAMS_INCLUDE_DIR NAMES io/openChams/Circuit.h PATHS ${IO_DIR_SEARCH} PATH_SUFFIXES include)
FIND_LIBRARY(OPENCHAMS_LIBRARY NAMES openChams PATHS ${IO_DIR_SEARCH} PATH_SUFFIXES lib)
SET_FOUND(OPENCHAMS)
# DTR
FIND_PATH (DTR_INCLUDE_DIR NAMES io/dtr/Techno.h PATHS ${IO_DIR_SEARCH} PATH_SUFFIXES include)
FIND_LIBRARY(DTR_LIBRARY NAMES dtr PATHS ${IO_DIR_SEARCH} PATH_SUFFIXES lib)
SET_FOUND(DTR)
IF(AGDS_FOUND AND CIF_FOUND AND OPENCHAMS_FOUND)
IF(AGDS_FOUND AND CIF_FOUND AND OPENCHAMS_FOUND AND DTR_FOUND)
SET(IO_FOUND TRUE)
ELSE(AGDS_FOUND AND CIF_FOUND AND OPENCHAMS_FOUND)
ELSE(AGDS_FOUND AND CIF_FOUND AND OPENCHAMS_FOUND AND DTR_FOUND)
SET(IO_FOUND FALSE)
ENDIF(AGDS_FOUND AND CIF_FOUND AND OPENCHAMS_FOUND)
ENDIF(AGDS_FOUND AND CIF_FOUND AND OPENCHAMS_FOUND AND DTR_FOUND)
ELSE(IO_DIR_SEARCH)
MESSAGE("-- Cannot find IO_LIBRARIES since IO_DIR_SEARCH is not defined.")
ENDIF(IO_DIR_SEARCH)
IF (NOT IO_FOUND)

View File

@ -0,0 +1 @@
ADD_SUBDIRECTORY(src)

View File

@ -0,0 +1,16 @@
INCLUDE_DIRECTORIES(${IO_SOURCE_DIR}/dtr/src ${LIBXML2_INCLUDE_DIR})
SET ( hpps io/dtr/Techno.h
io/dtr/Rules.h
io/dtr/Name.h
io/dtr/DTRException.h )
SET ( cpps Techno.cpp
Name.cpp )
ADD_LIBRARY(dtr ${cpps})
TARGET_LINK_LIBRARIES(dtr ${LIBXML2_LIBRARIES})
INSTALL(TARGETS dtr DESTINATION /lib)
INSTALL(FILES ${hpps} DESTINATION /include/io/dtr)

65
vlsisapd/dtr/src/Name.cpp Normal file
View File

@ -0,0 +1,65 @@
/*
* Name.cpp
* DTR
*
* Created by damien dupuis on 01/04/10.
* Copyright 2010 UPMC / LIP6. All rights reserved.
*
*/
using namespace std;
#include "io/dtr/Name.h"
namespace DTR {
unsigned long Name::_globalId = 0;
map<string, unsigned long> Name::_dict;
Name::Name(string str) : _str(NULL) {
map<string, unsigned long>::iterator it = _dict.find(str);
if (it != _dict.end()) {
_id = (*it).second;
_str = &((*it).first);
} else {
_id = _globalId++;
it = _dict.insert(_dict.begin(), make_pair(str, _id));
_str = &((*it).first);
}
}
Name::Name(const char* c) : _str(NULL) {
string str(c);
map<string, unsigned long>::iterator it = _dict.find(str);
if (it != _dict.end()) {
_id = (*it).second;
_str = &((*it).first);
} else {
_id = _globalId++;
it = _dict.insert(_dict.begin(), make_pair(str, _id));
_str = &((*it).first);
}
}
bool Name::operator==(const Name& n) {
return (_id == n._id);
}
bool Name::operator==(const string& str) {
Name n(str);
return (_id == n._id);
}
bool Name::operator!=(const Name& n) {
return (_id != n._id);
}
bool Name::operator!=(const string& str) {
Name n(str);
return (_id != n._id);
}
bool Name::operator<(const Name n) const {
return (_id < n._id);
}
} // namespace

222
vlsisapd/dtr/src/Techno.cpp Normal file
View File

@ -0,0 +1,222 @@
/*
* Techno.cpp
* DTR
*
* Created by damien dupuis on 01/04/10.
* Copyright 2010 UPMC / LIP6. All rights reserved.
*
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
using namespace std;
#include <libxml/parser.h>
#include <libxml/tree.h>
#include "io/dtr/Techno.h"
#include "io/dtr/Rules.h"
#include "io/dtr/DTRException.h"
namespace {
template<class T> T getValue(xmlChar* str) {
std::istringstream iss;
iss.str((const char*) str);
T res;
iss >> res;
return res;
}
}
namespace DTR {
Techno::Techno(Name name, Name unit) : _name(name), _unit(unit) {}
Rule* Techno::addRule (Name type, double value, Name ref, Name layer1, Name layer2) {
Rule* rule = new Rule(type, value, ref, layer1, layer2);
_rules.push_back(rule);
return rule;
}
ARule* Techno::addARule (Name type, double value, Name ref, Name layer1, Name layer2) {
ARule* arule = new ARule(type, value, ref, layer1, layer2);
_rules.push_back(arule);
return arule;
}
double Techno::getValue(Name type, Name layer1, Name layer2) {
bool testL1 = (layer1 == Name("")) ? false : true;
bool testL2 = (layer2 == Name("")) ? false : true;
for (size_t i = 0 ; i < _rules.size() ; i++) {
Rule* rule = _rules[i];
if (rule->getType() == type) {
if (testL1) {
if (rule->getLayer1() == layer1) {
if (testL2) {
if (rule->getLayer2() == layer2) {
return rule->getValue();
}
} else {
return rule->getValue();
}
}
} else {
return rule->getValue();
}
}
}
string error ("[ERROR] Could not found rule: ");
error += type.getString();
error += ".";
error += layer1.getString();
error += ".";
error += layer2.getString();
error += ".";
throw DTRException(error);
}
Techno* Techno::readFromFile(const string filePath) {
LIBXML_TEST_VERSION;
Techno* techno = NULL;
xmlDoc* doc = xmlReadFile(filePath.c_str(), NULL, 0);
if (doc == NULL) {
string error ("[ERROR] Failed to parse: ");
error += filePath;
throw DTRException(error);
//return NULL;
}
xmlNode* rootElement = xmlDocGetRootElement(doc);
if (rootElement->type == XML_ELEMENT_NODE && xmlStrEqual(rootElement->name, (xmlChar*)"technology")) {
xmlChar* technoNameC = xmlGetProp(rootElement, (xmlChar*)"name");
xmlChar* technoUnitC = xmlGetProp(rootElement, (xmlChar*)"unit");
if (technoNameC && technoUnitC) {
Name name ((const char*)technoNameC);
Name unit ((const char*)technoUnitC);
techno = new Techno(name, unit);
} else {
throw DTRException("[ERROR] 'technology' node must have 'name' and 'unit' properties.");
return NULL;
}
xmlNode* child = rootElement->children;
for (xmlNode* node = child; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (!xmlStrEqual(node->name, (xmlChar*)"physical_rules")) {
throw DTRException("[ERROR] only 'physical_rules' node is allowed under 'technology' node.");
return NULL;
}
for (xmlNode* subnode = node->children ; subnode ; subnode = subnode->next) {
if (subnode->type == XML_ELEMENT_NODE) {
if (xmlStrEqual(subnode->name, (xmlChar*)"rule")) {
xmlChar* nameC = xmlGetProp(subnode, (xmlChar*)"name" );
xmlChar* layerC = xmlGetProp(subnode, (xmlChar*)"layer" );
xmlChar* layer1C = xmlGetProp(subnode, (xmlChar*)"layer1");
xmlChar* layer2C = xmlGetProp(subnode, (xmlChar*)"layer2");
xmlChar* valueC = xmlGetProp(subnode, (xmlChar*)"value" );
xmlChar* refC = xmlGetProp(subnode, (xmlChar*)"ref" );
xmlChar* typeC = xmlGetProp(subnode, (xmlChar*)"type" );
Rule* rule = NULL;
if (nameC && layer1C && layer2C && valueC && refC) { // rule with two layers
Name name ((const char*)nameC);
Name ref ((const char*)refC);
Name layer1 ((const char*)layer1C);
Name layer2 ((const char*)layer2C);
double value = ::getValue<double>(valueC);
rule = techno->addRule(name, value, ref, layer1, layer2);
} else if (nameC && layerC && valueC && refC) {// rule with only one layer
Name name ((const char*)nameC);
Name ref ((const char*)refC);
Name layer ((const char*)layerC);
double value = ::getValue<double>(valueC);
rule = techno->addRule(name, value, ref, layer);
} else if (nameC && valueC && refC) { // rule without layer
Name name ((const char*)nameC);
Name ref ((const char*)refC);
double value = ::getValue<double>(valueC);
rule = techno->addRule(name, value, ref);
} else { // invalid case
throw DTRException("[ERROR] properties of 'rule' node must be ('name', 'value', 'ref') or ('name', 'layer', 'value', 'ref') or ('name', 'layer1', 'layer2', 'value', 'ref').");
return NULL;
}
if (typeC) {
Name type ((const char*)typeC);
rule->setType(type);
}
} else if (xmlStrEqual(subnode->name, (xmlChar*)"arule")) {
xmlChar* nameC = xmlGetProp(subnode, (xmlChar*)"name" );
xmlChar* layer1C = xmlGetProp(subnode, (xmlChar*)"layer1");
xmlChar* layer2C = xmlGetProp(subnode, (xmlChar*)"layer2");
xmlChar* valueC = xmlGetProp(subnode, (xmlChar*)"value" );
xmlChar* refC = xmlGetProp(subnode, (xmlChar*)"ref" );
if (nameC && layer1C && layer2C && valueC && refC) {
Name name ((const char*)nameC);
Name layer1 ((const char*)layer1C);
Name layer2 ((const char*)layer2C);
Name ref ((const char*)refC);
double value = ::getValue<double>(valueC);
techno->addARule(name, value, ref, layer1, layer2);
} else {
throw DTRException("[ERROR] 'arule' node must have 'name', 'layer1', 'layer2', 'value' and 'ref' properties.");
return NULL;
}
} else {
throw DTRException("[ERROR] only 'rule' and 'arule' nodes are allowed under 'physical_rules' node.");
}
}
}
}
}
}
return techno;
}
bool Techno::writeToFile(string filePath) {
ofstream file;
file.open(filePath.c_str());
if (!file.is_open()) {
string error("[ERROR] Cannot open file ");
error += filePath;
error += " for writting.";
throw DTRException(error);
}
// checks before do anything
if (_rules.size() == 0) {
throw DTRException("[ERROR] Cannot writeToFile since no rule is defined!");
}
file << "<technology name=\"" << _name.getString() << "\" unit=\"" << _unit.getString() << "\">" << endl
<< " <physical_rules>" << endl;
for (size_t i = 0 ; i < _rules.size() ; i++) {
Rule* rule = _rules[i];
if (dynamic_cast<ARule*>(rule)) {
file << " <arule name=\"" << rule->getName().getString() << "\" ";
} else {
file << " <rule name=\"" << rule->getName().getString() << "\" ";
}
if (rule->getType() != Name("")) {
file << "type=\"" << rule->getType().getString() << "\" ";
}
if (rule->getLayer1() != Name("")) {
if (rule->getLayer2() != Name("")) {
file << "layer1=\"" << rule->getLayer1().getString() << "\" layer2=\"" << rule->getLayer2().getString() << "\" ";
} else {
file << "layer=\"" << rule->getLayer1().getString() << "\" ";
}
}
file << "value=\"" << rule->getValue() << "\" ref=\"" << rule->getRef().getString() << "\"/>" << endl;
}
file << " </physical_rules>" << endl
<< "</technology>" << endl;
file.close();
return true;
}
}

View File

@ -0,0 +1,28 @@
/*
* DTRException.h
* DTR
*
* Created by damien dupuis on 01/04/10.
* Copyright 2010 UPMC / LIP6. All rights reserved.
*
*/
#ifndef __DTR_EXCEPTION_H__
#define __DTR_EXCEPTION_H__
#include <exception>
#include <string>
namespace DTR {
class DTRException {
public:
DTRException(const std::string& what) throw() : _what(what) {}
virtual const char* what() const throw() { return _what.c_str(); }
virtual ~DTRException() throw() {}
private:
std::string _what;
};
} // namespace
#endif

View File

@ -0,0 +1,49 @@
/*
* Name.h
* DTR
*
* Created by damien dupuis on 01/04/10.
* Copyright 2010 UPMC / LIP6. All rights reserved.
*
*/
#ifndef __DTR_NAME_H__
#define __DTR_NAME_H__
#include <string>
#include <map>
#include "io/dtr/DTRException.h"
namespace DTR {
class Name {
public:
Name(std::string);
Name(const char*);
bool operator==(const Name&);
bool operator==(const std::string&);
bool operator!=(const Name&);
bool operator!=(const std::string&);
bool operator<(const Name) const;
inline const std::string& getString() const;
private:
unsigned long _id;
const std::string *_str;
static std::map<std::string, unsigned long> _dict;
static unsigned long _globalId;
};
inline const std::string& Name::getString() const{
if (!_str) {
throw DTRException("[ERROR] Name object has no string");
}
return *_str;
}
} // namespace
#endif

View File

@ -0,0 +1,56 @@
/*
* Rules.h
* DTR
*
* Created by damien dupuis on 01/04/10.
* Copyright 2010 UPMC / LIP6 All rights reserved.
*
*/
#ifndef __DTR_RULES_H__
#define __DTR_RULES_H__
namespace DTR {
class Rule {
public:
Rule(Name name, double value, Name ref, Name layer1, Name layer2)
: _name(name), _type(Name("")), _value(value), _ref(ref), _layer1(layer1), _layer2(layer2) {};
// accessors
inline Name getName();
inline Name getType();
inline double getValue();
inline Name getRef();
inline Name getLayer1();
virtual inline Name getLayer2(); // add virtual so the Rule object is polymorphic
// modifiers
inline void setType(Name);
// members
private:
Name _name;
Name _type;
double _value;
Name _ref;
Name _layer1;
Name _layer2;
};
class ARule : public Rule {
public:
ARule(Name name, double value, Name ref, Name layer1, Name layer2)
: Rule(name, value, ref, layer1, layer2) {};
};
inline Name Rule::getName() { return _name; };
inline Name Rule::getType() { return _type; };
inline double Rule::getValue() { return _value; };
inline Name Rule::getRef() { return _ref; };
inline Name Rule::getLayer1() { return _layer1; };
inline Name Rule::getLayer2() { return _layer2; };
inline void Rule::setType(Name type) { _type = type; };
} // namespace DTR
#endif

View File

@ -0,0 +1,50 @@
/*
* Techno.h
* DTR
*
* Created by damien dupuis on 01/04/10.
* Copyright 2010 UPMC / LIP6 All rights reserved.
*
*/
#ifndef __DTR_TECHNO_H__
#define __DTR_TECHNO_H__
#include <vector>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include "io/dtr/Name.h"
namespace DTR {
class Rule;
class ARule;
class Techno {
public:
Techno(Name name, Name unit);
inline Name getName();
inline Name getUnit();
inline std::vector<Rule*>& getRules();
Rule* addRule (Name name, double value, Name ref, Name layer1=Name(""), Name layer2=Name(""));
ARule* addARule(Name name, double value, Name ref, Name layer1 , Name layer2);
double getValue(Name type, Name layer1=Name(""), Name layer2=Name(""));
bool writeToFile(std::string filePath);
static Techno* readFromFile(const std::string filePath);
Name _name;
Name _unit;
std::vector<Rule*> _rules;
};
inline Name Techno::getName() { return _name; };
inline Name Techno::getUnit() { return _unit; };
inline std::vector<Rule*>& Techno::getRules() { return _rules; };
} // namespace DTR
#endif