Subversion Repositories Code-Repo

Rev

Blame | Last modification | View Log | RSS feed

#include "Circuit.h"

Circuit::Circuit()
{
    numGates = 0;
    numFFs = 0;
    numInputs = 0;
    numOutputs = 0;
    circuitLoaded = false;

    sim = new Simulator(this);
    connect(sim, SIGNAL(updateStatus(QString)), this, SIGNAL(updateStatus(QString)));
}

/**
 * Reads a circuit (lev) file into local data structure
 */
int Circuit::readGates(QString name)
{
    QFile inputFile(name);

    // Check to make sure file exists before reading
    if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        lastError = "Unable to open circuit (.lev) file!";
        return 1;
    }

    // Open file as stream and begin reading
    QTextStream fileStream(&inputFile);

    int numLines, junk;
    int gateID, gateType, gateLevel, gateInputs, gateOutputs;
    int input, output;
    QMap<int, QList<int> > tmpInputs;
    QMap<int, QList<int> > tmpOutputs;

    fileStream >> numLines;
    fileStream >> junk;
    for (int i = 0; i < numLines - 1; i++) {
        // Read the first four values and create the gate
        fileStream >> gateID;
        fileStream >> gateType;
        fileStream >> gateLevel;
        fileStream >> gateInputs;

        // Initialize an instance of the specified gate
        Gate_BASE *gate;
        switch ((gType)gateType) {
            case gate_UNKNOWN:
                break;
            case gate_INPUT:
                numGates++;
                numInputs++;
                gate = new Gate_INPUT(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_OUTPUT:
                numGates++;
                numOutputs++;
                gate = new Gate_OUTPUT(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_BUFFER:
                numGates++;
                gate = new Gate_BUFFER(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_AND:
                numGates++;
                gate = new Gate_AND(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_NAND:
                numGates++;
                gate = new Gate_NAND(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_OR:
                numGates++;
                gate = new Gate_OR(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_NOR:
                numGates++;
                gate = new Gate_NOR(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_XOR:
                numGates++;
                gate = new Gate_XOR(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_XNOR:
                numGates++;
                gate = new Gate_XNOR(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_NOT:
                numGates++;
                gate = new Gate_NOT(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
            case gate_DFF:
                numGates++;
                numFFs++;
                gate = new Gate_DFF(gateID, (gType)gateType, gateInputs, gateLevel);
                break;
        }

        // Link gate to simulator
        connect(gate, SIGNAL(enqueueSim(Gate_BASE*)), sim, SLOT(enqueueGate(Gate_BASE*)));

        // Store the gate into persistent storage
        gateIndex[gateID] = gate;

        // Seperately map gates to levels
        gatesPerLevel[gateLevel].append(gate);

        // Read and save the inputs to this gate
        for (int j = 0; j < gateInputs; j++) {
            fileStream >> input;
            tmpInputs[gateID].append(input);
        }
        // Ignore the repeated values
        for (int j = 0; j < gateInputs; j++) {
            fileStream >> junk;
        }

        // Read and save the outputs from this gate
        fileStream >> gateOutputs;
        for (int j = 0; j < gateOutputs; j++) {
            fileStream >> output;
            tmpOutputs[gateID].append(output);
        }

        // Ignore the rest of the line
        fileStream.readLine();
    }

    // Once all the gates are allocated, we can go back and properly save fanin/fanouts
    // (allows for easier reference and path tracing)
    for (int i = 1; i <= numGates; i++) {
        Gate_BASE *tmp = gateIndex[i];
        for (int j = 0; j < tmpInputs[i].size(); j++) {
            tmp->fanInGates.append(gateIndex[tmpInputs[i][j]]);
        }
        for (int j = 0; j < tmpOutputs[i].size(); j++) {
            tmp->fanOutGates.append(gateIndex[tmpOutputs[i][j]]);
        }
    }

    circuitLoaded = true;

    return 0;
}

/**
 * Reads a vector (vec) file into local data structure
 */
int Circuit::readVectors(QString name)
{
    QFile inputFile(name);

    // Check to make sure file exists before reading
    if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        lastError = "Unable to open vector (.vec) file!";
        return 1;
    }

    return 0;
}

/**
 * Reads a circuit faults (eqf) file into local data structure
 */
int Circuit::readFaults(QString name)
{
    QFile inputFile(name);

    // Check to make sure file exists before reading
    if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        lastError = "Unable to open fault (.eqf) file!";
        return 1;
    }

    return 0;
}

/**
 * Returns the last error generated from this class
 */
QString Circuit::getLastError()
{
    return lastError;
}

/**
 * Resets all gate and wire values to unknown 'X'
 */
void Circuit::reset()
{
    if (circuitLoaded) {
        QList<int> keys = gateIndex.keys();
        for (int i = 0; i < gateIndex.size(); i++) {
            gateIndex[keys[i]]->reset();
        }
    }
}

/**
 * Brings up the circuit simulator control widget
 */
void Circuit::showSimController()
{
    simController = new SimController();
    connect(simController, SIGNAL(singleStep()), sim, SLOT(singleStep()));
    connect(simController, SIGNAL(autoStep()), sim, SLOT(autoStep()));
    simController->show();
}