From c6ab2d5ed892f2f34eda1ccebb6dd8f2b754f190 Mon Sep 17 00:00:00 2001
From: Damien Dupuis <alliance-users@asim.lip6.fr>
Date: Wed, 14 Sep 2011 08:13:46 +0000
Subject: [PATCH]     - New support for <hbtree> section in <layout> section
 used to describe relative placement with constraints

    - Examples (c++/python parse/drive) have been updated

    TODO: test under linux / write corresponding documentation
---
 .../openChams/cplusplus/driveOpenChams.cpp    |   9 +
 .../openChams/cplusplus/parseOpenChams.cpp    |  64 ++++++-
 vlsisapd/examples/openChams/inverter.xml      |   7 +
 .../openChams/python/driveOpenChams.py        |   8 +
 .../openChams/python/parseOpenChams.py        |  20 +++
 vlsisapd/src/openChams/src/CMakeLists.txt     |   2 +
 vlsisapd/src/openChams/src/Circuit.cpp        | 170 +++++++++++++++++-
 vlsisapd/src/openChams/src/Layout.cpp         |   4 +-
 vlsisapd/src/openChams/src/Node.cpp           |  34 ++++
 vlsisapd/src/openChams/src/PyOpenChams.cpp    |  44 +++++
 .../src/vlsisapd/openChams/Circuit.h          |   5 +
 .../openChams/src/vlsisapd/openChams/Layout.h |  15 +-
 .../openChams/src/vlsisapd/openChams/Node.h   | 100 +++++++++++
 13 files changed, 466 insertions(+), 16 deletions(-)
 create mode 100644 vlsisapd/src/openChams/src/Node.cpp
 create mode 100644 vlsisapd/src/openChams/src/vlsisapd/openChams/Node.h

diff --git a/vlsisapd/examples/openChams/cplusplus/driveOpenChams.cpp b/vlsisapd/examples/openChams/cplusplus/driveOpenChams.cpp
index f20ca11c..0bf1ef47 100644
--- a/vlsisapd/examples/openChams/cplusplus/driveOpenChams.cpp
+++ b/vlsisapd/examples/openChams/cplusplus/driveOpenChams.cpp
@@ -11,6 +11,7 @@ using namespace std;
 #include "vlsisapd/openChams/Sizing.h"
 #include "vlsisapd/openChams/Operator.h"
 #include "vlsisapd/openChams/Layout.h"
+#include "vlsisapd/openChams/Node.h"
 #include "vlsisapd/openChams/Port.h"
 #include "vlsisapd/openChams/Wire.h"
 
