/*

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "container.h"
#include <time.h>

Container::Container(ExplorerScene* scene)
{
    myScene = scene;
    maxlayer = 0;
    maxcountPerLayer = 0;
    myOdin = new OdinInterface();
    odinStarted = false;
    simOffset = 0;
    maxSimStep = 0;
    actSimStep = 0;
}

/*---------------------------------------------------------------------------------------------
 * (function: setFilename)
 *-------------------------------------------------------------------------------------------*/
void Container::setFilename(QString filename)
{
    myFilename = filename;
    myOdin->setFilename(filename);
}

/*---------------------------------------------------------------------------------------------
 * (function: addUnit)
 *-------------------------------------------------------------------------------------------*/
LogicUnit * Container::addUnit(QString name,LogicUnit::UnitType type, QPointF position,
                               nnode_t* odinRef)
{
    LogicUnit* newUnit;
    //create in scene
    newUnit = myScene->addLogicUnit(name,type,position);
    newUnit->setPos(position);
    newUnit->setOdinRef(odinRef);
    unithashtable[name] = newUnit;
    unitcontainer.append(newUnit);
    return newUnit;
}

/*---------------------------------------------------------------------------------------------
 * (function: addModule)
 *-------------------------------------------------------------------------------------------*/
LogicUnit * Container::addModule(QString name)
{
    LogicUnit* newUnit;
    //create in scene
    newUnit = myScene->addLogicUnit(name,LogicUnit::Module,QPointF(100,100));
    newUnit->setPos(QPointF(100,100));
    unithashtable[name] = newUnit;
    unitcontainer.append(newUnit);
    return newUnit;
}

/*---------------------------------------------------------------------------------------------
 * (function: addConnectionHash)
 *-------------------------------------------------------------------------------------------*/
bool Container::addConnectionHash(QString start, QString end)
{
    //do not connect modules with themself
    if(start.compare(end) == 0)
        return false;

    bool startFound = false;
    bool endFound = false;
    bool success = false;
    LogicUnit *startUnit, *endUnit;
    if(unithashtable.contains(start)){
        startUnit = unithashtable.value(start);
        startFound = true;
    }
    if(unithashtable.contains(end)){
        endUnit = unithashtable.value(end);
        endFound = true;
    }
    if(startFound && endFound){
        myScene->addConnection(startUnit, endUnit);
        success = true;
    }
    return success;

}

/*---------------------------------------------------------------------------------------------
 * (function: arrangeContainer)
 *-------------------------------------------------------------------------------------------*/
//arrange the modules according to their layer.
//at the moment wire crossing is not considered
void Container::arrangeContainer()
{
    computeLayers();
    spreadLayers();
    myScene->setSceneRect(0,0,1000.0+400*maxlayer+maxcountPerLayer*50,1000.0+400*maxcountPerLayer);
}

/*---------------------------------------------------------------------------------------------
 * (function: deleteModule)
 *-------------------------------------------------------------------------------------------*/
void Container::deleteModule(QString name)
{
    for(int i = 0;i<unitcontainer.count();i++){
        LogicUnit *temp = unitcontainer.at(i);
        if(temp->getName().compare(name)==0){
            unitcontainer.removeAt(i);
        }
    }
    if(unithashtable.contains(name))
        unithashtable.remove(name);
}

/*---------------------------------------------------------------------------------------------
 * (function: clearContainer)
 *-------------------------------------------------------------------------------------------*/
//delete everything in the container
void Container::clearContainer()
{
    while(!unitcontainer.empty()){
        unitcontainer.removeFirst();
    }
    unithashtable.clear();
}

/*---------------------------------------------------------------------------------------------
 * (function: setLayer)
 *-------------------------------------------------------------------------------------------*/
void Container::setLayer(QString unitName, int layercount){
    QString actName;

    foreach (LogicUnit *actUnit, unitcontainer) {
        actName = actUnit->getName();
        if(actName.compare(unitName)==0){
            if(layercount > actUnit->getLayer()){
                   actUnit->setLayer(layercount);
            }
        }
    }

}

/*---------------------------------------------------------------------------------------------
 * (function: computeLayersHash)
 *-------------------------------------------------------------------------------------------*/
