· 8 years ago · Apr 10, 2018, 06:44 AM
1/*
2 * =====================================================================================
3 *
4 * Filename: atpg.cc
5 *
6 * Description: This is an ATPG (Automatic Test Pattern Generator) code that
7 * generates test vectors to test single stuck at faults for
8 * combinational circuits.
9 *
10 * The circuits are defined in a specific format. Please refer to the
11 * README file for more details on the format of the circuit.
12 *
13 * The ATPG uses an algorithm that is somewhat similar to PODEM.
14 * After it generates the vectors, it simulates the circuit for a
15 * given fault list and gives the test vectors that can test each
16 * fault from the given fault file.
17 *
18 * License: This program is free software: you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, either version 3 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 *
31 * Version: 1.0
32 * Created: 12/02/2011
33 * Revision: none
34 * Compiler: gcc
35 *
36 * =====================================================================================
37 */
38
39// ##### HEADER FILE INCLUDES ###################################################
40
41#include <iostream>
42#include <fstream>
43#include <cstdlib>
44#include <cstdio>
45#include <string>
46#include <set>
47#include <vector>
48#include <map>
49#include <algorithm>
50#include <math.h>
51
52
53#include "lib/forward_implication.cc" // Contains the forward implication functions.
54#include "lib/radix_convert.cc" // Contains functions to convert deciman number to base N.
55#include "lib/string_convert.cc"
56#include "lib/file_operations.cc" // Generic input/output file open functions.
57
58#include "class/CircuitNode.cc" // This class stores information about each node in the circuit.
59#include "class/CircuitLine.cc" // This class stores the line number and stuck at faults. Both faults for unique line.
60#include "class/FaultList.cc" // This class stores the line number and stuck at fault. Only one fault, for analysis.
61#include "class/TestList.cc" // This class contains the line number, fault and test vector with a flag to indicate if test is possible.
62
63// Global constant definitions.
64
65#ifndef GLOBAL_DEFINES_H_
66#include "include/global_defines.h"
67#endif
68
69using namespace std;
70using namespace nameSpace_ATPG;
71
72#ifdef LOG
73 ofstream logFile; // This handle is used for the log file generated with all debug messages.
74#endif
75
76/*
77 * The number of objects of the CircuitNode class depend on the number of lines in the circuit.
78 * This vector is the list of all lines in a circuit.
79 */
80vector <CircuitNode> masterNodeList;
81
82/*
83 * This map contains the objects of CircuitLine. Reason to use map was that
84 * we need only unique line numbers for the CircuitLine objects. So, the line
85 * number is used as the key of the map and object of that line as the
86 * value associated with that key.
87 */
88map <int, CircuitLine> masterLineList;
89
90/*
91 * This vector contains the list of all possible inputs to a circuit in a 3
92 * valued logic. It contains strings. Width of the string is euqal to the
93 * number of inputs to the circuit. It will later be split into integers
94 * while applying to the circuit.
95 */
96vector <string> masterInputVector;
97vector <string> masterTestVector;
98
99/*
100 * This vector contains all the line numbers with faults and the possible
101 * fault values at those lines.
102 *
103 * When running ATPG, we have to obtain a vector to test every fault in this
104 * vector.
105 */
106vector <FaultList> masterFaultList;
107vector <FaultList> finalFaultList;
108vector <FaultList> providedFaultList;
109/*
110 * This vector contains all the possible faults in the circuit and the test
111 * vector associated with them.
112 */
113vector <TestList> masterTestList;
114vector <TestList> finalTestList;
115
116/*
117 * === FUNCTION ======================================================================
118 * Name: ReadCircuit
119 * Description: This function, once it can successfully open the circuit file, will
120 * then populate the structure/class with the proper values from the file.
121 * =====================================================================================
122 */
123void ReadCircuit (ifstream &inFile) {
124
125 #ifdef DEBUG
126 WRITE << "================================================================================" << endl;
127 WRITE << "=============== In --> ReadCircuit ===============" << endl;
128 WRITE << "================================================================================" << endl << endl;
129 #endif
130
131 unsigned int nodeType;
132 unsigned int fanInListMember;
133
134 while (true) {
135 inFile >> nodeType; // This is the type of current node.
136 if (inFile.eof())
137 break;
138 CircuitNode *thisNode;
139 thisNode = new CircuitNode (nodeType); // Constructor checks for inputs and outputs.
140
141 switch (nodeType) {
142 case PI: // Check if the current node is a primary input.
143 inFile >> thisNode->lineNumber; // Unique ID for the line.
144 inFile >> thisNode->gateType; // This will be always 0 for primary inputs.
145 inFile >> thisNode->numberFanOut; // Number of lines connected to this input.
146 inFile >> thisNode->numberFanIn; // This will always be 0 for primary inputs.
147 break;
148
149 case FB:
150 inFile >> thisNode->lineNumber; // Unique ID for the line.
151 inFile >> thisNode->gateType; // This will be always 1 for branches.
152 thisNode->numberFanIn = 1; // Branch always has only one input.
153 thisNode->numberFanOut = 100; // Branch can have multiple outputs but only one per line.
154 //TODO: Figure this out - 100 is incorrect. Needs to be proper value.
155 inFile >> fanInListMember; // This is the fan out for branch.
156 thisNode->listFanIn.insert(fanInListMember);
157 break;
158
159 case GT:
160 inFile >> thisNode->lineNumber; // Unique ID for the line.
161 inFile >> thisNode->gateType; // Gate type.
162 inFile >> thisNode->numberFanOut; // Number of lines connected to this node.
163 inFile >> thisNode->numberFanIn; // Number of lines connected at this node.
164 for (int i = 0; i < thisNode->numberFanIn; i++) {
165 inFile >> fanInListMember;
166 thisNode->listFanIn.insert(fanInListMember);
167 }
168 break;
169
170 case PO:
171 inFile >> thisNode->lineNumber; // Unique ID for the line.
172 inFile >> thisNode->gateType; // Type of the gate output is connected to.
173 inFile >> thisNode->numberFanOut; // Always zero for outputs.
174 inFile >> thisNode->numberFanIn; // Number of lines connected at this node.
175 for (int i = 0; i < thisNode->numberFanIn; i++) {
176 inFile >> fanInListMember;
177 thisNode->listFanIn.insert(fanInListMember);
178 }
179 break;
180
181 default: // Undefined node type.
182 cerr << "ERROR: Undefined Node Type." << endl
183 << "Valid values are 0, 1, 2 and 3." << endl
184 << "Current value is " << nodeType << endl;
185 exit (1);
186 break; // No necessary since exit (1) will end program.
187 }
188
189 masterNodeList.push_back(*thisNode);
190 delete thisNode;
191 }
192
193 set <int>::iterator it, ij;
194 for (int i = 0; i < masterNodeList.size(); i++) {
195 for(it = masterNodeList[i].listFanIn.begin(); it != masterNodeList[i].listFanIn.end(); it++) {
196 for (int j = 0; j < masterNodeList.size(); j++) {
197 if (masterNodeList[j].lineNumber == *it)
198 masterNodeList[j].listFanOut.insert(masterNodeList[i].lineNumber);
199 }
200 }
201 }
202
203 #ifdef DEBUG
204 set <int>::iterator itr;
205 for (int i = 0; i < masterNodeList.size(); i++) {
206 WRITE << "------------------------------------------------------------" << endl;
207 WRITE << "\tProperties Associated With Each Node" << endl;
208 WRITE << "------------------------------------------------------------" << endl;
209 WRITE << "nodeIndex = " << masterNodeList[i].nodeIndex << endl;
210 WRITE << "nodeType = " << masterNodeList[i].nodeType << endl;
211 WRITE << "lineNumber = " << masterNodeList[i].lineNumber << endl;
212 WRITE << "gateType = " << masterNodeList[i].gateType << endl;
213 WRITE << "numberFanOut = " << masterNodeList[i].numberFanOut << endl;
214 WRITE << "numberFanIn = " << masterNodeList[i].numberFanIn << endl;
215 WRITE << "listFanIn = ";
216 for(itr = masterNodeList[i].listFanIn.begin(); itr != masterNodeList[i].listFanIn.end(); itr++) {
217 WRITE << " " << *itr << ", ";
218 }
219 WRITE << endl;
220 WRITE << "listFanOut = ";
221 for(itr = masterNodeList[i].listFanOut.begin(); itr != masterNodeList[i].listFanOut.end(); itr++) {
222 WRITE << " " << *itr << ", ";
223 }
224 WRITE << endl << "------------------------------------------------------------" << endl;
225 WRITE << endl << endl << endl;
226 }
227 #endif
228}
229
230/*
231 * === FUNCTION ======================================================================
232 * Name: ReadFaultList
233 * Description: Fault list file has the format <lineNumber> <faultType> on each line.
234 * This function just parses that file and sets the proper variables
235 * in FaultList object list if fault exists.
236 * =====================================================================================
237 */
238void ReadFaultList (ifstream &inFile) {
239
240 #ifdef DEBUG
241 WRITE << "================================================================================" << endl;
242 WRITE << "=============== In --> ReadFaultList ===============" << endl;
243 WRITE << "================================================================================" << endl << endl;
244 #endif
245
246 int outLineNumber;
247 int outFaultValue;
248 bool invalidLine;
249
250 while (true) {
251 inFile >> outLineNumber;
252 if (inFile.eof())
253 break;
254 inFile >> outFaultValue;
255 invalidLine = true;
256 for (int i = 0; i < masterNodeList.size(); i++) {
257 if (masterNodeList[i].lineNumber == outLineNumber) {
258 FaultList *thisFault;
259 thisFault = new FaultList (outLineNumber, outFaultValue);
260 providedFaultList.push_back (*thisFault);
261 delete thisFault;
262 invalidLine = false;
263 }
264 // If the line number cannot be found in the circuit then print
265 // a message that it is invalid.
266 //
267 // Continue to the next fault in the file.
268 // This is not an error. The ATPG will simply ignore that invalid line.
269 else {
270 if (i == (masterNodeList.size() - 1) && invalidLine) {
271 cout << "------------------------------------------------------------" << endl;
272 cout << "INFO: Invalid line number in the provided fault list." << endl;
273 cout << "The line number " << outLineNumber << " does not exist in this circuit." << endl;
274 cout << "------------------------------------------------------------" << endl << endl;
275 }
276 }
277 }
278 }
279
280 for (int i = 0; i < providedFaultList.size(); i++) {
281 #ifdef DEBUG
282 WRITE << "------------------------------------------------------------" << endl;
283 WRITE << "\tSetting Fault Values" << endl;
284 WRITE << "------------------------------------------------------------" << endl;
285 WRITE << "For circuit line " << providedFaultList[i].lineNumber << endl;
286 WRITE << "Fault is Stuck At " << providedFaultList[i].stuckAtValue << endl;
287 WRITE << "------------------------------------------------------------" << endl;
288 WRITE << endl << endl;
289 #endif
290 }
291}
292
293/*
294 * ============================================================================
295 * Functions to Perform Logical Operations on the Circuit.
296 * ============================================================================
297 */
298
299/*
300 * === FUNCTION ======================================================================
301 * Name: SetLineLevel
302 * Description: This function divides the circuit in logical levels.
303 * There is no feedback in a combinational circuit so we can go from
304 * level 0 to level MAX and find the proper input to output paths.
305 * =====================================================================================
306 */
307void SetLineLevel (vector <CircuitNode> &masterNodeList) {
308
309 #ifdef DEBUG
310 WRITE << "================================================================================" << endl;
311 WRITE << "=============== In --> SetLineLevel ===============" << endl;
312 WRITE << "================================================================================" << endl << endl;
313 #endif
314
315 for (int i = 0; i < masterNodeList.size(); i++) {
316 if (masterNodeList[i].numberFanIn == 0)
317 masterNodeList[i].lineLevel = 0; // Level of primary inputs is 0.
318 else
319 masterNodeList[i].lineLevel = -1; // Level of all other nodes is -1, placeholder.
320 }
321
322 set <int>::iterator it;
323
324 /*
325 * For all nodes.
326 * -- For all nodes after the current node.
327 * -- If the input list of next node contains current node.
328 * -- Check the level of that next node.
329 * -- If it is less than the level of current node, update it.
330 */
331 for (int i = 0; i < masterNodeList.size(); i++) {
332 for (int j = (i + 1); j < masterNodeList.size(); j++) {
333 for (it = masterNodeList[j].listFanIn.begin(); it != masterNodeList[j].listFanIn.end(); it++) {
334 for (int k = 0; k < masterNodeList.size(); k++) {
335 if (masterNodeList[k].lineNumber == *it) {
336 if (masterNodeList[k].lineNumber == masterNodeList[i].lineNumber) {
337 if (masterNodeList[j].lineLevel < (masterNodeList[i].lineLevel + 1)) {
338 masterNodeList[j].lineLevel = (masterNodeList[i].lineLevel + 1);
339 }
340 }
341 }
342 }
343 }
344 }
345
346 #ifdef DEBUG
347 WRITE << "Line Number = " << masterNodeList[i].lineNumber << ". Level = " << masterNodeList[i].lineLevel << "." << endl;
348 #endif
349 }
350 #ifdef DEBUG
351 WRITE << "--------------------------------------------------------------------------------" << endl << endl;
352 #endif
353
354}
355
356/*
357 * === FUNCTION ======================================================================
358 * Name: CreateFaultObjects
359 * Description: This function generates one object of the CircuitLine class for every
360 * unique line in the circuit. So, after going through this function, we
361 * have a list of objects for each line in the circuit. Every line may
362 * have a stuck at 0 or a stuck at 1 fault so values are set to true for
363 * both.
364 *
365 * A map is used here with the line number as the key. Duplicate elements
366 * would be removed automatically by the map.
367 * =====================================================================================
368 */
369void CreateFaultObjects (map <int, CircuitLine> &masterLineList, vector <CircuitNode> &masterNodeList) {
370
371 #ifdef DEBUG
372 WRITE << "================================================================================" << endl;
373 WRITE << "=============== In --> CreateFaultObjects ===============" << endl;
374 WRITE << "================================================================================" << endl << endl;
375 #endif
376
377 set <int>::iterator itr;
378
379 for (int i = 0; i < masterNodeList.size(); i++) {
380
381 // Create an object for every node.
382 CircuitLine *thisLine;
383 thisLine = new CircuitLine(masterNodeList[i].lineNumber);
384 masterLineList.insert(pair<int, CircuitLine>(masterNodeList[i].lineNumber, *thisLine));
385 delete thisLine;
386
387 // Create an object for every fan in of the node.
388 for (itr = masterNodeList[i].listFanIn.begin(); itr != masterNodeList[i].listFanIn.end(); itr++) {
389 CircuitLine *thisLine;
390 thisLine = new CircuitLine(*itr);
391 masterLineList.insert(pair<int, CircuitLine>(*itr, *thisLine));
392 delete thisLine;
393 }
394
395 // Create an object for every fan out of the node.
396 for (itr = masterNodeList[i].listFanOut.begin(); itr != masterNodeList[i].listFanOut.end(); itr++) {
397 CircuitLine *thisLine;
398 thisLine = new CircuitLine(*itr);
399 masterLineList.insert(pair<int, CircuitLine>(*itr, *thisLine));
400 delete thisLine;
401 }
402
403 }
404
405 #ifdef DEBUG
406 for (map<int, CircuitLine>::iterator itr = masterLineList.begin(); itr != masterLineList.end(); itr++) {
407 WRITE << "------------------------------------------------------------" << endl;
408 WRITE << "\tThe map contains following values" << endl;
409 WRITE << "------------------------------------------------------------" << endl;
410 WRITE << "The key is " << (*itr).first << endl;
411 WRITE << "The Element is " << (*itr).second.lineNumber << endl;
412 WRITE << "The StuckAt_0 fault is " << (*itr).second.isStuckAt_0 << endl;
413 WRITE << "The StuckAt_1 fault is " << (*itr).second.isStuckAt_1 << endl;
414 WRITE << "------------------------------------------------------------" << endl;
415 WRITE << endl << endl;
416 }
417 #endif
418}
419
420/*
421 * === FUNCTION ======================================================================
422 * Name: CollapseFaults
423 * Description: This function takes the list of lines in the circuit and then
424 * collapses the faults going from output to input.
425 *
426 * Fault collapse for XOR, XNOR and Branches is not yet implemented.
427 * =====================================================================================
428 */
429void CollapseFaults (map <int, CircuitLine> &masterLineList, vector <CircuitNode> &masterNodeList) {
430
431 #ifdef DEBUG
432 WRITE << "================================================================================" << endl;
433 WRITE << "=============== In --> CollapseFaults ===============" << endl;
434 WRITE << "================================================================================" << endl << endl;
435 #endif
436
437 map <int, CircuitLine>::iterator itrMap;
438 set <int>::iterator itrSet;
439 itrMap = masterLineList.end();
440 itrMap--;
441
442 int lastOutputLineNumber = (*itrMap).second.lineNumber; // Line number of the last output.
443 int lastOutputLineLevel = masterNodeList.back().lineLevel; // Level of the last output.
444
445 #ifdef DEBUG
446 WRITE << "Line number of last output = " << lastOutputLineNumber << endl;
447 WRITE << "Level of last output = " << lastOutputLineLevel << endl;
448 #endif
449
450 // From the highest level (last output) to zero.
451 // -- For all the nodes.
452 // -- If the current node has the highest level.
453 // -- Collapse faults.
454 // -- Reduce highest level by 1.
455 // -- Next iteration of the loop.
456 //
457 // In the collapse faults procedure, the fault can collapse
458 // to any one of the 2/3 inputs.
459 // In this code, the fault always collapses to the input with
460 // the smallest line number.
461 //
462 // Generic structure of the fault collapse is -
463 // -- Remove both faults from output.
464 // -- Reduce one of them to single fault at one of the inputs.
465 // -- Second fault stays on all inputs.
466 //
467 // XOR, XNOR and Branches are not considered here.
468 for (int i = lastOutputLineLevel; i > 0; i--) {
469 for (int j = 0; j < masterNodeList.size(); j++) {
470 if (masterNodeList[j].lineLevel == i) {
471 switch (masterNodeList[j].gateType) {
472 case G_PI:
473 break;
474 case G_BRNCH:
475 break;
476 case G_XOR:
477 break;
478 case G_OR:
479 case G_NOR:
480 for (itrSet = masterNodeList[j].listFanOut.begin(); itrSet != masterNodeList[j].listFanOut.end(); itrSet++) {
481 masterLineList.at(*itrSet).isStuckAt_0 = false;
482 masterLineList.at(*itrSet).isStuckAt_1 = false;
483 }
484 for (itrSet = masterNodeList[j].listFanIn.begin(); itrSet != masterNodeList[j].listFanIn.end(); itrSet++) {
485 if (itrSet != masterNodeList[j].listFanIn.begin())
486 masterLineList.at(*itrSet).isStuckAt_1 = false;
487
488 }
489 break;
490 case G_NOT:
491 for (itrSet = masterNodeList[j].listFanOut.begin(); itrSet != masterNodeList[j].listFanOut.end(); itrSet++) {
492 masterLineList.at(*itrSet).isStuckAt_0 = false;
493 masterLineList.at(*itrSet).isStuckAt_1 = false;
494 }
495 break;
496 case G_NAND:
497 case G_AND:
498 for (itrSet = masterNodeList[j].listFanOut.begin(); itrSet != masterNodeList[j].listFanOut.end(); itrSet++) {
499 masterLineList.at(*itrSet).isStuckAt_0 = false;
500 masterLineList.at(*itrSet).isStuckAt_1 = false;
501 }
502 for (itrSet = masterNodeList[j].listFanIn.begin(); itrSet != masterNodeList[j].listFanIn.end(); itrSet++) {
503 if (itrSet != masterNodeList[j].listFanIn.begin())
504 masterLineList.at(*itrSet).isStuckAt_0 = false;
505
506 }
507 break;
508 default:
509 cerr << "Unknown gate type encountered. The possible gate type values are from 0-7." << endl;
510 cerr << "Current gate type is " << masterNodeList[j].gateType << endl;
511 exit (0);
512 break;
513 }
514 }
515 }
516 }
517
518 #ifdef DEBUG
519 for (map<int, CircuitLine>::iterator itr = masterLineList.begin(); itr != masterLineList.end(); itr++) {
520 WRITE << "------------------------------------------------------------" << endl;
521 WRITE << "\tAfter Fault Collapse, the Map contains" << endl;
522 WRITE << "------------------------------------------------------------" << endl;
523 WRITE << "The key is " << (*itr).first << endl;
524 WRITE << "The Element is " << (*itr).second.lineNumber << endl;
525 WRITE << "The StuckAt_0 fault is " << (*itr).second.isStuckAt_0 << endl;
526 WRITE << "The StuckAt_1 fault is " << (*itr).second.isStuckAt_1 << endl;
527 WRITE << "------------------------------------------------------------" << endl;
528 WRITE << endl << endl;
529 }
530 #endif
531}
532
533/*
534 * === FUNCTION ======================================================================
535 * Name: CreateFaultList
536 * Description: Once the faults have been collapsed, this function generates a list
537 * of all possible faults and the line numbers associated with them. When
538 * running ATPG, we have to obtain a test for every fault in this list.
539 * =====================================================================================
540 */
541void CreateFaultList (vector <FaultList> &inFaultList) {
542
543 #ifdef DEBUG
544 WRITE << "================================================================================" << endl;
545 WRITE << "=============== In --> CreateFaultList ===============" << endl;
546 WRITE << "================================================================================" << endl << endl;
547 #endif
548
549 for (map<int, CircuitLine>::iterator itr = masterLineList.begin(); itr != masterLineList.end(); itr++) {
550 if ((*itr).second.isStuckAt_0) {
551 FaultList *thisFault;
552 thisFault = new FaultList ((*itr).first, false);
553 inFaultList.push_back(*thisFault);
554 delete thisFault;
555 }
556 if ((*itr).second.isStuckAt_1) {
557 FaultList *thisFault;
558 thisFault = new FaultList ((*itr).first, true);
559 inFaultList.push_back(*thisFault);
560 delete thisFault;
561 }
562 }
563
564 #ifdef DEBUG
565 WRITE << endl;
566 WRITE << "Master Fault List Contains" << endl;
567 WRITE << "------------------------------------------------------------" << endl;
568 for (int i = 0; i < inFaultList.size(); i++) {
569 WRITE << "Line Number = " << inFaultList[i].lineNumber << endl;
570 WRITE << "Fault Value = " << inFaultList[i].stuckAtValue << endl;
571 WRITE << endl;
572 }
573 WRITE << endl;
574 #endif
575}
576
577/*
578 * === FUNCTION ======================================================================
579 * Name: SimpleLogicSimulation
580 * Description: Simple logic simulation. The number of inputs are provided to it.
581 * It generates a random input vector, simulates the circuit and then
582 * generates the output value.
583 * =====================================================================================
584 */
585void SimpleLogicSimulation (int totalInputs, string inVector) {
586
587 #ifdef DEBUG
588 WRITE << "================================================================================" << endl;
589 WRITE << "=============== In --> SimpleLogicSimulation ===============" << endl;
590 WRITE << "================================================================================" << endl << endl;
591 #endif
592
593 int *inputVector;
594 inputVector = new int [totalInputs];
595 set <int> *gateVector;
596 gateVector = new set <int> [3];
597 set <int>::iterator itrSet;
598
599 // Convert the input vector string to integer
600 // values to be applied to the circuit for simulation.
601 // (- 48) is done to convert ascii to integer.
602 for (int i = 0; i < totalInputs; i++) {
603 inputVector[i] = inVector[i] - 48;
604 }
605
606 // Clear all the sets. This is important since we don't want
607 // the previous values affecting current simulation.
608 for (int i = 0, j = 0; i < masterNodeList.size(); i++) {
609 masterNodeList[i].lineValue.clear();
610 }
611
612 // Assign the vector to inputs and keep all other values empty.
613 for (int i = 0, j = 0; i < masterNodeList.size(); i++) {
614 if (masterNodeList[i].numberFanIn == 0)
615 masterNodeList[i].lineValue.insert(inputVector[j++]);
616 }
617
618
619 // Calls implication on all the nodes going from input to output.
620 // Implication would result in a set of single value at the output.
621 // If there is a fault (will be considered in FaultSimulation) then
622 // the output set will have multiple values and/or D and/or B (Dbar).
623 for (int i = 0; i < masterNodeList.size(); i++) { // For all nodes.
624 if (masterNodeList[i].numberFanIn != 0) { // Not a primary input.
625 int inputNumber = 0;
626
627 // If not a primary input then generate the input set to be given to implication function.
628 for (itrSet = masterNodeList[i].listFanIn.begin(); itrSet != masterNodeList[i].listFanIn.end(); itrSet++) {
629 for (int j = 0; j < masterNodeList.size(); j++) {
630 if (masterNodeList[j].lineNumber == *itrSet) {
631 gateVector[inputNumber++] = masterNodeList[j].lineValue;
632 }
633 }
634 }
635
636 // Call proper implication function depending on the number of the inputs to the gate.
637 // Overloaded function, please refer to logic_implication.cc for details.
638 switch (masterNodeList[i].numberFanIn) {
639 case 1:
640 masterNodeList[i].lineValue = forwardImplication (masterNodeList[i].gateType, gateVector[0]);
641 break;
642 case 2:
643 masterNodeList[i].lineValue = forwardImplication (masterNodeList[i].gateType, gateVector[0], gateVector[1]);
644 break;
645 case 3:
646 masterNodeList[i].lineValue = forwardImplication (masterNodeList[i].gateType, gateVector[0], gateVector[1], gateVector[2]);
647 break;
648 default:
649 cerr << "This ATPG generator only works if the number of inputs to a gate is less than 4." << endl;
650 cerr << "Currently there are " << masterNodeList[i].numberFanIn << " inputs to the gate." << endl;
651 exit (0);
652 break;
653 }
654 }
655 }
656
657 #ifdef DEBUG
658 WRITE << "There are " << CircuitNode::totalInputs << " inputs to this circuit." << endl << endl;
659
660 for (int i = 0; i < totalInputs; i++) {
661 WRITE << "Input Vector [" << i << "] is = " << inputVector[i] << endl;
662 }
663 WRITE << endl;
664
665 for (int i = 0; i < masterNodeList.size(); i++) {
666 if (masterNodeList[i].numberFanIn == 0) {
667 WRITE << "The value of the input at line number " << masterNodeList[i].lineNumber << " is = ";
668 for (itrSet = masterNodeList[i].lineValue.begin(); itrSet != masterNodeList[i].lineValue.end(); itrSet++) {
669 WRITE << *itrSet << " ";
670 }
671 WRITE << endl;
672 }
673 }
674 WRITE << endl;
675
676 for (int i = 0; i < masterNodeList.size(); i++) {
677 if (masterNodeList[i].numberFanIn != 0) {
678 WRITE << "The value of the line number " << masterNodeList[i].lineNumber << " is = ";
679 for (itrSet = masterNodeList[i].lineValue.begin(); itrSet != masterNodeList[i].lineValue.end(); itrSet++) {
680 WRITE << *itrSet << " ";
681 }
682 WRITE << endl;
683 }
684 }
685 WRITE << endl;
686
687 for (int i = 0; i < masterNodeList.size(); i++) {
688 if (masterNodeList[i].numberFanOut == 0) {
689 WRITE << "The value of the output at line number " << masterNodeList[i].lineNumber << " is = ";
690 for (itrSet = masterNodeList[i].lineValue.begin(); itrSet != masterNodeList[i].lineValue.end(); itrSet++) {
691 WRITE << *itrSet << " ";
692 }
693 WRITE << endl;
694 }
695 }
696
697 WRITE << endl;
698 #endif
699}
700
701/*
702 * === FUNCTION ======================================================================
703 * Name: GenerateMasterInputVectors
704 * Description: This function takes in the number of inputs and then generates an
705 * exhaustive list of vectors to test the circuit with. Starting with
706 * all 'X's and finishing with all known inputs.
707 *
708 * These vectors are later tested with the circuit to check if a fault
709 * can be detected.
710 * =====================================================================================
711 */
712void GenerateMasterInputVectors (int totalInputs) {
713
714 #ifdef DEBUG
715 WRITE << "================================================================================" << endl;
716 WRITE << "=============== In --> GenerateMasterInputVectors ===============" << endl;
717 WRITE << "================================================================================" << endl << endl;
718 #endif
719
720 string resultVector; // Input vector.
721 vector <string> *tempInputVector; // We have to sort vectors by number of X in them.
722 tempInputVector = new vector <string> [totalInputs];
723 vector <string>::iterator itrVector;
724
725 for (int i = 0; i < (pow(3, totalInputs) - 1); i++) { // Go on converting numbers in base 3 system.
726 resultVector = RadixConvert (i, 3);
727 int numberOfX = 0; // Total X in the vector.
728 int positionOfX = resultVector.find_first_of('2'); // Iterate over the vector.
729 while (positionOfX!=string::npos)
730 {
731 numberOfX++; // Count number of 'X's
732 resultVector[positionOfX] = '4'; // Replace 2 by 4 since we are using #define X 4.
733 positionOfX = resultVector.find_first_of('2',(positionOfX + 1));
734 }
735
736 tempInputVector[numberOfX].push_back(resultVector);
737 }
738
739 // Now we have to put all the vectors in a large table.
740 // There are no leading zeros in the string. We need them
741 // in our simulation so padding is also done.
742 for (int i = 0; i < totalInputs; i++) {
743 for (itrVector = tempInputVector[i].begin(); itrVector != tempInputVector[i].end(); itrVector++) {
744 resultVector = *itrVector;
745 int vectorLength = resultVector.length();
746 for (int j = 0; j < (totalInputs - vectorLength); j++)
747 resultVector = "0" + resultVector;
748 masterInputVector.push_back (resultVector);
749 }
750 }
751
752 // We start from the case with most 'X's and go to the case with minimum 'X's.
753 // For this we have to reverse the vector.
754 reverse (masterInputVector.begin(), masterInputVector.end());
755
756 #ifdef DEBUG
757 WRITE << "Total Inputs = " << totalInputs << endl;
758 WRITE << "------------------------------------------------------------" << endl << endl;
759 WRITE << "Vector Table for this circuit." << endl;
760 WRITE << "------------------------------------------------------------" << endl << endl;
761 for (itrVector = masterInputVector.begin(); itrVector != masterInputVector.end(); itrVector++) {
762 WRITE << *itrVector << endl;
763 }
764 WRITE << "------------------------------------------------------------" << endl << endl;
765 #endif
766}
767
768/*
769 * === FUNCTION ======================================================================
770 * Name: CheckVectorForATPG
771 * Description: This function takes in the line number and the fault present at that
772 * line. It also takes in an input vector to be checked.
773 *
774 * It then checks first if the fault can be excited. If the fault can be
775 * excited then it checks whether the fault can be propagated to any one
776 * of the outputs. If both of them result in true then the fault can be
777 * tested with the vector.
778 * =====================================================================================
779 */
780bool CheckVectorForATPG (int totalInputs, int inLineNumber, bool inStuckAtValue, string inVector) {
781
782 int *inputVector;
783 inputVector = new int [totalInputs];
784 set <int> *gateVector;
785 gateVector = new set <int> [3];
786 set <int>::iterator itrSet;
787
788 // Convert the input vector string to integer
789 // values to be applied to the circuit for simulation.
790 // (- 48) is done to convert ascii to integer.
791 for (int i = 0; i < totalInputs; i++) {
792 inputVector[i] = inVector[i] - 48;
793 }
794
795 // Clear all the sets. This is important since we don't want
796 // the previous values affecting current simulation.
797 for (int i = 0; i < masterNodeList.size(); i++) {
798 masterNodeList[i].lineValue.clear();
799 }
800
801 // Assign the vector to inputs and keep all other values empty.
802 for (int i = 0, j = 0; i < masterNodeList.size(); i++) {
803 if (masterNodeList[i].numberFanIn == 0)
804 masterNodeList[i].lineValue.insert(inputVector[j++]);
805 }
806
807 bool isFaultExcited = false; // Check if the fault can be excited.
808 bool isTestGenerated = false; // Check if the test is generated.
809
810 // For all the nodes in the circuit.
811 // -- For all the primary inputs.
812 // -- If the current line == the line where fault exists.
813 // -- If the fault can be excited.
814 // -- Set the value to D or Dbar.
815 for (int i = 0; i < masterNodeList.size(); i++) {
816 if (masterNodeList[i].numberFanIn == 0) {
817 if (inLineNumber == masterNodeList[i].lineNumber) {
818 for (itrSet = masterNodeList[i].lineValue.begin(); itrSet != masterNodeList[i].lineValue.end(); itrSet++) {
819 if (*itrSet == 0 && inStuckAtValue == true) {
820 isFaultExcited = true;
821 masterNodeList[i].lineValue.clear();
822 masterNodeList[i].lineValue.insert(3);
823 break;
824 }
825 if (*itrSet == 1 && inStuckAtValue == false) {
826 isFaultExcited = true;
827 masterNodeList[i].lineValue.clear();
828 masterNodeList[i].lineValue.insert(2);
829 break;
830 }
831 }
832 }
833 }
834 }
835
836 set <int> tempSet; // To store the result of implication.
837
838 // Calls implication on all the nodes going from input to output.
839 // Implication would result in a set of single value at the output.
840 // If there is a fault (will be considered in FaultSimulation) then
841 // the output set will have multiple values and/or D and/or B (Dbar).
842 for (int i = 0; i < masterNodeList.size(); i++) { // For all nodes.
843 if (masterNodeList[i].numberFanIn != 0) { // Not a primary input.
844 int inputNumber = 0;
845
846 // If not a primary input then generate the input set to be given to implication function.
847 for (itrSet = masterNodeList[i].listFanIn.begin(); itrSet != masterNodeList[i].listFanIn.end(); itrSet++) {
848 for (int j = 0; j < masterNodeList.size(); j++) {
849 if (masterNodeList[j].lineNumber == *itrSet) {
850 gateVector[inputNumber++] = masterNodeList[j].lineValue;
851 }
852 }
853 }
854
855 // Call proper implication function depending on the number of the inputs to the gate.
856 // Overloaded function, please refer to logic_implication.cc for details.
857 switch (masterNodeList[i].numberFanIn) {
858 case 1:
859 tempSet = forwardImplication (masterNodeList[i].gateType, gateVector[0]);
860 break;
861 case 2:
862 tempSet = forwardImplication (masterNodeList[i].gateType, gateVector[0], gateVector[1]);
863 break;
864 case 3:
865 tempSet = forwardImplication (masterNodeList[i].gateType, gateVector[0], gateVector[1], gateVector[2]);
866 break;
867 default:
868 cerr << "This ATPG generator only works if the number of inputs to a gate is less than 4." << endl;
869 cerr << "Currently there are " << masterNodeList[i].numberFanIn << " inputs to the gate." << endl;
870 exit (0);
871 break;
872 }
873 // If the current line number is the same as the line number with the fault.
874 // -- If the fault can be excited.
875 // -- Set proper value D or Dbar.
876 if (inLineNumber == masterNodeList[i].lineNumber) {
877 for (itrSet = tempSet.begin(); itrSet != tempSet.end(); itrSet++) {
878 if (*itrSet == 0 && inStuckAtValue == true) {
879 isFaultExcited = true;
880 tempSet.clear();
881 tempSet.insert(3);
882 break;
883 }
884 if (*itrSet == 1 && inStuckAtValue == false) {
885 isFaultExcited = true;
886 tempSet.clear();
887 tempSet.insert(2);
888 break;
889 }
890 }
891 // If fault cannot be excited, exit.
892 if (isFaultExcited == false) {
893 return false;
894 }
895 }
896 // If fault can be excited, assign the value D or Dbar to the line.
897 masterNodeList[i].lineValue = tempSet;
898 }
899 }
900
901 // Once the simulation is done, check all the outputs.
902 // -- If any output has either a D or a Dbar then the fault is detected.
903 // -- The vector can test the fault.
904 for (int i = 0; i < masterNodeList.size(); i++) {
905 if (masterNodeList[i].numberFanOut == 0) {
906 for (itrSet = masterNodeList[i].lineValue.begin(); itrSet != masterNodeList[i].lineValue.end(); itrSet++) {
907 if (*itrSet == 2 || *itrSet == 3) {
908 isTestGenerated = true;
909 }
910 }
911 }
912 }
913
914 #ifdef DEBUG
915 if (isTestGenerated) {
916 WRITE << "================================================================================" << endl;
917 WRITE << "=============== In --> CheckVectorForATPG ===============" << endl;
918 WRITE << "================================================================================" << endl << endl;
919 WRITE << "There are " << CircuitNode::totalInputs << " inputs to this circuit." << endl << endl;
920
921 for (int i = 0; i < totalInputs; i++) {
922 WRITE << "Input Vector [" << i << "] is = " << inputVector[i] << endl;
923 }
924 WRITE << endl;
925
926 for (int i = 0; i < masterNodeList.size(); i++) {
927 if (masterNodeList[i].numberFanIn == 0) {
928 WRITE << "The value of the input at line number " << masterNodeList[i].lineNumber << " is = ";
929 for (itrSet = masterNodeList[i].lineValue.begin(); itrSet != masterNodeList[i].lineValue.end(); itrSet++) {
930 WRITE << *itrSet << " ";
931 }
932 WRITE << endl;
933 }
934 }
935 WRITE << endl;
936
937 for (int i = 0; i < masterNodeList.size(); i++) {
938 if (masterNodeList[i].numberFanIn != 0) {
939 WRITE << "The value of the line number " << masterNodeList[i].lineNumber << " is = ";
940 for (itrSet = masterNodeList[i].lineValue.begin(); itrSet != masterNodeList[i].lineValue.end(); itrSet++) {
941 WRITE << *itrSet << " ";
942 }
943 WRITE << endl;
944 }
945 }
946 WRITE << endl;
947
948 for (int i = 0; i < masterNodeList.size(); i++) {
949 if (masterNodeList[i].numberFanOut == 0) {
950 WRITE << "The value of the output at line number " << masterNodeList[i].lineNumber << " is = ";
951 for (itrSet = masterNodeList[i].lineValue.begin(); itrSet != masterNodeList[i].lineValue.end(); itrSet++) {
952 WRITE << *itrSet << " ";
953 }
954 WRITE << endl;
955 }
956 }
957
958 WRITE << endl;
959 }
960 #endif
961
962 if (isTestGenerated)
963 return true;
964 else
965 return false;
966}
967
968/*
969 * === FUNCTION ======================================================================
970 * Name: TestAllVectorsATPG
971 * Description: This function reads from the vector table.
972 * It then applies each vector to CheckVectorForATPG.
973 * If a test is generated then it returns true.
974 * If no test is generated after looking at all vectors, return false.
975 * =====================================================================================
976 */
977bool TestAllVectorsATPG (int totalInputs, int inLineNumber, bool inStuckAtValue, vector <string> &inVectorList, vector <TestList> &inTestList) {
978
979 #ifdef DEBUG
980 WRITE << "================================================================================" << endl;
981 WRITE << "=============== In --> TestAllVectorsForATPG ===============" << endl;
982 WRITE << "================================================================================" << endl << endl;
983 #endif
984
985 string outVector;
986
987 for (int i = 0; i < inVectorList.size(); i++) {
988 outVector = inVectorList[i];
989 if (CheckVectorForATPG(totalInputs, inLineNumber, inStuckAtValue, outVector)) {
990 TestList *thisTest;
991 thisTest = new TestList(inLineNumber, inStuckAtValue, outVector);
992 inTestList.push_back(*thisTest);
993 delete thisTest;
994
995 #ifdef DEBUG
996 WRITE << endl;
997 WRITE << "------------------------------------------------------------" << endl;
998 WRITE << "The fault is at line number = " << inLineNumber << endl;
999 WRITE << "The fault is stuck at = " << inStuckAtValue << endl;
1000 WRITE << "Test was generated by vector = " << outVector << endl;
1001 WRITE << "------------------------------------------------------------" << endl;
1002 WRITE << endl;
1003 #endif
1004 return true;
1005 }
1006 }
1007
1008 return false;
1009}
1010
1011/*
1012 * === FUNCTION ======================================================================
1013 * Name: CheckAllFaultsATPG
1014 * Description: This function keeps checking if a test vector is possible for all the
1015 * faults left in the circuit after fault collapsing. If a test is
1016 * possible then it moves to next fault. If no test is found then
1017 * the test possible flag in the TestList object is set to false and the
1018 * next fault is checked.
1019 * =====================================================================================
1020 */
1021void CheckAllFaultsATPG (int totalInputs, vector <string> &inVectorList, vector <TestList> &inTestList, vector <FaultList> &inFaultList) {
1022
1023 #ifdef DEBUG
1024 WRITE << "================================================================================" << endl;
1025 WRITE << "=============== In --> CheckAllFaultsATPG ===============" << endl;
1026 WRITE << "================================================================================" << endl << endl;
1027 #endif
1028
1029 for (int i = 0; i < inFaultList.size(); i++) {
1030 if(!TestAllVectorsATPG (totalInputs, inFaultList[i].lineNumber, inFaultList[i].stuckAtValue, inVectorList, inTestList)) {
1031 TestList *thisTest;
1032 thisTest = new TestList(inFaultList[i].lineNumber, inFaultList[i].stuckAtValue);
1033 inTestList.push_back(*thisTest);
1034 delete thisTest;
1035
1036 #ifdef DEBUG
1037 WRITE << endl;
1038 WRITE << "------------------------------------------------------------" << endl;
1039 WRITE << "The fault is at line number = " << inFaultList[i].lineNumber << endl;
1040 WRITE << "The fault is stuck at = " << inFaultList[i].stuckAtValue << endl;
1041 WRITE << "Test cannot be generated for this fault." << endl;
1042 WRITE << "------------------------------------------------------------" << endl;
1043 WRITE << endl;
1044 #endif
1045 }
1046 }
1047
1048}
1049
1050/*
1051 * ============================================================================
1052 * NOTE - this function is just written to check the working of all the
1053 * methods defined above. This has no connection with how the final program
1054 * would work.
1055 * ============================================================================
1056 */
1057int main (int argc, char *argv[]) {
1058
1059 #ifdef LOG
1060 openOutFile((char *)LOG_FILE_NAME, logFile, logFile);
1061 WRITE << "================================================================================" << endl;
1062 WRITE << "=============== ===============" << endl;
1063 WRITE << "=============== ATPG Generator - Podem Log File ===============" << endl;
1064 WRITE << "=============== ===============" << endl;
1065 WRITE << "================================================================================" << endl;
1066 WRITE << endl;
1067 WRITE << "Generated On --> " << endl;
1068 WRITE << endl;
1069 WRITE << "================================================================================" << endl;
1070 WRITE << endl << endl << endl;
1071 #endif
1072
1073 ifstream inFile;
1074 ofstream outFile;
1075
1076 if (argc <= 1 || argc > 3) {
1077 cerr << "ERROR: Usage: " << argv[0] << " <Circuit Filename> (Optional <Faultlist Filename>)" << endl;
1078 exit(1);
1079 }
1080 int i;
1081
1082 // The first argument to the program is the circuit file.
1083 openInFile (argv[1], inFile, logFile);
1084 ReadCircuit (inFile);
1085 inFile.close();
1086
1087 // If there is a second argument present, then that is the provided fault
1088 // list that we have to obtain the vectors for.
1089 //
1090 // If the argument is given, parse the file and create a list of faults to
1091 // be checked.
1092 if (argc == 3) {
1093 openInFile (argv[2], inFile, logFile);
1094 ReadFaultList(inFile);
1095 inFile.close();
1096 }
1097
1098 // Levelize the circuit.
1099 SetLineLevel(masterNodeList);
1100
1101 // Create a list of faults to be collapsed.
1102 //
1103 // This creates a list of all the lines in the circuit and assumes possibility of
1104 // a stuck at 0 and 1 fault at each line.
1105 CreateFaultObjects(masterLineList, masterNodeList);
1106
1107 // If there is no fault list provided to be checked then we assume that we have to
1108 // check all the faults in the circuit.
1109 //
1110 // So we create a list of all faults in the circuit.
1111 if (argc == 2) {
1112 CreateFaultList(finalFaultList);
1113 }
1114
1115 // Then we collapse the faults.
1116 CollapseFaults(masterLineList, masterNodeList);
1117
1118 // We create a master list of faults after collapsing the faults.
1119 //
1120 // This list is used to find the test vectors that can identify all
1121 // detectable faults in the circuit.
1122 CreateFaultList(masterFaultList);
1123
1124 // We create a master list of possible inputs. This is a pseudo sequence that
1125 // goes on checking the circuit by first setting only one input and then moving
1126 // on with 2, 3 till it finds proper test.
1127 GenerateMasterInputVectors(CircuitNode::totalInputs);
1128
1129 // Not really necessary. We just simulate the fault free circuit for all possible inputs.
1130 // Uncomment this part if you want simple logic simulation.
1131 /*
1132 vector <string>::iterator itrVector;
1133 for (itrVector = masterInputVector.begin(); itrVector != masterInputVector.end(); itrVector++) {
1134 SimpleLogicSimulation(CircuitNode::totalInputs, *itrVector);
1135 }
1136 */
1137
1138 cout << "=========================================================" << endl;
1139 cout << "========== Starting PODEM ==========" << endl;
1140 cout << "=========================================================" << endl;
1141
1142 // This routine generates a list of vectors (the masterTestList) that has the faults in the circuit
1143 // and the vectors associated with each test.
1144 CheckAllFaultsATPG(CircuitNode::totalInputs, masterInputVector, masterTestList, masterFaultList);
1145
1146 // Here we print all the faults, the faults and the test vectors associated with them.
1147 for (int i = 0; i < masterTestList.size(); i++) {
1148 cout << "Test Information For" << endl;
1149 cout << "------------------------------------------------------------" << endl;
1150 cout << "Line Number Is = " << masterTestList[i].lineNumber << endl;
1151 cout << "Fault Is Stuck At = " << masterTestList[i].stuckAtValue << endl;
1152 if (masterTestList[i].isTestPossible) {
1153 cout << "Test Vector Is = " << StringConvert(masterTestList[i].testVector) << endl;
1154 } else {
1155 cout << "Test is not possible for this fault." << endl;
1156 }
1157 cout << endl;
1158 }
1159
1160 // Here we create a list of all the vectors that were created in the last step.
1161 // This list should, theoretically, be able to test all faults in the circuit.
1162 //
1163 // Only add the vectors where test was possible. Don't add otherwise.
1164 for (int i = 0; i < masterTestList.size(); i++) {
1165 if (masterTestList[i].isTestPossible)
1166 masterTestVector.push_back(masterTestList[i].testVector);
1167 }
1168
1169 cout << "=========================================================" << endl;
1170 if (argc == 3) {
1171 cout << "========== Checking for given faults. ==========" << endl;
1172 } else {
1173 cout << "========== Checking for all faults in circuit. ==========" << endl;
1174 }
1175 cout << "=========================================================" << endl;
1176
1177 // Now, if there was a fault list given, we try to test the faults in the list using
1178 // the master test vector list created in the last step.
1179 //
1180 // If there was no fault list provided then we test the circuit for all the faults in
1181 // the circuit (stuck at 0 and 1 on each line).
1182 if (argc == 3) {
1183 CheckAllFaultsATPG(CircuitNode::totalInputs, masterTestVector, finalTestList, providedFaultList);
1184 } else {
1185 CheckAllFaultsATPG(CircuitNode::totalInputs, masterTestVector, finalTestList, finalFaultList);
1186 }
1187
1188 // We just pring the information out to screen here.
1189 for (int i = 0; i < finalTestList.size(); i++) {
1190 cout << "Test Information For" << endl;
1191 cout << "------------------------------------------------------------" << endl;
1192 cout << "Line Number Is = " << finalTestList[i].lineNumber << endl;
1193 cout << "Fault Is Stuck At = " << finalTestList[i].stuckAtValue << endl;
1194 cout << "Test Vector Is = " << StringConvert(finalTestList[i].testVector) << endl;
1195 cout << endl;
1196 }
1197
1198 // If result file is defined then we dump the whole result in a file
1199 // in the format specified below. This is defined in the global defines file.
1200 //
1201 // lineNumber stuckAtFault
1202 // testVector
1203 // lineNumber stuckAtFault
1204 // testVector
1205 #ifdef RESULT_FILE
1206 openOutFile((char *)VECTOR_FILE_NAME, outFile, logFile);
1207
1208 for (int i = 0; i < masterTestList.size(); i++) {
1209 outFile << masterTestList[i].lineNumber << " " << masterTestList[i].stuckAtValue << endl << StringConvert(masterTestList[i].testVector) << endl;
1210 }
1211
1212 outFile.close();
1213
1214 openOutFile((char *)REPORT_FILE_NAME, outFile, logFile);
1215
1216 for (int i = 0; i < finalTestList.size(); i++) {
1217 outFile << finalTestList[i].lineNumber << " " << finalTestList[i].stuckAtValue << endl << StringConvert(finalTestList[i].testVector) << endl;
1218 if (finalTestList[i].isTestPossible)
1219 outFile << "Yes" << endl;
1220 else
1221 outFile << "No" << endl;
1222 }
1223
1224 outFile.close();
1225 #endif
1226
1227 /*
1228 * ============================================================================
1229 * This is the same routine as the one used in the code provided to us.
1230 * Just using it here to print information about the circuit to terminal.
1231 * Not really required in the ATPG.
1232 * ============================================================================
1233 */
1234
1235 #ifdef DEBUG_PRINT
1236 set <int>::iterator it;
1237 for (i = 0; i < masterNodeList.size(); i++) {
1238 cout << "-----------------------------------------------------" << endl;
1239 cout << endl << endl;
1240 cout << " Node Type \tIn\t\tOut\t\tFaults" << endl;
1241 for(i = 0; i<CircuitNode::totalNodes; i++) {
1242 cout << "\t\t\t\t";
1243 for(it = masterNodeList[i].listFanOut.begin(); it != masterNodeList[i].listFanOut.end(); it++) {
1244 cout << *it << ", ";
1245 }
1246 cout << "\b\b ";
1247
1248 cout << "\r\t\t\t\t\t\t";
1249
1250 printf("\r%5d %d\t", masterNodeList[i].lineNumber, masterNodeList[i].gateType);
1251
1252 for(it = masterNodeList[i].listFanIn.begin(); it != masterNodeList[i].listFanIn.end(); it++) {
1253 cout << *it << ", ";
1254 }
1255 cout << "\b\b ";
1256
1257 cout << endl;
1258 }
1259
1260 cout << endl << endl;
1261 cout << "Number of nodes = " << CircuitNode::totalNodes << endl;
1262 cout << "Number of primary inputs = " << CircuitNode::totalInputs << endl;
1263 cout << "List of inputs = ";
1264 for(i = 0; i<CircuitNode::totalNodes; i++) {
1265 if (masterNodeList[i].numberFanIn == 0)
1266 cout << masterNodeList[i].lineNumber << ", ";
1267 }
1268 cout << "\b\b " << endl;
1269 cout << "Number of primary outputs = " << CircuitNode::totalOutputs << endl;
1270 cout << "List of outputs = ";
1271 for(i = 0; i<CircuitNode::totalNodes; i++) {
1272 if (masterNodeList[i].numberFanOut == 0)
1273 cout << masterNodeList[i].lineNumber << ", ";
1274 }
1275 cout << "\b\b " << endl;
1276
1277 }
1278 #endif
1279
1280 #ifdef LOG
1281 logFile.close();
1282 #endif
1283}