@@ -109,6 +110,14 @@ int main(int argc, char * argv[]) {
     OpenChams::Layout* layout = circuit->createLayout();
     layout->addInstance(OpenChams::Name("pmos1"), OpenChams::Name("Common transistor"));
     layout->addInstance(OpenChams::Name("nmos1"), OpenChams::Name("Rotate transistor"));
+    // create hbtree
+    OpenChams::Group* g1 = new OpenChams::Group("g1"); // default position is NONE and default parent is NULL
+    g1->setAlign(OpenChams::Group::VERTICAL);
+    OpenChams::Bloc* b1 = new OpenChams::Bloc("nmos1", OpenChams::Node::NONE, g1);
+    g1->setRootNode(b1); // b1 is root node of group g1
+    OpenChams::Bloc* b2 = new OpenChams::Bloc("pmos1", OpenChams::Node::TOP, b1);
+    b1->setTop(b2); // b2 is on top of b1
+    layout->setHBTreeRoot(g1); // g1 is the root of the tree
 
     circuit->writeToFile("./myInverter.xml");
     return 0;
diff --git a/vlsisapd/examples/openChams/cplusplus/parseOpenChams.cpp b/vlsisapd/examples/openChams/cplusplus/parseOpenChams.cpp
index 69fd5a5a..734f25c3 100644
--- a/vlsisapd/examples/openChams/cplusplus/parseOpenChams.cpp
+++ b/vlsisapd/examples/openChams/cplusplus/parseOpenChams.cpp
@@ -16,10 +16,57 @@ using namespace std;
 #include "vlsisapd/openChams/Sizing.h"
 #include "vlsisapd/openChams/Operator.h"
 #include "vlsisapd/openChams/Layout.h"
+#include "vlsisapd/openChams/Node.h"
 #include "vlsisapd/openChams/Port.h"
 #include "vlsisapd/openChams/Wire.h"
 #include "vlsisapd/openChams/OpenChamsException.h"
 
+void printHBTree(OpenChams::Node* node, unsigned indent) {
+    if (!node) return; // since we pass nnode->getRight and node-getTop without checking for NULL
+    for (unsigned i = 0 ; i < indent ; i++) {
+        cerr << " |";
+    }
+    string pos = "";
+    switch(node->getPosition()) {
+        case OpenChams::Node::TOP:
+            pos = "top";
+            break;
+        case OpenChams::Node::RIGHT:
+            pos = "right";
+            break;
+        default:
+            break;
+    }
+    OpenChams::Bloc* bloc = dynamic_cast<OpenChams::Bloc*>(node);
+    if (bloc) {
+        cerr << " bloc: " << bloc->getName().getString() << " - " << pos << endl;
+        printHBTree(bloc->getTop()  , indent+1);
+        printHBTree(bloc->getRight(), indent+1);
+        return;
+    }
+    OpenChams::Group* group = dynamic_cast<OpenChams::Group*>(node);
+    if (group) {
+        string align = "none";
+        switch(group->getAlign()) {
+            case OpenChams::Group::VERTICAL:
+                align = "vertical";
+                break;
+            case OpenChams::Group::HORIZONTAL:
+                align = "horizontal";
+                break;
+            default:
+                break;
+        }
+        cerr << " group: " << group->getName().getString() << " - " << pos << " - align: " << align << " - isolated: " << group->isIsolated() << " - paired: " << group->isPaired() << endl; 
+        printHBTree(group->getRootNode(), indent+1);
+        printHBTree(group->getTop()     , indent+1);
+        printHBTree(group->getRight()   , indent+1);
+        return;
+    }
+    cerr << "[ERROR] printHBTree: node is nor a bloc nor a group !" << endl;
+    return;
+}
+
 int main(int argc, char * argv[]) {
     string file = "";
     if (argc == 1)
@@ -166,11 +213,18 @@ int main(int argc, char * argv[]) {
         }
     }
     OpenChams::Layout* layout = circuit->getLayout();
-    if (layout && !layout->hasNoInstance()) {
-        cerr << " + layout" << endl;
-        for (map<OpenChams::Name, OpenChams::Name>::const_iterator lit = layout->getInstances().begin() ; lit != layout->getInstances().end() ; ++lit) {
-            cerr << " | | instance name: " << ((*lit).first).getString() << " - style: " << ((*lit).second).getString() << endl;
-        }
+    if (layout) {
+       if (!layout->hasNoInstance()) {
+          cerr << " + layout" << endl;
+          for (map<OpenChams::Name, OpenChams::Name>::const_iterator lit = layout->getInstances().begin() ; lit != layout->getInstances().end() ; ++lit) {
+             cerr << " | | instance name: " << ((*lit).first).getString() << " - style: " << ((*lit).second).getString() << endl;
+          }
+       }
+       OpenChams::Node* root = layout->getHBTreeRoot();
+       if (root) {
+           cerr << " | + hbtree" << endl;
+           printHBTree(root, 2);
+       }
     }
 
 
diff --git a/vlsisapd/examples/openChams/inverter.xml b/vlsisapd/examples/openChams/inverter.xml
index 0c1d36ab..49247179 100644
--- a/vlsisapd/examples/openChams/inverter.xml
+++ b/vlsisapd/examples/openChams/inverter.xml
@@ -119,5 +119,12 @@
   <layout>
     <instance name="pmos1" style="Common transistor"/>
     <instance name="nmos1" style="Rotate transistor"/>
+    <hbtree>
+      <group name="g1" align="vertical">
+        <bloc name="nmos1">
+          <bloc name="pmos1" position="top"/>
+        </bloc>
+      </group>
+    </hbtree>
   </layout>
 </circuit>
diff --git a/vlsisapd/examples/openChams/python/driveOpenChams.py b/vlsisapd/examples/openChams/python/driveOpenChams.py
index 9bfad42d..95bcf9b2 100644
--- a/vlsisapd/examples/openChams/python/driveOpenChams.py
+++ b/vlsisapd/examples/openChams/python/driveOpenChams.py
@@ -92,5 +92,13 @@ op_nmos1.addConstraint("another", "myEq", -2.5 )
 layout = circuit.createLayout()
 layout.addInstance("pmos1", "Common transistor")
 layout.addInstance("nmos1", "Rotate transistor")
+# create hbtree
+g1 = Group("g1")
+g1.align = Group.Align.VERTICAL
+b1 = Bloc("nmos1", Node.Position.NONE, g1)
+g1.rootNode = b1 
+b2 = Bloc("pmos1", Node.Position.TOP, b1)
+b1.top = b2
+layout.hbTreeRoot = g1
 
 circuit.writeToFile("./myInverter.xml")
diff --git a/vlsisapd/examples/openChams/python/parseOpenChams.py b/vlsisapd/examples/openChams/python/parseOpenChams.py
index a946e524..9917da8c 100644
--- a/vlsisapd/examples/openChams/python/parseOpenChams.py
+++ b/vlsisapd/examples/openChams/python/parseOpenChams.py
@@ -2,6 +2,23 @@ import sys
 
 from OPENCHAMS import *
 
+def printHBTree(node, indent):
+    if node == None:
+        return
+    for i in range(indent):
+        print " |",
+    if isinstance(node, Bloc):
+        print " bloc:", node.getName(), "-", node.getPosition()
+        printHBTree(node.top  , indent+1)
+        printHBTree(node.right, indent+1)
+        return
+    if isinstance(node, Group):
+        print " group:", node.getName(), "-", node.getPosition(), "-", node.align, "-", node.isolated, "-", node.paired
+        printHBTree(node.rootNode, indent+1)
+        printHBTree(node.top     , indent+1)
+        printHBTree(node.right   , indent+1)
+        return
+
 def printContents(circuit):
   print circuit.name
   # circuit parameters
@@ -78,6 +95,9 @@ def printContents(circuit):
     print " + layout"
     for inst in circuit.layout.getInstances():
       print " | | instance name:", inst.key, "- style:", inst.value
+    if circuit.layout.hbTreeRoot != None:
+      print " | + hbtree"
+      printHBTree(circuit.layout.hbTreeRoot, 2)
 
 def usage():
     print "usage:", sys.argv[0], "[filename]"
diff --git a/vlsisapd/src/openChams/src/CMakeLists.txt b/vlsisapd/src/openChams/src/CMakeLists.txt
index 61565be1..a308f8f3 100644
--- a/vlsisapd/src/openChams/src/CMakeLists.txt
+++ b/vlsisapd/src/openChams/src/CMakeLists.txt
@@ -12,6 +12,7 @@ SET ( hpps vlsisapd/openChams/Circuit.h
            vlsisapd/openChams/SimulModel.h
            vlsisapd/openChams/Sizing.h
            vlsisapd/openChams/Layout.h
+           vlsisapd/openChams/Node.h
            vlsisapd/openChams/Transistor.h
            vlsisapd/openChams/Port.h
            vlsisapd/openChams/Wire.h
@@ -29,6 +30,7 @@ SET ( cpps Circuit.cpp
            SimulModel.cpp
            Sizing.cpp
            Layout.cpp
+           Node.cpp
            Transistor.cpp 
            Wire.cpp
     )
diff --git a/vlsisapd/src/openChams/src/Circuit.cpp b/vlsisapd/src/openChams/src/Circuit.cpp
index 8753970e..8751e08a 100644
--- a/vlsisapd/src/openChams/src/Circuit.cpp
+++ b/vlsisapd/src/openChams/src/Circuit.cpp
@@ -23,6 +23,7 @@ using namespace std;
 #include "vlsisapd/openChams/SimulModel.h"
 #include "vlsisapd/openChams/Sizing.h"
 #include "vlsisapd/openChams/Layout.h"
+#include "vlsisapd/openChams/Node.h"
 #include "vlsisapd/openChams/Transistor.h"
 #include "vlsisapd/openChams/Operator.h"
 #include "vlsisapd/openChams/Port.h"
@@ -688,6 +689,7 @@ void Circuit::readSizing(xmlNode* node) {
     }
     
     Sizing* sizing = new Sizing(this);
+    cerr << "** S ** " << node->name << ": " << node->type << endl;
     xmlNode* child = node->children;
     for (xmlNode* node = child; node; node = node->next) {
         if (node->type == XML_ELEMENT_NODE) {
@@ -796,12 +798,15 @@ void Circuit::readLayout(xmlNode* node) {
     
     Layout* layout = new Layout(this);
     xmlNode* child = node->children;
+    cerr << "** L ** " << node->name << ": " << node->type << endl;
     for (xmlNode* node = child; node; node = node->next) {
         if (node->type == XML_ELEMENT_NODE) {
             if (xmlStrEqual(node->name, (xmlChar*)"instance")) {
                 readInstanceLayout(node, layout);
+            } else if (xmlStrEqual(node->name, (xmlChar*)"hbtree")) {
+                readHBTree(node, layout);
             } else {
-                cerr << "[WARNING] Only 'instance' nodes are allowed in 'sizing', others will be ignored." << endl;
+                cerr << "[WARNING] Only 'instance' and 'hbtree' nodes are allowed in 'layout' section, others will be ignored." << endl;
             }
         }
     }
@@ -821,6 +826,90 @@ void Circuit::readInstanceLayout(xmlNode* node, Layout* layout) {
     }
 }
 
+void Circuit::readHBTree(xmlNode* node, Layout* layout) {
+    // HBTree node can have only one child (group or bloc)
+    xmlNode* child = node->children;
+    if (child->type == XML_ELEMENT_NODE) {
+        // create root node
+        //  thanks to readNodeOrBloc
+        Node* root = readNodeOrBloc(child);
+        // save root node in layout
+        layout->setHBTreeRoot(root);
+    }
+}
+
+Node* Circuit::readNodeOrBloc(xmlNode* node, Node* parent) {
+    // 1 - create Node based on xmlNode* passed as argument
+    if (node->type == XML_ELEMENT_NODE) {
+        bool isAGroup = xmlStrEqual(node->name, (xmlChar*)"group");
+        xmlChar* nameC = xmlGetProp(node, (xmlChar*)"name");
+        xmlChar* posiC = xmlGetProp(node, (xmlChar*)"position");
+        if (!nameC) 
+            throw OpenChamsException("[ERROR] 'bloc' and 'group' nodes in 'hbtree' must have at least a 'name' property.");
+        Node* nodeOC = NULL;
+        Name name ((const char*)nameC);
+        Node::Position pos = Node::NONE;
+        if (posiC) {
+            string posStr ((const char*)posiC);
+            if      (posStr == "right")   pos = Node::RIGHT;
+            else if (posStr == "top")     pos = Node::TOP;
+            else throw OpenChamsException("[ERROR] 'position' property of 'bloc' and 'group' nodes must be 'right' or 'top'.");
+        }
+        if (isAGroup) {
+            Group* groupOC = new Group(name, pos, parent);
+            xmlChar* isolatC = xmlGetProp(node, (xmlChar*)"isolation");
+            xmlChar* alignC  = xmlGetProp(node, (xmlChar*)"align");
+            xmlChar* pairedC = xmlGetProp(node, (xmlChar*)"paired");
+            if (isolatC) {
+                string isolation ((const char*)isolatC);
+                if      (isolation == "true")   groupOC->setIsolated(true);
+                else if (isolation == "false")  groupOC->setIsolated(false);
+                else throw OpenChamsException("[ERROR] 'isolation' property of 'group' node must be 'true' or 'false'.");
+            }
+            if (alignC) {
+                string align ((const char*)alignC);
+                Group::Align galign = Group::NONE;
+                if      (align == "vertical")    galign = Group::VERTICAL;
+                else if (align == "horizontal")  galign = Group::HORIZONTAL;
+                else throw OpenChamsException("[ERROR] 'align' property of 'group' node must be 'vertical' or 'horizontal'.");
+                groupOC->setAlign(galign);
+            }
+            if (pairedC) {
+                string paired ((const char*)pairedC);
+                if      (paired == "true")   groupOC->setPaired(true);
+                else if (paired == "false")  groupOC->setPaired(false);
+                else throw OpenChamsException("[ERROR] 'paired' property of 'group' node must be 'true' or 'false'.");
+            }
+            nodeOC = groupOC;
+        } else {
+            nodeOC = new Bloc(name, pos, parent);
+        }
+        // 2 - for each children (up to 2) readNodeOrBloc
+        for (xmlNode* child = node->children; child; child = child->next) {
+            if (child->type == XML_ELEMENT_NODE) {
+                Node* childOC = readNodeOrBloc(child, nodeOC);
+                // 3 - add to returned Node* to current Node* as right or top children (based on its position)
+                switch(childOC->getPosition()) {
+                    case Node::RIGHT:
+                        nodeOC->setRight(childOC);
+                        break;
+                    case Node::TOP:
+                        nodeOC->setTop(childOC);
+                        break;
+                    case Node::NONE:
+                        if (!isAGroup)
+                            throw OpenChamsException("[ERROR] a 'bloc' or 'group' without position is only allowed directly under a 'group'.");
+                        Group* groupOC = dynamic_cast<Group*>(nodeOC);
+                        groupOC->setRootNode(childOC);
+                }
+            }
+        }
+        // 4 - return current Node
+        return nodeOC;
+    }
+    return NULL;
+}
+
 void Circuit::setAbsolutePath(const string filePath) {
     if (filePath[0] == '/')
         _absolutePath = filePath;
@@ -835,7 +924,7 @@ Circuit* Circuit::readFromFile(const string filePath) {
     LIBXML_TEST_VERSION;
     Circuit* cir = NULL;
 
-    xmlDoc* doc = xmlReadFile(filePath.c_str(), NULL, 0);
+    xmlDoc* doc = xmlReadFile(filePath.c_str(), NULL, XML_PARSE_NOBLANKS);
     if (doc == NULL) {
         string error ("[ERROR] Failed to parse: ");
         error += filePath;
@@ -941,13 +1030,75 @@ Layout* Circuit::createLayout() {
     return _layout;
 }
 
+void Circuit::driveHBTree(ofstream& file, Node* node, unsigned indent) {
+    if (!node) return;
+    for (unsigned i = 0 ; i < indent ; i++)
+        file << "  ";
+    string pos = "";
+    switch(node->getPosition()) {
+        case OpenChams::Node::TOP:
+            pos = "top";
+            break;
+        case OpenChams::Node::RIGHT:
+            pos = "right";
+            break;
+        default:
+            break;
+    }
+    
+    Bloc* bloc = dynamic_cast<Bloc*>(node);
+    if (bloc) {
+        file << "<bloc name=\"" << bloc->getName().getString() << "\"";
+        if (pos != "")
+            file << " position=\"" << pos << "\"";
+        if (bloc->getTop() == NULL && bloc->getRight() == NULL)
+            file << "/>" << endl;
+        else {
+            file << ">" << endl;
+            driveHBTree(file, bloc->getTop() , indent+1);
+            driveHBTree(file, bloc->getRight(), indent+1);
+            for (unsigned i = 0 ; i < indent ; i++)
+                file << "  ";
+            file << "</bloc>" << endl;
+        }
+        return;
+    }
+    Group* group = dynamic_cast<Group*>(node);
+    if (group) {
+        string align = "";
+        switch(group->getAlign()) {
+            case OpenChams::Group::VERTICAL:
+                align = "vertical";
+                break;
+            case OpenChams::Group::HORIZONTAL:
+                align = "horizontal";
+                break;
+            default:
+                break;
+        }
+        file << "<group name=\"" << group->getName().getString() << "\"";
+        if (pos != "")            file << " position=\"" << pos << "\"";
+        if (align != "")          file << " align=\"" << align << "\"";
+        if (group->isIsolated())  file << " isolated=\"true\"";
+        if (group->isPaired())    file << " paired=\"true\"";
+        file << ">" << endl;
+        driveHBTree(file, group->getRootNode(), indent+1);
+        driveHBTree(file, group->getTop()     , indent+1);
+        driveHBTree(file, group->getRight()   , indent+1);
+        for (unsigned i = 0 ; i < indent ; i++)
+            file << "  ";
+        file << "</group>" << endl;
+                return;
+    }
+}
+
 bool Circuit::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.";
+        error += " for writing.";
         throw OpenChamsException(error);
     }
     // checks before do anything
@@ -1148,10 +1299,17 @@ bool Circuit::writeToFile(string filePath) {
         }
         file << "  </sizing>" << endl;
     }
-    if (_layout && !_layout->hasNoInstance()) {
+    if (_layout) {
         file << "  <layout>" << endl;
-        for (map<Name, Name>::const_iterator it = _layout->getInstances().begin() ; it != _layout->getInstances().end() ; ++it) {
-            file << "    <instance name=\"" << ((*it).first).getString() << "\" style=\"" << ((*it).second).getString() << "\"/>" << endl;
+        if (!_layout->hasNoInstance()) {
+            for (map<Name, Name>::const_iterator it = _layout->getInstances().begin() ; it != _layout->getInstances().end() ; ++it) {
+                file << "    <instance name=\"" << ((*it).first).getString() << "\" style=\"" << ((*it).second).getString() << "\"/>" << endl;
+            }
+        }
+        if (Node* root = _layout->getHBTreeRoot()) {
+            file << "    <hbtree>" << endl;
+            driveHBTree(file, root, 3);
+            file << "    </hbtree>" << endl;
         }
         file << "  </layout>" << endl;
     }
diff --git a/vlsisapd/src/openChams/src/Layout.cpp b/vlsisapd/src/openChams/src/Layout.cpp
index e478eb26..57de6285 100644
--- a/vlsisapd/src/openChams/src/Layout.cpp
+++ b/vlsisapd/src/openChams/src/Layout.cpp
@@ -3,7 +3,7 @@
  *  openChams
  *
  *  Created by damien dupuis on 31/08/10.
- *  Copyright 2008-2010 UPMC / LIP6. All rights reserved.
+ *  Copyright 2008-2011 UPMC / LIP6. All rights reserved.
  *
  */
 
@@ -15,7 +15,7 @@ using namespace std;
 #include "vlsisapd/openChams/OpenChamsException.h"
 
 namespace OpenChams {
-Layout::Layout(Circuit* circuit): _circuit(circuit) {}
+Layout::Layout(Circuit* circuit): _circuit(circuit), _hbTreeRoot(NULL), _instances() {}
     
 void Layout::addInstance(Name name, Name style) {
     map<Name, Name>::iterator it = _instances.find(name);
diff --git a/vlsisapd/src/openChams/src/Node.cpp b/vlsisapd/src/openChams/src/Node.cpp
new file mode 100644
index 00000000..4c1e0f5e
--- /dev/null
+++ b/vlsisapd/src/openChams/src/Node.cpp
@@ -0,0 +1,34 @@
+/*
+ *  Node.cpp
+ *  openChams
+ *
+ *  Created by damien dupuis on 23/08/11.
+ *  Copyright 2010-2011 UPMC / LIP6. All rights reserved.
+ *
+ */
+
+using namespace std;
+
+#include "vlsisapd/openChams/Node.h"
+
+namespace OpenChams {
+Node::Node(Name nodeName, Position pos, Node* parent) 
+    : _name(nodeName)
+    , _position(pos)
+    , _parent(parent)
+    , _right(NULL)
+    , _top(NULL)
+{}
+    
+Bloc::Bloc(Name blocName, Position pos, Node* parent)
+    : Node(blocName, pos, parent)
+{}
+
+Group::Group(Name groupName, Position pos, Node* parent)
+     : Node(groupName, pos, parent)
+     , _isolated(false)
+     , _paired(false)
+     , _align(Group::NONE)
+{}
+
+} // namespace
diff --git a/vlsisapd/src/openChams/src/PyOpenChams.cpp b/vlsisapd/src/openChams/src/PyOpenChams.cpp
index db55aede..2eabf25b 100644
--- a/vlsisapd/src/openChams/src/PyOpenChams.cpp
+++ b/vlsisapd/src/openChams/src/PyOpenChams.cpp
@@ -16,6 +16,7 @@ using namespace boost::python;
 #include "vlsisapd/openChams/SimulModel.h"
 #include "vlsisapd/openChams/Sizing.h"
 #include "vlsisapd/openChams/Layout.h"
+#include "vlsisapd/openChams/Node.h"
 #include "vlsisapd/openChams/Circuit.h"
 #include "vlsisapd/openChams/Port.h"
 #include "vlsisapd/openChams/Wire.h"
@@ -317,6 +318,8 @@ BOOST_PYTHON_MODULE(OPENCHAMS) {
     STL_MAP_WRAPPING(Name, Name, "LayoutInstancesMap")
     // class OpenChams::Layout
     class_<Layout, Layout*>("Layout", init<Circuit*>())
+        // properties
+        .add_property("hbTreeRoot", make_function(&Layout::getHBTreeRoot, return_value_policy<reference_existing_object>()), &Layout::setHBTreeRoot)
         // accessors
         .def("hasNoInstance", &Layout::hasNoInstance)
         // modifiers
@@ -349,6 +352,47 @@ BOOST_PYTHON_MODULE(OPENCHAMS) {
         .def("writeToFile" , &Circuit::writeToFile)
     ;
 
+    { //this scope is used to define Position as a subenum of Node
+    // class OpenChams::Node
+    scope nod = class_<Node, Node*, boost::noncopyable>("Node", no_init)
+        // properties
+        .add_property("top"  , make_function(&Node::getTop  , return_value_policy<reference_existing_object>()), &Node::setTop  )
+        .add_property("right", make_function(&Node::getRight, return_value_policy<reference_existing_object>()), &Node::setRight)
+        // accessors
+        .def("getName"    , &Node::getName    )
+        .def("getPosition", &Node::getPosition)
+        .def("getParent"  , &Node::getParent  , return_value_policy<reference_existing_object>())
+        .def("isRoot"     , &Node::isRoot     )
+    ;
+
+    enum_<Node::Position>("Position")
+        .value("NONE" , Node::NONE )
+        .value("RIGHT", Node::RIGHT)
+        .value("TOP"  , Node::TOP  )
+        .export_values()
+    ;
+    } // end of node scope
+
+    // class OpenChams::Bloc
+    class_<Bloc, bases<Node> >("Bloc", init<Name, optional<Node::Position, Node*> >())
+    ;
+
+    { // this scope is used to define Align as a subenum of Group
+    // class OpenChams::Group
+    scope grou = class_<Group, bases<Node> >("Group", init<Name, optional<Node::Position, Node*> >())
+        .add_property("rootNode", make_function(&Group::getRootNode, return_value_policy<reference_existing_object>()), &Group::setRootNode)
+        .add_property("isolated", &Group::isIsolated, &Group::setIsolated)
+        .add_property("paired"  , &Group::isPaired  , &Group::setPaired  )
+        .add_property("align"   , &Group::getAlign  , &Group::setAlign   )
+    ;
+
+    enum_<Group::Align>("Align")
+        .value("NONE"      , Group::NONE      )
+        .value("VERTICAL"  , Group::VERTICAL  )
+        .value("HORIZONTAL", Group::HORIZONTAL)
+    ;
+    } // end of group scope
+
     // OpenChamsException translator
     register_exception_translator<OpenChamsException>(translator)
     ;
diff --git a/vlsisapd/src/openChams/src/vlsisapd/openChams/Circuit.h b/vlsisapd/src/openChams/src/vlsisapd/openChams/Circuit.h
index b7230a2d..bee06c21 100644
--- a/vlsisapd/src/openChams/src/vlsisapd/openChams/Circuit.h
+++ b/vlsisapd/src/openChams/src/vlsisapd/openChams/Circuit.h
@@ -30,6 +30,7 @@ class Sizing;
 class Transistor;
 class Operator;
 class Layout;
+class Node;
 
 class Circuit {
     public:
@@ -57,6 +58,8 @@ class Circuit {
     Schematic* createSchematic();
     Sizing*    createSizing();
     Layout*    createLayout();
+
+    void driveHBTree(ofstream&, Node*, unsigned);
     
     bool writeToFile(std::string filePath);
     static Circuit* readFromFile(const std::string filePath);
@@ -91,6 +94,8 @@ class Circuit {
     void      readEquation(xmlNode*, Sizing*);
     void      readLayout(xmlNode*);
     void      readInstanceLayout(xmlNode*, Layout*);
+    void      readHBTree(xmlNode*, Layout*);
+    Node*     readNodeOrBloc(xmlNode*, Node* parent = NULL);
     void      setAbsolutePath(const std::string filePath);
     
     void      check_uppercase(std::string& str, std::vector<std::string>& compares, std::string message);
diff --git a/vlsisapd/src/openChams/src/vlsisapd/openChams/Layout.h b/vlsisapd/src/openChams/src/vlsisapd/openChams/Layout.h
index e6e167e2..e4602e0a 100644
--- a/vlsisapd/src/openChams/src/vlsisapd/openChams/Layout.h
+++ b/vlsisapd/src/openChams/src/vlsisapd/openChams/Layout.h
@@ -15,6 +15,7 @@
 namespace OpenChams {
 class Name;
 class Circuit;
+class Node;
 
 class Layout {
 	public:
@@ -24,14 +25,22 @@ class Layout {
         
         inline bool  hasNoInstance();
         inline const std::map<Name, Name>& getInstances();
+
+        inline Node* getHBTreeRoot();
+        inline void  setHBTreeRoot(Node*);
         
     private:
         Circuit* _circuit;
+        Node*    _hbTreeRoot;
         std::map<Name, Name> _instances; // device name <-> style (name)
-    };
+};
     
-    inline bool   Layout::hasNoInstance() { return (_instances.size() == 0) ? true : false; };
-    inline const  std::map<Name, Name>& Layout::getInstances() { return _instances; };
+inline bool   Layout::hasNoInstance() { return (_instances.size() == 0) ? true : false; };
+inline const  std::map<Name, Name>& Layout::getInstances() { return _instances; };
+
+inline Node* Layout::getHBTreeRoot() { return _hbTreeRoot; }
+inline void  Layout::setHBTreeRoot(Node* root) { _hbTreeRoot = root; }
+
 } // namespace
 #endif
 
diff --git a/vlsisapd/src/openChams/src/vlsisapd/openChams/Node.h b/vlsisapd/src/openChams/src/vlsisapd/openChams/Node.h
new file mode 100644
index 00000000..bbedcc61
--- /dev/null
+++ b/vlsisapd/src/openChams/src/vlsisapd/openChams/Node.h
@@ -0,0 +1,100 @@
+/*
+ *  Node.h
+ *  openChams
+ *
+ *  Created by damien dupuis on 23/08/11.
+ *  Copyright 2010-2011 UPMC / LIP6. All rights reserved.
+ *
+ */
+
+#ifndef __OPENCHAMS_NODE_H__
+#define __OPENCHAMS_NODE_H__
+
+#include "vlsisapd/openChams/Name.h"
+
+namespace OpenChams {
+class Node {
+    public:
+    enum Position { NONE  = 0,
+                    RIGHT = 1,
+                    TOP   = 2
+                  };
+
+	protected:
+    Node(Name nodeName, Position pos, Node* parent);
+    virtual ~Node() {};
+        
+	public:
+    inline Name     getName() const;
+    inline Position getPosition() const;
+    inline Node*    getParent();
+    inline Node*    getRight();
+    inline Node*    getTop();
+    inline bool     isRoot();
+
+    inline void setRight(Node*);
+    inline void setTop(Node*);
+
+    private:
+    Name     _name;
+    Position _position;
+    Node*    _parent;
+    Node*    _right;
+    Node*    _top;
+};
+    
+inline Name           Node::getName() const     { return _name;     }
+inline Node::Position Node::getPosition() const { return _position; }
+inline Node*          Node::getParent()         { return _parent;   }
+inline Node*          Node::getRight()          { return _right;    }
+inline Node*          Node::getTop()            { return _top;      }
+inline bool           Node::isRoot()            { return _parent == NULL; }
+
+inline void Node::setRight(Node* right) { _right = right; }
+inline void Node::setTop(Node* top)     { _top = top; }
+
+
+class Bloc : public Node {
+    public:
+    Bloc(Name blocName, Position pos=Node::NONE, Node* parent=NULL);
+};
+
+class Group : public Node {
+    public:
+    enum Align { NONE       = 0
+               , VERTICAL   = 1
+               , HORIZONTAL = 2
+               };
+
+    Group(Name groupName, Position pos=Node::NONE, Node* parent=NULL);
+
+    inline void setRootNode(Node*);
+    inline void setIsolated(bool);
+    inline void setPaired(bool);
+    inline void setAlign(Align);
+
+    inline Node* getRootNode();
+    inline bool  isIsolated();
+    inline bool  isPaired();
+    inline Align getAlign();
+
+    private:
+    Node* _root;
+    bool  _isolated;
+    bool  _paired;
+    Align _align;
+};
+
+inline void Group::setRootNode(Node* root)      { _root = root; }
+inline void Group::setIsolated(bool isolated)   { _isolated = isolated; }
+inline void Group::setPaired(bool paired)       { _paired = paired; }
+inline void Group::setAlign(Group::Align align) { _align = align; }
+
+inline Node*        Group::getRootNode() { return _root; }
+inline bool         Group::isIsolated()  { return _isolated; }
+inline bool         Group::isPaired()    { return _paired; }
+inline Group::Align Group::getAlign()    { return _align; }
+
+} // namespace
+#endif
+