//A smarter function to compute the layers.
void Container::computeLayersHash()
{
    QHash<QString, LogicUnit *> currentStep = arrHashtable;
    QHash<QString, LogicUnit *> nextStep;
    QHash<QString, LogicUnit *>::const_iterator blockIterator = currentStep.constBegin();
    LogicUnit *actUnit;

    for(int i = unitcontainer.count(); i>=0;i--){
        while(blockIterator != currentStep.constEnd()){
            actUnit = blockIterator.value();
            //adjust the layers of all "children"
            QList<Wire *> cons = actUnit->getOutCons();
            foreach(Wire *wire, cons){
                //go through all of the ends and set the layer to layer+1
                int newLayer = actUnit->getLayer()+1;
                wire->endUnit()->setLayer(newLayer);
                nextStep.insert(wire->endUnit()->getName(),wire->endUnit());
                if(newLayer > maxlayer){
                    maxlayer = newLayer;
                }
            }
            //get next Item
            ++blockIterator;
        }
        currentStep.clear();
        currentStep = nextStep;
        nextStep.clear();
        blockIterator = currentStep.constBegin();
    }
}

/*---------------------------------------------------------------------------------------------
 * (function: getMaxParentLayer)
 *-------------------------------------------------------------------------------------------*/
int Container::getMaxParentLayer(LogicUnit* node){
    QList<LogicUnit*> parents = node->getParents();
    int result = -1;
    foreach(LogicUnit* parent, parents){
        if(parent->getLayer() > result){
            result = parent->getLayer();
        }
    }
    return result;
}

/*---------------------------------------------------------------------------------------------
 * (function: copySimCyclesintoNodes)
 *-------------------------------------------------------------------------------------------*/
void Container::copySimCyclesIntoNodes()
{   //for each cycle which was simulated         //int value;
    //int i;, copy the values into the nodes
    int cycle;
    for(cycle=0+simOffset;cycle<maxSimStep;cycle++){
        QHash<QString, nnode_t *>::const_iterator blockIterator = odinTable.constBegin();

        while(blockIterator != odinTable.constEnd()){
             int value;
             int i;
             QString name = blockIterator.key();
             LogicUnit* visNode = unithashtable[name];
             nnode_t* node = blockIterator.value();
             //for each output pin of the node update the current value
             for(i=0;i<node->num_output_pins;i++){
                 value = myOdin->getOutputValue(node, i, cycle);
                 visNode->setOutValue(i, value, cycle);
                 visNode->updateWires();
             }
             ++blockIterator;
        }
    }
}

/*---------------------------------------------------------------------------------------------
 * (function: computeLayers)
 *-------------------------------------------------------------------------------------------*/
//compute the layers of all modules inside the container
void Container::computeLayers()
{
    int i;

    QQueue<LogicUnit*> nodequeue;
    QHash<QString, LogicUnit*> donehashtable;
    for (i = 0; i < verilog_netlist->num_top_input_nodes; i++){
        QString name = verilog_netlist->top_input_nodes[i]->name;
        nodequeue.enqueue(getReferenceToUnit(name));
    }

    // Enqueue constant nodes.
    nnode_t* constant_nodes[] = {verilog_netlist->gnd_node,
                                 verilog_netlist->vcc_node,
                                 verilog_netlist->pad_node};
    int num_constant_nodes = 3;
    for (i = 0; i < num_constant_nodes; i++){
        QString name = constant_nodes[i]->name;
        nodequeue.enqueue(getReferenceToUnit(name));
    }

    // go through the netlist. While doing so
    // remove nodes from the queue and add followup nodes
    LogicUnit* node;
    int maxparent;
    while(!nodequeue.isEmpty()){
        node = nodequeue.dequeue();
        //remember name of the node so it is not processed again
        QString nodeName(node->getName());
        //assign layer
        maxparent = getMaxParentLayer(node);

        //only if the node is visible it is considered for a layer
        if(node->isVisible()){
            node->setLayer(maxparent+1);
        }
        if(node->getLayer()>maxlayer){
            maxlayer = node->getLayer();
        }
        //save node in hash, so it will be processed only once
        donehashtable[nodeName] = node;
        //Enqueue child nodes which are ready
        int num_children = 0;
        nnode_t** children = get_children_of(node->getOdinRef(), &num_children);

        // connect node to all children
        //enqueue children if not already done or in queue
        for(i=0; i< num_children; i++){
            nnode_t* nodeKid = children[i];
            QString kidName(nodeKid->name);
            LogicUnit* kidUnit = getReferenceToUnit(kidName);

            bool inQueue = nodequeue.contains(kidUnit);
            bool done = donehashtable.contains(kidName);

            if(!inQueue && !done && parentsDone(kidUnit,donehashtable)){
                nodequeue.enqueue(kidUnit);
            }
        }
    }
    maxlayer++;
    /*Locate all outputs at the very end of the graph*/
    QHash<QString, LogicUnit*>::const_iterator blockIterator = unithashtable.constBegin();
    for(int i = 0; i<=maxlayer;i++){
        blockIterator = unithashtable.constBegin();
        while(blockIterator != unithashtable.constEnd()){
            LogicUnit* actUnit = blockIterator.value();
            if(actUnit->getName().contains("top^out")){
                actUnit->setLayer(maxlayer);
            }

            ++blockIterator;
        }
    }

}

