From 68f575d0281862239d3882c38fbb5afb0fdb61b7 Mon Sep 17 00:00:00 2001
From: Damien Dupuis <alliance-users@asim.lip6.fr>
Date: Mon, 5 Apr 2010 16:27:18 +0000
Subject: [PATCH]     Added Python interface and python module creation (using
 Boost.Python libraries)

    Name, Rule, Arule and Techno objects has been ported, so it is possible to read a dtr xml file from disk to get a techno and then rules' values.

    DTRException object still need to be ported.
---
 vlsisapd/dtr/src/CMakeLists.txt  | 28 ++++++++++++++++++---
 vlsisapd/dtr/src/PyTechno.cpp    | 43 ++++++++++++++++++++++++++++++++
 vlsisapd/dtr/src/Techno.cpp      | 26 ++++++++++++-------
 vlsisapd/dtr/src/io/dtr/Techno.h |  4 ++-
 4 files changed, 88 insertions(+), 13 deletions(-)
 create mode 100644 vlsisapd/dtr/src/PyTechno.cpp

diff --git a/vlsisapd/dtr/src/CMakeLists.txt b/vlsisapd/dtr/src/CMakeLists.txt
index f00a7f55..9251a522 100644
--- a/vlsisapd/dtr/src/CMakeLists.txt
+++ b/vlsisapd/dtr/src/CMakeLists.txt
@@ -1,4 +1,15 @@
-INCLUDE_DIRECTORIES(${IO_SOURCE_DIR}/dtr/src ${LIBXML2_INCLUDE_DIR})
+SET(Boost_USE_STATIC_LIBS   ON)
+SET(Boost_USE_MULTITHREADED ON)
+FIND_PACKAGE(Boost 1.38.0 COMPONENTS python)
+IF (Boost_FOUND)
+  MESSAGE(STATUS "Found Boost.Python libraries in ${Boost_INCLUDE_DIR} as ${Boost_LIBRARIES}")
+ELSE (Boost_FOUND)
+  MESSAGE(FATAL_ERROR "Boost.Python libraries were not found")
+ENDIF (Boost_FOUND)
+
+FIND_PACKAGE(PythonLibs REQUIRED)
+
+INCLUDE_DIRECTORIES(${IO_SOURCE_DIR}/dtr/src ${LIBXML2_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_PATH})
 
 SET ( hpps io/dtr/Techno.h
            io/dtr/Rules.h
@@ -8,9 +19,20 @@ SET ( hpps io/dtr/Techno.h
 SET ( cpps Techno.cpp
            Name.cpp )
 
-ADD_LIBRARY(dtr ${cpps})
+SET ( pycpps PyTechno.cpp ${cpps})
 
+          ADD_LIBRARY(dtr ${cpps})
 TARGET_LINK_LIBRARIES(dtr ${LIBXML2_LIBRARIES})
-
 INSTALL(TARGETS dtr     DESTINATION /lib)
+
+IF (Boost_FOUND)
+          ADD_LIBRARY(pyDTR MODULE ${pycpps})
+SET_TARGET_PROPERTIES(pyDTR PROPERTIES
+                            COMPILE_FLAGS "${COMPILE_FLAGS} -D__PYTHON_MODULE__=1"
+                            PREFIX        ""
+                     )
+TARGET_LINK_LIBRARIES(pyDTR dtr ${LIBXML2_LIBRARIES} ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
+INSTALL(TARGETS pyDTR   DESTINATION /lib/python)
+ENDIF(Boost_FOUND)
+
 INSTALL(FILES   ${hpps} DESTINATION /include/io/dtr)
diff --git a/vlsisapd/dtr/src/PyTechno.cpp b/vlsisapd/dtr/src/PyTechno.cpp
new file mode 100644
index 00000000..c60459c6
--- /dev/null
+++ b/vlsisapd/dtr/src/PyTechno.cpp
@@ -0,0 +1,43 @@
+#include <boost/python.hpp>
+using namespace boost::python;
+
+#include "io/dtr/Techno.h"
+#include "io/dtr/Rules.h"
+
+namespace DTR {
+BOOST_PYTHON_MODULE(pyDTR) {
+    // class DTR::Name
+    class_<Name>("Name", init<std::string>())
+        .def("getString", &Name::getString, return_value_policy<copy_const_reference>()) // return_value_policy because this method return a refenrce on string
+    ;
+
+    // class DTR::Rule
+    class_<Rule>("Rule", init<Name, double, Name, Name, Name>())
+        // accessors
+        .def("getName"  , &Rule::getName  )
+        .def("getType"  , &Rule::getType  )
+        .def("getValue" , &Rule::getValue )
+        .def("getRef"   , &Rule::getRef   )
+        .def("getLayer1", &Rule::getLayer1)
+        .def("getLayer2", &Rule::getLayer2)
+        // modifiers
+        .def("setType"  , &Rule::setType  )
+    ; 
+
+    // class DTR::ARule derived from DTR::Rule
+    class_<ARule, bases<Rule> >("ARule", init<Name, double, Name, Name, Name>())
+    ;
+
+    // class DTR::Techno
+    class_<Techno>("Techno", init<Name, Name>())
+        .def("readFromFile", &Techno::readFromFile, return_value_policy<manage_new_object>())
+        .staticmethod("readFromFile")
+
+        .def("getName"     , &Techno::getName )
+        .def("getUnit"     , &Techno::getUnit )
+        .def("getValue"    , static_cast<double(Techno::*)(Name            )>(&Techno::getValue))
+        .def("getValue"    , static_cast<double(Techno::*)(Name, Name      )>(&Techno::getValue))
+        .def("getValue"    , static_cast<double(Techno::*)(Name, Name, Name)>(&Techno::getValue))
+    ;
+}
+}
diff --git a/vlsisapd/dtr/src/Techno.cpp b/vlsisapd/dtr/src/Techno.cpp
index bc4fa6c1..7cecc0b2 100644
--- a/vlsisapd/dtr/src/Techno.cpp
+++ b/vlsisapd/dtr/src/Techno.cpp
@@ -34,25 +34,33 @@ namespace {
 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);
+Rule* Techno::addRule (Name name, double value, Name ref, Name layer1, Name layer2) {
+    Rule* rule = new Rule(name, 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);
+ARule* Techno::addARule (Name name, double value, Name ref, Name layer1, Name layer2) {
+    ARule* arule = new ARule(name, 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;
+double Techno::getValue(Name name) {
+    return getValue(name, Name(""), Name(""));
+}
+
+double Techno::getValue(Name name, Name layer) {
+    return getValue(name, layer, Name(""));
+}
+
+double Techno::getValue(Name name, 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 (rule->getName() == name) {
             if (testL1) {
                 if (rule->getLayer1() == layer1) {
                     if (testL2) {
@@ -69,7 +77,7 @@ double Techno::getValue(Name type, Name layer1, Name layer2) {
         }
     }
     string error ("[ERROR] Could not found rule: ");
-    error += type.getString();
+    error += name.getString();
     error += ".";
     error += layer1.getString();
     error += ".";
diff --git a/vlsisapd/dtr/src/io/dtr/Techno.h b/vlsisapd/dtr/src/io/dtr/Techno.h
index 93ca01ed..82eae78f 100644
--- a/vlsisapd/dtr/src/io/dtr/Techno.h
+++ b/vlsisapd/dtr/src/io/dtr/Techno.h
@@ -31,7 +31,9 @@ class Techno {
     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(""));
+    double getValue(Name name);
+    double getValue(Name name, Name layer);
+    double getValue(Name name, Name layer1, Name layer2);
     
     bool writeToFile(std::string filePath);
     static Techno* readFromFile(const std::string filePath);