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();
}