/*---------------------------------------------------------------------------------------------
 * (function: spreadLayers)
 *-------------------------------------------------------------------------------------------*/
void Container::spreadLayers()
{
    QHash<QString, LogicUnit*>::const_iterator blockIterator = unithashtable.constBegin();
    LogicUnit* lastUnit = NULL;
    int counter = 0;
    int offset = 200;

    for(int i = 0; i<=maxlayer;i++){
        blockIterator = unithashtable.constBegin();

        while(blockIterator != unithashtable.constEnd()){
            LogicUnit* actUnit = blockIterator.value();
            if(actUnit->isVisible()){
                if(actUnit->getLayer()== i){
                    actUnit->setPos(offset+15*counter,100.0+200*counter);
                    actUnit->updateWires();
                    lastUnit = actUnit;
                    counter++;
                }
                if(maxcountPerLayer < counter){
                    maxcountPerLayer = counter;
                }
            }
            ++blockIterator;
        }
        if(lastUnit!=NULL){
            offset = lastUnit->x()+200;
        }else{
            offset = 200;
        }

        counter = 0;

    }

}

/*---------------------------------------------------------------------------------------------
 * (function: startOdin)
 *-------------------------------------------------------------------------------------------*/
void Container::startOdin(){
    if(!odinStarted){
        myOdin->setFilename(myFilename);
        myOdin->startOdin();
        odinStarted = true;
        odinTable = myOdin->getNodeTable();
    }
}

/*---------------------------------------------------------------------------------------------
 * (function: createNodesFromOdin)
 *-------------------------------------------------------------------------------------------*/
int Container::createNodesFromOdin(){
    QHash<QString, nnode_t *>::const_iterator blockIterator = odinTable.constBegin();
    int items = 0;
    int odinNodeCount = odinTable.count();
     while(blockIterator != odinTable.constEnd()){
         QString actName = blockIterator.key();
         nnode_t* actOdinNode = blockIterator.value();
         operation_list odinType = actOdinNode->type;
         LogicUnit::UnitType type;

         switch(odinType){
         case CLOCK_NODE:
             type = LogicUnit::Clock;
             break;
         case INPUT_NODE:         
             type = LogicUnit::Input;
            break;
         case FF_NODE:
             type = LogicUnit::Latch;
             break;
         case OUTPUT_NODE:
             type = LogicUnit::Output;
             break;
         case LOGICAL_AND:
             type = LogicUnit::And;
             break;
         case LOGICAL_OR:
             type = LogicUnit::Or;
             break;
         case LOGICAL_NOT:
             type = LogicUnit::Not;
             break;
         case LOGICAL_NAND:
             type = LogicUnit::Nand;
             break;
         case LOGICAL_XOR:
             type = LogicUnit::Xor;
             break;
         case LOGICAL_XNOR:
             type = LogicUnit::Xnor;
             break;
         case LOGICAL_NOR:
             type = LogicUnit::Nor;
             break;
         case MUX_2:
             type = LogicUnit::MUX;
             break;
         case ADDER_FUNC:
             type = LogicUnit::ADDER_FUNC;
             break;
         case CARRY_FUNC:
             type = LogicUnit::CARRY_FUNC;
             break;
         case MULTIPLY:
             type = LogicUnit::MULTIPLY;
             break;
         case ADD:
             type = LogicUnit::ADD;
             break;
         case MINUS:
             type = LogicUnit::MINUS;
             break;
         case MEMORY:
             type = LogicUnit::MEMORY;
             break;
         default:
             type = LogicUnit::LogicGate;
             break;
         }
        //add Unit with name and type
         addUnit(actName, type,QPointF(100,100),actOdinNode);
         if(actName.contains("+")){
             assignToModule(actName);
             unithashtable[actName]->setVisible(false);
         }
         items++;
         if((100*items/odinNodeCount)%5==0)
         {
             fprintf(stdout, "VISUALIZATION: Node progress: %d\n", 100*items/odinNodeCount);
         }
         ++blockIterator;
     }
     fprintf(stderr, "Created Nodes from Netlist: %d\n", items);
     return items;
}

