blob: f245254a44122fa743a052e5cea85c71e559a20a [file] [log] [blame]
/*
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()
{
QQueue<LogicUnit*> nodequeue;
QHash<QString, LogicUnit*> donehashtable;
for (int i = 0; i < myOdin->blifexplorer_netlist->num_top_input_nodes; i++){
QString name = myOdin->blifexplorer_netlist->top_input_nodes[i]->name;
nodequeue.enqueue(getReferenceToUnit(name));
}
// Enqueue constant nodes.
nnode_t* constant_nodes[] = {myOdin->blifexplorer_netlist->gnd_node,
myOdin->blifexplorer_netlist->vcc_node,
myOdin->blifexplorer_netlist->pad_node};
int num_constant_nodes = 3;
for (int 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(int 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(){
int error_code = 0;
if(!odinStarted){
myOdin->setFilename(myFilename);
error_code = myOdin->startOdin();
}
else
{
std::cout << "odin is already started";
}
odinStarted = (error_code == 0)? true: false;
if(odinStarted){
odinTable = myOdin->getNodeTable();
}
else
{
std::cout << "odin failed to start with error:" << std::to_string(error_code);
exit(1);
}
}
/*---------------------------------------------------------------------------------------------
* (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,"%s", ((char*)actName.toLocal8Bit().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 && endNode->hasModule){
startModule = startNode->getModule();
endModule = endNode->getModule();
if(startModule->getName().compare(endModule->getName())!=0){
//both connections are in modules
startModule->addConnection(newWire);
endModule->addConnection(newWire);
newWire->setEndModule(endModule);
newWire->setStartModule(startModule);
}
}else if(startNode->hasModule){
startModule = startNode->getModule();
startModule->addConnection(newWire);
newWire->setStartModule(startModule);
}else if(endNode->hasModule){
endModule = endNode->getModule();
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 && endNode->hasModule){
startModule = startNode->getModule();
endModule = endNode->getModule();
if(startModule->getName().compare(endModule->getName())!=0){
//both connections are in modules
startModule->addConnection(newWire);
endModule->addConnection(newWire);
newWire->setEndModule(endModule);
newWire->setStartModule(startModule);
}
}else if(startNode->hasModule){
startModule = startNode->getModule();
startModule->addConnection(newWire);
newWire->setStartModule(startModule);
}else if(endNode->hasModule){
endModule = endNode->getModule();
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 < myOdin->blifexplorer_netlist->num_top_input_nodes; i++){
QString name = myOdin->blifexplorer_netlist->top_input_nodes[i]->name;
nodequeue.enqueue(getReferenceToUnit(name));
}
// Enqueue constant nodes.
nnode_t* constant_nodes[] = {myOdin->blifexplorer_netlist->gnd_node,
myOdin->blifexplorer_netlist->vcc_node,
myOdin->blifexplorer_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;
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: 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());
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();
}