CppLogicGateSimulator / circuit.cpp
circuit.cpp
Raw
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <sstream>
#include "node.h"
#include "gate.h"
#include "gateAND.h"
#include "gateOR.h"
#include "gateNOT.h"
#include "circuit.h"

vector<string> mySplitFunction(const string &s);

//run the functions needed to load a circuit (fiorst nodes, then gate)
void circuit::load_circuit_from_file(string inFileName)
{
    load_nodes_from_file(inFileName);
    load_gates_from_file(inFileName);
}

//Read input file and create all the nodes (putthing them in specific vectors if they are input or output nodes)
void circuit::load_nodes_from_file(string inFileName)
{
    //Variables
    string inputFileString;

    ifstream myfile (inFileName);
    if (myfile.is_open())
    {
        while(getline (myfile, inputFileString))
        {
            vector<string> words = mySplitFunction(inputFileString);    //split the line into words
            if (words[0] == "INPUT")
            {
                bool first = true;
                for (string i : words)
                {
                    if(first){first = false;}                           //skip first word in the line
                    else
                    {
                        nodes.insert(pair<string, node>(i, node(i)));   //create node
                        inputs.push_back(i);                            //add node to the input vectors
                    }
                }
            }
            else if (words[0] == "OUTPUT")
            {
                bool first = true;
                for (string i : words)
                {
                    if(first){first = false;}                           //skip first word in the line
                    else
                    {
                        nodes.insert(pair<string, node>(i, node(i)));   //create node
                        outputs.push_back(i);                           //add node to the output vectors
                    }
                }
            }
            else //gate line, we create node if they don't exist already
            {
                bool first = true;
                for (string i : words)                                      //skip first word in the line
                {
                    if(first){first = false;}
                    else
                    {
                        if(!nodes.count(i))                                 //node not created yet (no nodes named like this)
                        {
                            nodes.insert(pair<string, node>(i, node(i)));   //create node
                        }
                    }
                }
            }
        }
    myfile.close();
    }
    else cout<<"Unable to open file"<<endl;
}

//Read input file and create all the gates
void circuit::load_gates_from_file(string inFileName)
{
    //Variables
    string inputFileString;

    ifstream myfile (inFileName);
    if (myfile.is_open())
    {
        while(getline (myfile, inputFileString))
        {
            vector<string> words = mySplitFunction(inputFileString);    //split the line into words
            if (words[0] == "AND")
            {
                gates.insert(pair<string, gate*>(inputFileString, new gateAND(inputFileString)));   //create gate into the map
                gates.at(inputFileString)->output = &nodes.at(words[1]);                            //set the output of the newlmy created gate
                int skipTwice = 2;
                for (string i : words)  //add the inputs
                {
                    if (skipTwice){skipTwice--;}    //skip the gate type and the ouput
                    else
                    {
                        gates.at(inputFileString)->inputs.push_back(&nodes.at(i));  //add input node
                    }
                }
            }
            else if (words[0] == "OR")
            {
                gates.insert(pair<string, gate*>(inputFileString, new gateOR(inputFileString)));    //create node
                gates.at(inputFileString)->output = &nodes.at(words[1]);                            //set the output of the newlmy created gate
                int skipTwice = 2;
                for (string i : words)  //add the inputs
                {
                    if (skipTwice){skipTwice--;}    //skip the gate type and the ouput
                    else
                    {
                        gates.at(inputFileString)->inputs.push_back(&nodes.at(i));  //add input node
                    }
                }
            }
            else if (words[0] == "NOT")
            {
                gates.insert(pair<string, gate*>(inputFileString, new gateNOT(inputFileString)));   //create node
                gates.at(inputFileString)->output = &nodes.at(words[1]);                            //set the output of the newlmy created gate
                gates.at(inputFileString)->inputs.push_back(&nodes.at(words[2]));                   //set input (single input because not gate)
            }
        }
    myfile.close();
    }
    else cout<<"Unable to open file"<<endl;
}

//reste the nodes value (actually reste the alreadyComputed variable)
void circuit::reset()
{
    for (auto& currentNode : nodes)                     //for all the nodes
    {
        currentNode.second.alreadyComputed = false;     //change alreadyComputed to false
    }
}

//Read input file and set the values of the input nodes
void circuit::load_inputs_from_file(string inFileName)
{
    //Variables
    string inputFileString;

    ifstream myfile (inFileName);
    if (myfile.is_open())
    {
        bool skipFirst = true;
        while(getline (myfile, inputFileString))
        {
            if (skipFirst){skipFirst = false;}                          //skip first word in the line
            else
            {
                cout<<"new input will be : "<<inputFileString<<endl;
                reset();                                                        //reset all nodes
                for (int i = 0; i<inputs.size(); i++)                           //loop throught all the input node's names
                {
                    nodes.at(inputs[i]).setValue(int(inputFileString[i])-48);   //find the node in the map using it's name as key, set it's value to the input value (converted int from string)
                }
                while(!are_all_outputs_computed())                              //as long as all output not computed
                {
                    compute();                                                  //we compute
                }
                for (string outputName : outputs)                               //for all outputs
                {
                    nodes.at(outputName).showValue();                           //show output values
                }
                cout<<endl;
            }
        }
    myfile.close();
    }
    else cout<<"Unable to open file"<<endl;
}

//Run the compute function of every gate
void circuit::compute()
{
    for(pair<string, gate*> currentGate: gates) //loop througbt all the gates
    {
        currentGate.second->compute();          //execute their compute method
    }
}

//Check if all the output nodes have been computed
bool circuit::are_all_outputs_computed()
{
    bool myAns = true;
    for (string outputName : outputs)               //for all outputs
    {
        if(!nodes.at(outputName).alreadyComputed)   //if the output is not computed
        {
            myAns = false;
            break;
        }
    }
    return myAns;
}

//Call the showgate method of all gates in the circuit
void circuit::showGates()
{
    for(pair<string, gate*> currentGate: gates) //for all the gates
    {
        currentGate.second->showValue();        //call their showValue method
    }
}

//Split function from https://stackoverflow.com/questions/9435385/split-a-string-using-c11
vector<string> mySplitFunction(const string &s)
{
  stringstream ss(s);
  string item;
  vector<string> elems;
  while (getline(ss, item, ' '))
  {
    elems.push_back(item);
    // elems.push_back(std::move(item));
  }
  return elems;
}