/*---------------------------------------------------------------------------------------------
 * (function: parentsDone)
 *-------------------------------------------------------------------------------------------*/
bool Container::parentsDone(LogicUnit *unit, QHash<QString, LogicUnit *> donehashlist)
{
    //in case it is a flipFlop the parents don't have to be done
    //FlipFlops can be parts of cycles.
    if(unit->unitType() == LogicUnit::Latch ||
            unit->unitType() == LogicUnit::MEMORY){
        return true;
    }

    bool result = true;
    QList<LogicUnit*> parents = unit->getParents();
    foreach(LogicUnit* parent,parents){
        if(!donehashlist.contains(parent->getName())){
            result = false;
        }
    }
    return result;
}

/*---------------------------------------------------------------------------------------------
 * (function: parentsDone)
 *-------------------------------------------------------------------------------------------*/
bool Container::parentsDone(LogicUnit *unit)
{
    bool result = true;
    QList<LogicUnit*> parents = unit->getParents();
    foreach(LogicUnit* parent,parents){
        if(!completeNodes.contains(parent->getName())){
            result = false;
        }
    }
    return result;
}


int Container::createConnectionsFromOdinIterate()
{
    //only create connections if nodes are created
    if(myItemcount <= 0)
        return -1;
    //create all connections while iterating through all nodes
    //leave out the clocks
    //(visual reasons. The clock should be added last to be at the right port)
    int conCount = 0;
    int itemNr = 0;
    int j,i, itemTotal;
    bool clocksFound = false;

    QHash<QString, LogicUnit *> hash =unithashtable;
    QHash<QString, LogicUnit *>::const_iterator blockIterator = hash.constBegin();
    itemTotal = hash.count();
     while(blockIterator != hash.constEnd()){
         QString actName = blockIterator.key();
         LogicUnit* actNode = blockIterator.value();

         if(actNode->unitType() == LogicUnit::Module){
             ++blockIterator;
             continue;
         }

         if(actNode->getOdinRef()->type == CLOCK_NODE){
             if(!clocks.contains(actNode)){
                clocks.append(actNode);
                clocksFound = true;
             }
         }else{//if the node is not a clock node, create all output connections
             int output_number = actNode->getOdinRef()->num_output_pins;
             for(j=0; j<output_number;j++)
             {
                 int num_children = 0;
                 nnode_t** children = get_children_of_nodepin(actNode->getOdinRef(), &num_children,j);
                 QHash<QString, nnode_t*> childrenDone;
                 for(i=0; i< num_children; i++){
                     nnode_t* nodeKid = children[i];
                     QString kidName(nodeKid->name);
                     //LogicUnit* kidUnit = getReferenceToUnit(kidName);

                     if(!childrenDone.contains(kidName)){
                         //bool success = addConnectionHashByRef(actNode,kidUnit);
                         bool success = addConnectionHash(actName,kidName);
                         if(!success){
                             /*FIXME: This error is sometimes created by Odin as
                                         the method get_children_of(node->getOdinRef(), &num_children)
                                         sometimes returns a node itself as its child.*/
                             fprintf(stderr, "CONTAINER:  Warning: Node has itself in childlist in Odin II:");
                             fprintf(stderr,actName.toAscii().data());
                             fprintf(stderr,"\n");
                         }else{
                         //for hard blocks add the output pin of the created connection
                             Wire* newWire = getConnectionBetween(actName, kidName);
                             newWire->setMaxOutputPinNumber(
                                         actNode->getOdinRef()->num_output_pins);
                             newWire->setMyOutputPinNumber(j+1);
                             //add modules to connection if needed
                             LogicUnit* startNode = unithashtable[actName];
                             LogicUnit* startModule;
                             LogicUnit* endNode = unithashtable[kidName];
                             LogicUnit* endModule;
                             if(startNode->hasModule){
                                startModule = startNode->getModule();
                             }
                             if(endNode->hasModule){
                                 endModule = endNode->getModule();
                             }
                             if(startNode->hasModule && endNode->hasModule){
                                 if(startModule->getName().compare(endModule->getName())==0){
                                     //do nothing because the connection is inside the module
                                     ;
                                 }else{//both connections are in modules
                                     startModule->addConnection(newWire);
                                     endModule->addConnection(newWire);
                                     newWire->setEndModule(endModule);
                                     newWire->setStartModule(startModule);
                                 }
                             }else if(startNode->hasModule){
                                 startModule->addConnection(newWire);
                                 newWire->setStartModule(startModule);
                             }else if(endNode->hasModule){
                                endModule->addConnection(newWire);
                                newWire->setEndModule(endModule);
                             }

                             childrenDone[kidName] = nodeKid;
                             conCount++;
                             if(conCount%500 == 0){
                                fprintf(stdout, "CONTAINER:  Connection progress: %d Cons, %d.%d Percent.\n", conCount, 100*itemNr/itemTotal,
                                        (10000*itemNr/itemTotal)%100);
                                fflush(stdout);
                             }
                         }
                     }
                 }
             }
         }

         //go through each output pin of the node and create all connections
         itemNr++;
         ++blockIterator;
     }

     //create all clock connections if clocks exist
     if(clocksFound){
         //for all clocks create the connections
         foreach(LogicUnit* clock, clocks){
             int num_children = 0;
             nnode_t** children = get_children_of(clock->getOdinRef(), &num_children);
             QString clockName = clock->getName();

             // connect clock to all children
             for(i=0; i< num_children; i++){
                 nnode_t* nodeKid = children[i];
                 QString kidName(nodeKid->name);
                 addConnectionHash(clockName,kidName);

                 Wire* newWire = getConnectionBetween(clockName, kidName);
                 LogicUnit* startNode = unithashtable[clockName];
                 LogicUnit* startModule;
                 LogicUnit* endNode = unithashtable[kidName];
                 LogicUnit* endModule;
                 if(startNode->hasModule){
                    startModule = startNode->getModule();
                 }
                 if(endNode->hasModule){
                     endModule = endNode->getModule();
                 }
                 if(startNode->hasModule && endNode->hasModule){
                     if(startModule->getName().compare(endModule->getName())==0){
                         //do nothing because the connection is inside the module
                         ;
                     }else{//both connections are in modules
                         startModule->addConnection(newWire);
                         endModule->addConnection(newWire);
                         newWire->setEndModule(endModule);
                         newWire->setStartModule(startModule);
                     }
                 }else if(startNode->hasModule){
                     startModule->addConnection(newWire);
                     newWire->setStartModule(startModule);
                 }else if(endNode->hasModule){
                    endModule->addConnection(newWire);
                    newWire->setEndModule(endModule);
                 }

                 conCount++;
             }
         }
     }
     return conCount;


}


