From 8fc065694910e5241178d4f3dd9da6ac35815614 Mon Sep 17 00:00:00 2001
From: Damien Dupuis <alliance-users@asim.lip6.fr>
Date: Sat, 3 Apr 2010 15:52:29 +0000
Subject: [PATCH]   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 ^^)
---
 vlsisapd/CMakeLists.txt                |   1 +
 vlsisapd/cmake_modules/FindIO.cmake    |  78 +++------
 vlsisapd/dtr/CMakeLists.txt            |   1 +
 vlsisapd/dtr/src/CMakeLists.txt        |  16 ++
 vlsisapd/dtr/src/Name.cpp              |  65 ++++++++
 vlsisapd/dtr/src/Techno.cpp            | 222 +++++++++++++++++++++++++
 vlsisapd/dtr/src/io/dtr/DTRException.h |  28 ++++
 vlsisapd/dtr/src/io/dtr/Name.h         |  49 ++++++
 vlsisapd/dtr/src/io/dtr/Rules.h        |  56 +++++++
 vlsisapd/dtr/src/io/dtr/Techno.h       |  50 ++++++
 10 files changed, 515 insertions(+), 51 deletions(-)
 create mode 100644 vlsisapd/dtr/CMakeLists.txt
 create mode 100644 vlsisapd/dtr/src/CMakeLists.txt
 create mode 100644 vlsisapd/dtr/src/Name.cpp
 create mode 100644 vlsisapd/dtr/src/Techno.cpp
 create mode 100644 vlsisapd/dtr/src/io/dtr/DTRException.h
 create mode 100644 vlsisapd/dtr/src/io/dtr/Name.h
 create mode 100644 vlsisapd/dtr/src/io/dtr/Rules.h
 create mode 100644 vlsisapd/dtr/src/io/dtr/Techno.h

diff --git a/vlsisapd/CMakeLists.txt b/vlsisapd/CMakeLists.txt
index 22771642..efe0df40 100644
--- a/vlsisapd/CMakeLists.txt
+++ b/vlsisapd/CMakeLists.txt
@@ -9,4 +9,5 @@ FIND_PACKAGE(LibXml2 REQUIRED)
 ADD_SUBDIRECTORY(agds)
 ADD_SUBDIRECTORY(cif)
 ADD_SUBDIRECTORY(openChams)
+ADD_SUBDIRECTORY(dtr)
 ADD_SUBDIRECTORY(cmake_modules)
diff --git a/vlsisapd/cmake_modules/FindIO.cmake b/vlsisapd/cmake_modules/FindIO.cmake
index a205c3e0..5f742dac 100644
--- a/vlsisapd/cmake_modules/FindIO.cmake
+++ b/vlsisapd/cmake_modules/FindIO.cmake
@@ -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)
diff --git a/vlsisapd/dtr/CMakeLists.txt b/vlsisapd/dtr/CMakeLists.txt
new file mode 100644
index 00000000..4b7537b5
--- /dev/null
+++ b/vlsisapd/dtr/CMakeLists.txt
@@ -0,0 +1 @@
+ADD_SUBDIRECTORY(src)
diff --git a/vlsisapd/dtr/src/CMakeLists.txt b/vlsisapd/dtr/src/CMakeLists.txt
new file mode 100644
index 00000000..f00a7f55
--- /dev/null
+++ b/vlsisapd/dtr/src/CMakeLists.txt
@@ -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)
diff --git a/vlsisapd/dtr/src/Name.cpp b/vlsisapd/dtr/src/Name.cpp
new file mode 100644
index 00000000..1353865f
--- /dev/null
+++ b/vlsisapd/dtr/src/Name.cpp
@@ -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
+
diff --git a/vlsisapd/dtr/src/Techno.cpp b/vlsisapd/dtr/src/Techno.cpp
new file mode 100644
index 00000000..bc4fa6c1
--- /dev/null
+++ b/vlsisapd/dtr/src/Techno.cpp
@@ -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;        
+}
+
+}
+
diff --git a/vlsisapd/dtr/src/io/dtr/DTRException.h b/vlsisapd/dtr/src/io/dtr/DTRException.h
new file mode 100644
index 00000000..a597b513
--- /dev/null
+++ b/vlsisapd/dtr/src/io/dtr/DTRException.h
@@ -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
+
diff --git a/vlsisapd/dtr/src/io/dtr/Name.h b/vlsisapd/dtr/src/io/dtr/Name.h
new file mode 100644
index 00000000..30e2bc7f
--- /dev/null
+++ b/vlsisapd/dtr/src/io/dtr/Name.h
@@ -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
+
diff --git a/vlsisapd/dtr/src/io/dtr/Rules.h b/vlsisapd/dtr/src/io/dtr/Rules.h
new file mode 100644
index 00000000..6e365cb8
--- /dev/null
+++ b/vlsisapd/dtr/src/io/dtr/Rules.h
@@ -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
+
diff --git a/vlsisapd/dtr/src/io/dtr/Techno.h b/vlsisapd/dtr/src/io/dtr/Techno.h
new file mode 100644
index 00000000..93ca01ed
--- /dev/null
+++ b/vlsisapd/dtr/src/io/dtr/Techno.h
@@ -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
+