/*---------------------------------------------------------------------------------------------
 * (function: createConnectionsFromOdin)
 *-------------------------------------------------------------------------------------------*/
int Container::createConnectionsFromOdin()
{
    //only create connections if nodes are created
    if(myItemcount <= 0)
        return -1;
    //create all connections while traversing through the netlist
    //leave out the clocks
    //(visual reasons. The clock should be added last to be at the right port)
    int i, j, conCount;
    conCount = 0;
    QQueue<LogicUnit*> nodequeue;
    QHash<QString, LogicUnit*> donehashtable;

    for (i = 0; i < verilog_netlist->num_top_input_nodes; i++){
        QString name = verilog_netlist->top_input_nodes[i]->name;
        nodequeue.enqueue(getReferenceToUnit(name));
    }

    // Enqueue constant nodes.
    nnode_t* constant_nodes[] = {verilog_netlist->gnd_node,
                                 verilog_netlist->vcc_node,
                                 verilog_netlist->pad_node};
    int num_constant_nodes = 3;
    for (i = 0; i < num_constant_nodes; i++){
        QString name = constant_nodes[i]->name;
        nodequeue.enqueue(getReferenceToUnit(name));
    }

    // go through the netlist. While doing so
    // remove nodes from the queue and add followup nodes
    LogicUnit* node;
    QList<LogicUnit*> clocks;
    bool clockFound = false;
    while(!nodequeue.isEmpty()){
        node = nodequeue.dequeue();
        //remember name of the node so it is not processed again
        QString nodeName(node->getName());
        //save node in hash, so it will be processed only once
        donehashtable[nodeName] = node;
        //check each output pin for children.
        int output_number = node->getOdinRef()->num_output_pins;
        for(j=0; j<output_number;j++)
        {
            //Enqueue child nodes which are ready
            int num_children = 0;
            nnode_t** children = get_children_of_nodepin(node->getOdinRef(), &num_children,j);
            QHash<QString, nnode_t*> childrenDone;//used to not create a connection multiple times
            // connect node to all children
            //enqueue children if not already done or in queue
            for(i=0; i< num_children; i++){
                nnode_t* nodeKid = children[i];
                QString kidName(nodeKid->name);
                LogicUnit* kidUnit = getReferenceToUnit(kidName);

                bool inQueue = nodequeue.contains(getReferenceToUnit(kidName));
                bool done = donehashtable.contains(kidName);

                if(node->getOdinRef()->type != CLOCK_NODE)
                {
                    if(!childrenDone.contains(kidName)){
                        bool success = addConnectionHash(nodeName,kidName);
                        if(!success){
                            /*FIXME: This error is sometimes created by Odin as
                                        the method get_children_of(node->getOdinRef(), &num_children)
                                        sometimes returns a node itself as its child.*/
                            fprintf(stderr, "CONTAINER:  Warning: Node has itself in childlist in Odin II.\n");
                        }else{
                        //for hard blocks add the output pin of the created connection
                            Wire* newWire = getConnectionBetween(nodeName, kidName);
                            newWire->setMaxOutputPinNumber(
                                        getReferenceToUnit(nodeName)->getOdinRef()->num_output_pins);
                            newWire->setMyOutputPinNumber(j+1);
                            childrenDone[kidName] = nodeKid;
                            conCount++;
                        }
                    }
                }else if(!clocks.contains(node)){
                    clocks.append(node);
                    clockFound = true;
                }

                if(!inQueue && !done && parentsDone(kidUnit,donehashtable)){
                    nodequeue.enqueue(kidUnit);
                }else if(!inQueue && !done && kidUnit->getOdinRef()->type == FF_NODE){
                    nodequeue.enqueue(kidUnit);
                }
            }
        }
    }

    //create clock connections
    int num_children = 0;
    if(clockFound){
        //for all clocks create the connections
        foreach(LogicUnit* clock, clocks){
            nnode_t** children = get_children_of(clock->getOdinRef(), &num_children);
            QString clockName = clock->getName();

            // connect clock to all children
            for(i=0; i< num_children; i++){
                nnode_t* nodeKid = children[i];
                QString kidName(nodeKid->name);
                addConnectionHash(clockName,kidName);
                conCount++;
            }
        }
    }
    //return connection count
    return conCount;
}

/*---------------------------------------------------------------------------------------------
 * (function: readInFileOdinOnly)
 *-------------------------------------------------------------------------------------------*/
/**
  * Reads in the file in Odin and creates the nodes based on the netlist provided by odin.
  */
int Container::readInFileOdinOnly(){
    //used to measure the time, which is needed to create a graph
    clock_t start, finish;
    int cons;
    start = clock();
    //let odin ii parse in the file and return a hashtable of all nodes in the netlist
    startOdin();
    fprintf(stdout, "VISUALIZATION: Creating nodes...\n");
    //iterate through the hashtable and create all nodes based on the type
    myItemcount = createNodesFromOdin();
    fprintf(stdout, "VISUALIZATION: Creating Node connections...\n");
     //create connections
    cons = createConnectionsFromOdinIterate();
     if(myItemcount <= 0)
         return -1;

     finish = clock();
     fprintf(stderr, "Nodes: %d, Cons: %d, Time: %f\n", myItemcount, cons, (double)(finish - start)/CLOCKS_PER_SEC);
     return 0;

}

/*---------------------------------------------------------------------------------------------
 * (function: findByName)
 *-------------------------------------------------------------------------------------------*/
QHash<QString, LogicUnit *> Container::findByName(QString name)
{
    QHash<QString, LogicUnit *> result;
    QHash<QString, LogicUnit *> hash =unithashtable;
    QHash<QString, LogicUnit *>::const_iterator blockIterator = hash.constBegin();

     while(blockIterator != unithashtable.constEnd()){
         QString actName = blockIterator.key();
         if(actName.contains(name, Qt::CaseInsensitive)){
            result.insert(actName, blockIterator.value());
            blockIterator.value()->setBrush(QColor(23,255,255,255));
         }
         ++blockIterator;
     }
     return result;
}

/*---------------------------------------------------------------------------------------------
 * (function: getReferenceToUnit)
 *-------------------------------------------------------------------------------------------*/
LogicUnit * Container::getReferenceToUnit(QString name)
{
    if(!unithashtable.contains(name)){
        fprintf(stderr, "Container: Not all nodes could be connected!\n");
    }
    return unithashtable[name];
}

/*---------------------------------------------------------------------------------------------
 * (function: getMaxSimStep)
 *-------------------------------------------------------------------------------------------*/
int Container::getMaxSimStep()
{
    return maxSimStep;
}

/*---------------------------------------------------------------------------------------------
 * (function: getActSimiStep)
 *-------------------------------------------------------------------------------------------*/
int Container::getActSimStep()
{
    return actSimStep;
}

/*---------------------------------------------------------------------------------------------
 * (function: startSimulator)
 *-------------------------------------------------------------------------------------------*/
int Container::startSimulator()
{
    myOdin->setUpSimulation();
    maxSimStep = myOdin->simulateNextWave();
    copySimCyclesIntoNodes();
    /*
    myOdin->simulateNextWave();
    myOdin->endSimulation();
    copySimCyclesIntoNodes();*/
    return 0;
}

int Container::simulateNextWave()
{
    int success = -1;
    simOffset = maxSimStep;
    maxSimStep = myOdin->simulateNextWave();
    copySimCyclesIntoNodes();

    return success;
}

void Container::resetAllHighlights()
{
    QHash<QString, LogicUnit *> hash =unithashtable;
    QHash<QString, LogicUnit *>::const_iterator blockIterator = hash.constBegin();

     while(blockIterator != unithashtable.constEnd()){
        LogicUnit *unit = blockIterator.value();
        unit->setBrush(QColor(255,255,255,255));
        QList<Wire *> list = unit->getAllCons();
        foreach (Wire *wire, list) {
            wire->setColor(QColor(0,0,0,255));
            wire->setZValue(-1000);
            wire->update();
        }
         ++blockIterator;
     }
}

void Container::setVisibilityForAll(bool value)
{
    QHash<QString, LogicUnit *> hash =unithashtable;
    QHash<QString, LogicUnit *>::const_iterator blockIterator = hash.constBegin();

     while(blockIterator != unithashtable.constEnd()){
        LogicUnit *unit = blockIterator.value();
        unit->setShown(value);
        QList<Wire *> list = unit->getAllCons();
        foreach (Wire *wire, list) {
            wire->updatePosition();
        }
         ++blockIterator;
     }
}

void Container::showActivity()
{
    QHash<QString, nnode_t *>::const_iterator blockIterator = odinTable.constBegin();

    while(blockIterator != odinTable.constEnd()){
         QString name = blockIterator.key();
         LogicUnit* visNode = unithashtable[name];
         //get all connections outgoing and advise them to
         //represent the activity by color
         QList<Wire*> outgoingWires = visNode->getOutCons();
         foreach(Wire* wire, outgoingWires){
             wire->showActivity();
             wire->update();
         }
         visNode->showActivity();

         ++blockIterator;
    }

}

void Container::getActivityInformation()
{
    //right now it is a dummy function. the activity values are
    //generated randomly
    QHash<QString, nnode_t *>::const_iterator blockIterator = odinTable.constBegin();

    while(blockIterator != odinTable.constEnd()){
         QString name = blockIterator.key();
         LogicUnit* visNode = unithashtable[name];
         //get all connections outgoing and advise them to
         //represent the activity by color
         QList<Wire*> outgoingWires = visNode->getOutCons();
         foreach(Wire* wire, outgoingWires){
             int act = qrand() % 255;
             wire->setActivity(act);

         }
        ++blockIterator;
    }
}

/*---------------------------------------------------------------------------------------------
 * (function: showSimulationStep)
 *-------------------------------------------------------------------------------------------*/
void Container::showSimulationStep(int cycle)
{
    actSimStep = cycle;

    //if current step is bigger than the last cycle, create new values
    if(actSimStep>maxSimStep){
        maxSimStep = myOdin->simulateNextWave();
        copySimCyclesIntoNodes();
    }

    //visit each node and update the output status of each one of them
    QHash<QString, nnode_t *>::const_iterator blockIterator = odinTable.constBegin();

    while(blockIterator != odinTable.constEnd()){
         QString name = blockIterator.key();
         LogicUnit* visNode = unithashtable[name];
         visNode->setCurrentCycle(cycle);
         ++blockIterator;
    }
    //actSimStep = (simOffset+1)%64;
}

/*---------------------------------------------------------------------------------------------
 * (function: setEdge)
 *-------------------------------------------------------------------------------------------*/
void Container::setEdge(int i)
{
    if(odinStarted){
        myOdin->setEdge(i);
    }
}

/*---------------------------------------------------------------------------------------------
 * (function: getConnectionBetween)
 *-------------------------------------------------------------------------------------------*/
Wire *Container::getConnectionBetween(QString nodeName, QString kidName)
{
    Wire* result = NULL;
    QHash<QString, Wire *> wires;
    QHash<QString, LogicUnit *> hash =unithashtable;
    QHash<QString, LogicUnit *>::const_iterator blockIterator = hash.constBegin();

     while(blockIterator != unithashtable.constEnd()){
         QString actName = blockIterator.key();
         if(actName.compare(nodeName)==0){
             LogicUnit* actUnit = blockIterator.value();
             wires = actUnit->getOutConsHash();
         }
         ++blockIterator;
     }

     if(wires.contains(kidName)){
        result = wires.value(kidName);
     }
     return result;
}

QList<LogicUnit *> Container::getClocks()
{
    return clocks;
}

QString Container::extractModuleFromName(QString name){
    if(!name.contains("+"))
        return QString("");

    QString result = name.left(name.lastIndexOf("+"));
    result = result.right(result.length()-name.lastIndexOf(".")-1);
    return result;
}

void Container::assignNodeToModule(QString nodeName,
                                   QString moduleName){
    LogicUnit* node = unithashtable[nodeName];
    LogicUnit* module = unithashtable[moduleName];

    node->addPartner(module);
    module->addPartner(node);
}

void Container::assignToModule(QString actName)
{
    //extract module
    QString moduleName = extractModuleFromName(actName);
    //check if module exist
    if(!unithashtable.contains(moduleName)){
        //create module
        addModule(moduleName);
    }
    //assign node to module
    assignNodeToModule(actName, moduleName);
}

void Container::expandCollapse(QString modulename)
{
    bool makeAllVisible;
    LogicUnit* module = unithashtable[modulename];

    makeAllVisible = module->isVisible();

    //toggle module visibility
    module->setVisible(!module->isVisible());
    bool now = module->isVisible();

    QHash<QString, LogicUnit *> hash =unithashtable;
    QHash<QString, LogicUnit *>::const_iterator blockIterator = hash.constBegin();

     while(blockIterator != unithashtable.constEnd()){
         LogicUnit* actNode = blockIterator.value();
         if(actNode->hasModule &&
                 actNode->getModule()->getName().compare(modulename)==0){
            actNode->setVisible(makeAllVisible);
         }
         ++blockIterator;
     }
     arrangeContainer();


}



