Upload
others
View
8
Download
0
Embed Size (px)
Citation preview
Graduate Theses and Dissertations Iowa State University Capstones, Theses andDissertations
2018
Design and verification approaches for reliabilityand functional safety of analog integrated circuitsZhiqiang LiuIowa State University
Follow this and additional works at: https://lib.dr.iastate.edu/etd
Part of the Electrical and Electronics Commons
This Dissertation is brought to you for free and open access by the Iowa State University Capstones, Theses and Dissertations at Iowa State UniversityDigital Repository. It has been accepted for inclusion in Graduate Theses and Dissertations by an authorized administrator of Iowa State UniversityDigital Repository. For more information, please contact [email protected].
Recommended CitationLiu, Zhiqiang, "Design and verification approaches for reliability and functional safety of analog integrated circuits" (2018). GraduateTheses and Dissertations. 17246.https://lib.dr.iastate.edu/etd/17246
Design and verification approaches for reliability and functional
safety of analog integrated circuits
by
Zhiqiang Liu
A dissertation submitted to the graduate faculty
in partial fulfillment of the requirements for the degree of
DOCTOR OF PHILOSOPHY
Major: Electrical Engineering
Program of Study Committee:
Degang Chen, Major Professor
Randall Geiger
Chris Chong-Nuen Chu
Jiming Song
Ratnesh Kumar
The student author, whose presentation of the scholarship herein was approved by the
program of study committee, is solely responsible for the content of this dissertation. The
Graduate College will ensure this dissertation is globally accessible and will not permit
alterations after a degree is conferred.
Iowa State University
Ames, Iowa
2018
Copyright © Zhiqiang Liu, 2018. All rights reserved.
ii
DEDICATION
To my family
iii
TABLE OF CONTENTS
Page
LIST OF FIGURES ................................................................................................................. vi
LIST OF TABLES ................................................................................................................... ix
ACKNOWLEDGMENTS ........................................................................................................ x
ABSTRACT ............................................................................................................................. xi
CHAPTER 1. INTRODUCTION ............................................................................................. 1
1.1 Background and Motivation .......................................................................................... 1 1.2 Organization of Dissertation .......................................................................................... 6
1.3 References ..................................................................................................................... 9
CHAPTER 2. DESIGN OF LOW TEMPERATURE-COEFFICIENT BANDGAP
REFERENCE .......................................................................................................................... 11 2.1 Introduction ................................................................................................................. 11 2.2 Curvature Compensation and General Concept of VGO extractor................................ 15
2.2.1 Temperature Characteristic of VBE ...................................................................... 15 2.2.2 Curvature Compensation Approaches ................................................................. 17
2.2.3 VGO Extraction in General ................................................................................. 20 2.2.4 Discussion ........................................................................................................... 22
2.3 One Implementation of Proposed Voltage Reference Generator ................................ 23 2.3.1 Generation of Nonlinear Term Containing TlnT ................................................ 23
2.3.2 VGO Extraction ................................................................................................... 25 2.4 Discussion of Non-Ideal Error Source ......................................................................... 28
2.4.1 Temperature dependence of resistors (TCR)....................................................... 28
2.4.2 Temperature dependence of BJT current gain .................................................... 29 2.4.3 Opamp offset ....................................................................................................... 30
2.5 Simulation Results ....................................................................................................... 33
2.6 Conclusion ................................................................................................................... 35 2.7 References ................................................................................................................... 37
CHAPTER 3. AUTO-IDENTIFICATION OF POSITIVE FEEDBACK LOOPS IN
MULTI-STATE VULNERABLE CIRCUITS ....................................................................... 40 3.1 Introduction ................................................................................................................. 40 3.2 Feedback Loops ........................................................................................................... 42 3.3 PFLs Identification ...................................................................................................... 45
3.3.1 Analyze the Netlist .............................................................................................. 45 3.3.2 Determine the Channel List ................................................................................. 46 3.3.3 Construct DDG .................................................................................................... 46 3.3.4 Identify Feedback Loops and Determine The Sign ............................................. 48
iv
3.4 Simulation Results ....................................................................................................... 50
3.5 Conclusion ................................................................................................................... 53
3.6 References ................................................................................................................... 54
CHAPTER 4. SYSTEMATIC BREAKING-LOOP METHOD FOR VERIFICATION
AGAINST UNDESIRED OPERATING POINTS ................................................................. 56 4.1 Introduction ................................................................................................................. 56 4.2 Break-loop Homotopy Method .................................................................................... 59
4.3 A Multi-loop Example ................................................................................................. 61 4.4 Strongly-Connected Components ................................................................................ 63
4.4.1 Constructing the DDG ......................................................................................... 63 4.4.2 Strongly-Connected Components........................................................................ 65
4.5 Identify and Break PFLs .............................................................................................. 66
4.5.1 Identity Positive Feedback Loops ....................................................................... 66 4.5.2 Break Positive Feedback Loops .......................................................................... 67
4.6 Results ......................................................................................................................... 68 4.7 Conclusion ................................................................................................................... 69
4.8 References ................................................................................................................... 71
CHAPTER 5. IMPROVING TIME-EFFICIENCY OF FAULT-COVERAGE
SIMULATION FOR MOS ANALOG CIRCUIT .................................................................. 73
5.1 Introduction ................................................................................................................. 73 5.2 Overview of Proposed Method .................................................................................... 76
5.3 Directed Dependency Graph ....................................................................................... 79 5.3.1 Directed Dependency Graph ............................................................................... 79
5.3.2 Strongly-Connected Components........................................................................ 83 5.4 Fault Simulation with Sub-circuits .............................................................................. 85
5.4.1 SCC Sub-circuits ................................................................................................. 85 5.4.2 Time Efficiency ................................................................................................... 88
5.5 Fault Coverage Evaluation .......................................................................................... 89
5.5.1 Directed Acyclic Graph ....................................................................................... 90 5.5.2 Backward Sensitivity Analysis ............................................................................ 91
5.6 Case Study ................................................................................................................... 96
5.7 Discussion .................................................................................................................. 100 5.8 Conclusion ................................................................................................................. 101 5.9 References ................................................................................................................. 103
CHAPTER 6. IMPROVING ANALOG FAULT-COVERAGE WITH SYSTEMATIC
TEST-POINTS SELECTION AND CONCURRENT SAMPLING .................................... 106 6.1 Introduction ............................................................................................................... 106 6.2 Overview of Proposed Method .................................................................................. 108
6.3 Test-Points Set ........................................................................................................... 110 6.3.1 Directed Dependency Graph ............................................................................. 110 6.3.2 Recursive Backward Propagation Method ........................................................ 112
6.4 Concurrent Sampling with Local Digitization ........................................................... 115 6.5 Case Study ................................................................................................................. 118
v
6.6 Conclusion ................................................................................................................. 121
6.7 References ................................................................................................................. 122
CHAPTER 7. CONCLUSION .............................................................................................. 124
APPENDIX A. PROGRAMS FOR IDENTIFYING AND BREADING FEEDBACK
LOOPS OF A CIRCUIT ....................................................................................................... 127
APPENDIX B. PROGRAMS FOR IMPROVING TIME EFFICIENCY OF FAULT-
COVERAGE SIMULATION ............................................................................................... 244
vi
LIST OF FIGURES
Page
Figure 1.1 IoT/IoE of the New Ecosystem of the Electronics’ Industry (Modified from
2017 IRDS) ........................................................................................................... 1
Figure 2.1 Operation of a standard VBE-based bandgap reference ......................................... 12
Figure 2.2 Example of curvature in the GlobalFoudries 130nm process ............................... 17
Figure 2.3 Bermak’ curvature correction technique: bias a BJT base with a PTAT
current ................................................................................................................. 18
Figure 2.4 Curvature compensation by adding a logarithmic term (a) simplified
schematic R3-R4=Rtype1 and R5= Rtype2 (b) curvature compensation
illustration ........................................................................................................... 19
Figure 2.5 Curvature compensation by adding the piecewise linear current (a) simplified
schematic (b) curvature compensation illustration ............................................. 20
Figure 2.6 Illustration of using (a) three diodes (b) three BJT connected as diodes, to
extract the VGO .................................................................................................... 21
Figure 2.7 Generation of PTAT current using two BJTs ....................................................... 23
Figure 2.8 Generation of nonlinear term containing TlnT ..................................................... 24
Figure 2.9 Conceptual generation of temperature independent current ................................. 25
Figure 2.10 One implementation of the proposed method ..................................................... 27
Figure 2.11 Equivalent circuit when opamp offset of A2 is injected ..................................... 31
Figure 2.12 Equivalent circuit when opamp offset of A1 is injected ..................................... 32
Figure 2.13 Bandgap voltage versus absolute temperature and the tangent line for
Tr=300K .............................................................................................................. 33
Figure 2.14 Output voltage over process ................................................................................ 34
Figure 2.15 Output voltage over process with (a)one-point and (b)two-points calibration .... 34
Figure 3.1 A feedback structure .............................................................................................. 41
Figure 3.2 Inverse widlar (a) branch-current and controlling voltage (b) directed
dependency graph ............................................................................................... 43
vii
Figure 3.3 Bootstrapped Vt reference circuit (a) schematic (b) netlist (c) channels list (d)
branches (e) directed dependency graph ............................................................ 45
Figure 3.4 Sign of dependencies for Figure 3.2(e) (a) the upper loop (b) the bottom loop .... 49
Figure 3.5 Voltage regulator (a) schematic (b) DDG ............................................................. 50
Figure 3.6 Sign of dependencies for each loop shown in Figure 3.5(b) ................................. 51
Figure 3.7 Schematic of self-biased bandgap reference ......................................................... 51
Figure 3.8 DDG of self-biased bandgap circuit shown in Figure 3.7 ..................................... 52
Figure 3.9 Sign of dependencies for each loop shown in Figure 3.8 ...................................... 52
Figure 4.1 Flow chart of proposed method ............................................................................. 58
Figure 4.2 Broken PFLs for Wilson bias generator (a) Break at the schematic (b) Break
at the DDG .......................................................................................................... 59
Figure 4.3 Return map for Wilson bias generator (a) Blue: curve for VA1= VA2 (b) Red:
return map when temperature is 25oC (c) Black: return map when
temperature is 125 oC ......................................................................................... 61
Figure 4.4 A full CMOS Voltage regulating circuit ............................................................... 62
Figure 4.5 (a) schematic (b) netlist (c) channels list (d) branches (e) directed
dependency graph ............................................................................................... 64
Figure 4.6 Example directed graph ........................................................................................ 66
Figure 4.7 Schematic of the Sub-Bandgap reference............................................................. 68
Figure 4.8 DDG showing SCCs of Figure 4.7 ........................................................................ 69
Figure 4.9 Widlar-banba circuit (a) schematic (b) DDG showing the strongly connected
components ......................................................................................................... 70
Figure 5.1 Flowchart of the proposed method ....................................................................... 78
Figure 5.2 A simple directed graph example ......................................................................... 80
Figure 5.3 Example circuit: Widlar bias generator, (a) schematic (b) DDG ......................... 81
Figure 5.4 The SCCs for the DDG shown in Figure 2.3(b) ................................................... 84
Figure 5.5 (a) SCC sub-circuits of example widlar circuit (b) a sub-circuit generated
from the combination of SCC2 and SCC3 ......................................................... 86
viii
Figure 5.6 The directed acyclic graph for Figure 5.3 ............................................................ 91
Figure 5.7 (a)an artificial DAG where SCC1 has two output vertices N1 and N2; (b)
calculation of equivalent detection limits for N1 and N2 .................................... 94
Figure 5.8 A simplified graph where multiple paths exist from one vertex to a test point
vertex to a test point ........................................................................................... 94
Figure 5.9 Benchmark circuit ................................................................................................ 96
Figure 5.10 A ‘simplified’ graph of the benchmark circuit in Figure 5.9 ............................. 97
Figure 6.1 Flowchart of the proposed method ...................................................................... 109
Figure 6.2 Example circuit: Widlar bias generator, (a) schematic (b) DDG with with
SCCs ................................................................................................................. 112
Figure 6.3 The DAG for the DDG shown in Figure 6.2 ....................................................... 113
Figure 6.4 Recursive backward method (a) DAG with fault impacts in each SCC (b)
first iteration (c) second iteration ..................................................................... 114
Figure 6.5 Local Digitization ................................................................................................ 116
Figure 6.6 Architecture of the proposed Concurrent Sampling method ............................... 117
Figure 6.7 Benchmark circuit with the test-points highlighted with different color a)
Red: from iteration 0; b) Blue: from iteration 1; c) Green: from iteration 2;
d)Purple: from iteration 3 ................................................................................ 119
ix
LIST OF TABLES
Page
Table 2.1 Error sources in a typical CMOS BGR ................................................................... 13
Table 2.2 Comparison with the state-of-the-art high-precision voltage reference
generators ........................................................................................................... 35
Table 3.1 The Sign of Different Dependencies ...................................................................... 49
Table 4.1 Simulation Results of Voltage Regulating Circuit ................................................. 63
Table 5.1 Performance Summary ........................................................................................... 99
Table 6.1 Differences between ATB and CS ........................................................................ 118
Table 6.2 Iterations of The Recursive Backward Method .................................................... 120
Table 6.3 Comparison with the state-of-the-art methods...................................................... 120
x
ACKNOWLEDGMENTS
First and foremost, I wish to express my deepest gratitude to my advisor Dr. Degang
Chen for his guidance, support, and patience during my research study. In the past several
years, he has helped me to develop my background in Analog IC design, Mix-signal IC
design, and verification.
I would also like to thank my committee members, Dr. Randall Geiger, Dr. Chris
Chong-Nuen Chu, Dr. Jiming Song, and Dr. Ratnesh Kumar, for their guidance and
encouragement throughout the course of this research.
In addition, I would also like to express my thanks to Shravan Chaganti, Dr. You Li,
Xu Zhang, Chin-Wen Chen, Huanhuan Zhang, Hao Meng, Nanqi Liu, Dr. Bin Huang, Dr.
Minshun Wu and my other friends, especially Songlin Hu, Yang He and Yifei Li who helped
me with various aspects of conducting this Ph.D. work. I want to also offer my appreciation
to my colleagues, the department faculty, and staff for making my time at Iowa State
University a wonderful experience.
I thank my parents: Xianbao Liu and Yinfeng Luo, for their unconditional love and
support throughout my Ph.D. study abroad. I would also like to thank my sisters and
brothers-in-law: Shufei Liu, Ming Liu, Shujuan Liu, and Kun Zhang for providing me with
encouragement and any necessary supports during my study.
xi
ABSTRACT
New breakthroughs in semiconductor design have enabled a rapid integration of
semiconductor chips into systems that affect all aspects of the society. Examples of emerging
systems include spacecraft, Internet of Things (IoT), intelligent automotive, and bio-
implantable devices. Many of these systems are mission-critical or safety-critical, meaning
that failure or malfunction may lead to severe economic losses, environmental damages or
risks to human lives [1]. In addition to performances improvement, the reliability and
functional safety of the underlying integrated circuit (IC) have attracted more and more
attention and have posed grand challenges for semiconductor industries. This dissertation
introduces an approach for high performance voltage reference design and investigates two
subjects that improve the reliability and functional safety of analog circuits.
The first part of this dissertation studies design strategies of a low temperature-
coefficient voltage reference generator, which is a fundamental building block and
determines the maximum achievable performance of almost all analog/mixed-signal systems.
The proposed method is targeted at extracting a physical quantity of the silicon bandgap, and
has the potential of designing a voltage reference that has qualitatively better temperature
dependence. An implementation of the proposed approach in GlobalFoundries 130nm
process shows that the design can achieve temperature coefficients as low as 0.7ppm/°C over
a temperature range of -40°C to 125°C over all process corners.
The second part of this dissertation focuses on multi-states verification of analog
circuits. The multiple DC equilibrium points or multi-states problem traces back to IC
design. It is a well-known problem in many basic self-stabilized analog circuits because of
the existence of positive feedback loops (PFLs). This work proposes systematic and
xii
automatic approaches for locating all PFLs to identify circuits vulnerable to undesired
equilibrium states and methods for automatically identifying break-points to break all PFLs
in the vulnerable circuits. The proposed methods make it possible to efficiently identify a
circuit’s vulnerability to undesired operating points by considering circuit topology only,
without the need for finding all possible solutions to a set of simultaneous nonlinear
equations which is an open problem with no solution. Moreover, the automatic break-points
identification enables easy use of homotopy analysis to guarantee absence of undesired
states.
The third part of this dissertation focuses on fault coverage simulation of analog
circuits. This work describes two methods, one is to reduce the fault coverage estimation
time and the other is to improve the fault coverage for analog circuits. The first method
incorporates graph theory and sensitivity analysis and leads to a dramatic reduction in fault
coverage simulation time by 10’s of times for a moderately sized analog circuit. The second
method discusses a systematic test-points selection technique to improve the analog fault
coverage with simple DC tests and a concurrent sampling technique for monitoring these
points. This work could be applied to manufacturing testing or for real-time fault detection.
1
CHAPTER 1. INTRODUCTION
1.1 Background and Motivation
During the past 50 years, the semiconductor industry has marched at the pace of
Moore’s Law. Transistor scaling associated with doubling the number of transistors every
two years on the average has been and continues to be the unique feature of the
semiconductor industry[2]. As the manufacturer technology and design innovation advance,
both the complexity and the number of ICs embedded in systems that affect all aspects of the
society have grown rapidly. Figure 1.1 gives an overview of the well-known topic, Internet
of Things/Internet of Everything (IoT/IoE) which is simplified from the new ecosystem of
the electronics’ industry in the 2017 International roadmap for devices and systems (IRDS)
[2]. It is worth to point out that analog circuits play major and irreplaceable roles in the core
hardware of IoT/ToE. Specifically, in Figure 1.1, the Radio Frequency (RF), Analog Front
End (AFE) and sensors are essentially analog circuits; inside all other sub-systems (e.g., bio-
medical devices, intelligent automotive), there are also various analog components
Figure 1.1 IoT/IoE of the New Ecosystem of the Electronics’ Industry (Modified from 2017 IRDS)
2
such as reference generators, analog-to-digital converters (ADC), digital-to-analog
converter(DAC), power management ICs, and et al.
Performance improvement, such as high speed, high accuracy, low power and small
area are still an important goal for current and future semiconductor industries. The IRDS
technology roadmap (More Moore) targets bringing PPAC value for node scaling every 2-3
years [3], [4]:
• (P)erformance:> 15% more operating frequency at scaled supply voltage
• (P)ower: >35% less energy per switching at a given performance
• (A)rea: >35% less chip area footprint
• (C)ost:<30% more wafer cost-20% less die cost for scaled die.
In addition to continuous performance improvements, the reliability and functional
safety of the underlying ICs have attracted more and more attention and have posed grand
challenges for both academia and industry. On the one hand, this is because failure or
malfunction of those safety-critical systems, e.g., automotive or medical devices, may
directly or indirectly lead to severe economical losses, environmental damages or risks to
human lives. On the other hand, the shrunk geometries, higher operating frequency, and
scaled supply voltage bring negative impacts on functional safety and reliability to a circuit.
In particular, such technology advances have the potential to increase the rate of occurrence
of a fault. For example, smaller interconnect features will increase the likelihood of
intermittent faults, resulting from process variations and manufacturing residuals[5]. Smaller
transistors and lower supply voltages lead to higher sensitivity to neutron and alpha particles,
which in turn significantly increase rates of particle-induced transients[5]. Moreover, as the
complexity, as well as the number of ICs in a system, grows, the impacts of some hidden or
3
negligible problems may manifest and become critical. One example of such problems is
multiple DC equilibrium points problem.
This dissertation will first introduce an approach for high-performance voltage
reference design and then investigate two subjects that improve the reliability and functional
safety of analog circuits, multi-state verification and fault coverage analysis. The first subject
traces back to IC design itself and the second results from the manufacturing process.
The first part of this dissertation studies design strategies of low temperature-
coefficient voltage reference generator. The accuracy of voltage reference determines the
maximum achievable performance of nearly all mixed-signal and radio-frequency systems
[6], [7]. Increasing demands of modern high-performance circuits such as voltage regulators,
high-resolution data converters, and precision measurement systems, pose a need for the
design of high-accuracy, low temperature coefficient (TC) voltage reference. Over the past
few years, efforts in high-precision reference study have emerged in both industry [8]–[10]
and academia [11]–[15]. These precision reference generators utilize the base-emitter voltage
(VBE) of a bipolar junction transistor since VBE contains a physical constant voltage VGO
which is independent of temperature, supply, and process over a very wide temperature
range. In most exiting high-order compensation techniques, low temperature drift is achieved
by canceling the temperature nonlinearity of VBE and making the temperature coefficient zero
at a given reference temperature Tr, resulting in an output voltage with a constant term equal
or proportional to VGO plus a high order term of Tr. In another word, there is no exiting work
that reports exact VGO extraction. Therefore, it is very meaningful to investigate techniques to
exactly extract the VGO such that a voltage reference with qualitatively better temperature
dependence can be created.
4
Many basic analog circuits, such as self-stabilized bias generators, voltage and
current references, and Schmitt-triggers [1,2,3], frequently utilized as subcircuits in large-
scale circuit, are well known to sometimes possess multiple DC operating points or multiple
states. This is due to the existence of positive feedback loops (PFLs) []. These PFLs can be
inherently in the circuit, e.g., self-stabilized bias generators or intentionally introduced by the
designer for stabilization or performance enhancement. Moreover, these PFLs can also be
unintentionally introduced when the circuit becomes complex. The presence of multiple
states sometimes causes these circuits to fail to function as designed [4]. Therefore it is
worthwhile to verify the presence of such multiple states before the fabrication of circuits.
Unfortunately, according to [5], the commonly used simulators such as spectre and ultraism,
provide only one solution even though multiple states may be present. Start-up circuits have
been introduced to make a circuit work at the desired states. However, there are several
concerns: a) there is no systematical way to identify the potential multiple states problem of a
circuit. It is typically achieved by inspection or by the designers’ experience, which might be
possible for a small circuit but it becomes difficult or impracticable as the circuit size
becomes complex and large. b) the introduction of a start-up circuit for a target design is
usually heuristic and there is no systematical method to verify that the added start-up circuit
has successfully removed the undesired states over process or temperature variation. Break-
loop homotopy methods [16] have been investigated to guarantee freedom of undesired states
of a circuit. However, these methods require the knowledge of all feedback loops and how to
break all positive feedback loops in the circuit. Therefore, systematic and automatic
approaches are needed for locating all PFLs to identify circuits vulnerable to undesired
5
equilibrium states. In addition, methods for automatically identifying break-points to break
all PFLs in the vulnerable circuits are also needed.
A defect introduced by an unintended physical change during the manufacturing
fabrication may result in dramatic performance loss and possibly even system failure. Fault
simulation is a technique for estimating the coverage by injecting hypothetical physical
defects into a design and verifying that a manufacturing test or verification suite can detect
them. The increasingly stringent quality requirements for modern safe/mission-critical
systems have posed grand challenges to improve fault coverage, i.e., to prevent
malfunctioning ICs from being shipped to customers. After decades of innovation, fault
coverage simulation for digital circuits has achieved great success, with test escape rates
reaching below 0.1 defective parts per million (dppm) [17], [18]. However, fault simulation
for analog circuits lags far behind, and there is a lack of existing commercially-available
analog fault simulators [19]. Although analog circuits typically constitute only a small
fraction of modern mixed-signal ASICs, they represent a major cause of customer returns in
the industry [17], [20]. Therefore, there is an urgent need to develop practical and efficient
methods for improving fault coverage for analog circuits at reasonable cost and time.
In analog fault simulation, there are two major challenges the number one challenge
is that simulation time could grow rapidly and become prohibitive as circuit size becomes
large. Therefore, practical methods for improving time efficiency in estimating the fault
coverage of analog fault simulation is needed. Another challenge is that the primary outputs
provide very limited observability, making it virtually impossible to achieve high fault
coverage for analog circuits without observing internal nodes [21]. Although researchers tend
to believe that observing some internal nodes is one effective technique for improving fault
6
coverage, exactly where and how to access these nodes still remains challenging in reality.
Hence, systematic methods for selecting the test-points and monitoring these points are
needed as well.
1.2 Organization of Dissertation
The rest of this dissertation is arranged in the following order:
Chapter 2. This chapter describes a precision voltage reference generator targeting a
sub-ppm temperature coefficient over a wide temperature range. Unlike conventional
curvature-correction techniques that attempt to cancel the temperature nonlinearity of VBE,
the proposed method is specifically targeted at extracting VGO from the temperature
characteristic of VBE. Analytical constraints that lead to strategies for creating an output
voltage proportional to VGO when certain mismatches and offsets are accurately trimmed are
carefully investigated. The proposed method is implemented in the GlobalFoundries 130nm
process. Simulation results show that the design can achieve temperature coefficients as low
as 0.7ppm/°C from -40°C to 125°C over process corners.
Chapter 3. A systematic method is proposed for automatically identifying positive
feedback loops (PFLs) in analog/mixed-signal circuits. The method first converts the netlist
of a circuit into a directed dependency graph (DDG) that captures the critical relationships
among branch currents and node voltages. It then utilizes graph theory techniques to find all
feedback loops from the DDG and, finally, a criterion for determining the PFLs is developed.
Since multiple states are caused by the PFLs, this method could identify a circuit’s
vulnerability to undesigned operating points only by considering only its structure and
without the computation of DC solutions. The proposed approach is implemented in a
program, and simulation results show that it can identify all PFLs very robustly.
7
Chapter 4. A method for breaking PFLs in Multi-states vulnerable circuits is
proposed in this Chapter. At determined breaking points, a break-loop homotopy sweep
method can be applied to verify the presence or absence of undesired operating points. It will
be shown that questions of how and where to break PFLs is challenging for many circuits,
particularly as a circuit becomes large and feedback structures become complex. To
overcome such difficulty, graph theory techniques are employed to partition a complex
circuit graph into disjoint Strongly Connected Components (SCCs). Based on this approach,
detection of PFLs and locating break-points can be conducted for every SCC. This limits the
sweep dimension of the break-loop homotopy sweep method to within one or two even for a
large-scale circuit. Sub-Bandgap reference and widlar-Banba examples will be used to show
that the proposed approach can effectively identify all the SCCs and corresponding
breakpoints. methods for automatically identifying break-points to break all PFLs in the
vulnerable circuits are also proposed.
Chapter 5. This chapter proposes a systematic method for significantly improving
time efficiency in estimating the fault coverage for analog fault simulation. In analog fault
simulation, the number one challenge is that, the overall simulation time could grow rapidly
and become prohibitively high as circuit size becomes large. In the proposed method, a
circuit under test (CUT) is first partitioned into independent sub-circuits. This is
accomplished through mapping the circuit into a graph, decomposing the graph into strongly
connected components (SCCs), and generating a sub-circuit for each SCC. The impacts of
potential faults directly entering a sub-circuit are then simulated and recorded using the sub-
circuits, an activity expected to be much more time-efficient than fault simulation using the
much larger whole circuit. Finally, fault detectability at the given test-points is evaluated
8
based on fault impacts and sensitivity among the different sub-circuits. As a first step toward
quick estimation of fault coverage, this chapter focuses on DC tests. Simulation results show
that the fault coverage of DC tests can be estimated sufficiently accurately, with simulation
time reduced by 10X, or by approximately the number of SCCs, for the benchmark circuit.
For a much larger circuit, the number of SCCs is expected to be much larger and the
corresponding time-saving factor would also be much larger.
Chapter 6. A novel Test-Points selection And Concurrent sampling method(TPAC)
is introduced for significantly improving fault coverage of analog circuits. The method
consists of two major parts. The first part is to select a set of test-points with a recursive
backward method such that the knowledge of values of the selected test-points is sufficient to
tell whether a fault has occurred in the circuit. Since the selected test-points could be internal,
we propose concurrent sampling with local digitization for observing the values at these test-
points. The proposed concurrent sampling method allows multi-bit resolution and thus
enables detection of both catastrophic(hard) faults and parametric faults. As part of
concurrent sampling, the measurement results are sent out as digital values. The proposed
TPAC method could be used for off-line manufacturer tests as well as for real-time fault
detection.
Chapter 7 concludes the dissertation.
9
1.3 References
[1] M. Bozzano and A. Villafiorita, Design and safety assessment of critical systems.
Auerbach Publications, 2010.
[2] “The 2017 International roadmap for devices and systems, Executive Summary.”
[Online]. Available: https://irds.ieee.org/images/files/pdf/2017/2017IRDS_ES.pdf.
[Accessed: 09-Apr-2018].
[3] “The 2017 International roadmap for devices and systems, More Moore,” IRDS, 2017.
[Online]. Available: https://irds.ieee.org/images/files/pdf/2017/2017IRDS_MM.pdf.
[Accessed: 09-Apr-2018].
[4] W. T. J. Chan, A. B. Kahng, S. Nath, and I. Yamamoto, “The ITRS MPU and SOC
system drivers: Calibration and implications for design-based equivalent scaling in the
roadmap,” in 2014 IEEE 32nd International Conference on Computer Design (ICCD),
2014, pp. 153–160.
[5] C. Constantinescu, “Trends and challenges in VLSI circuit reliability,” IEEE Micro, vol.
23, no. 4, pp. 14–19, Jul. 2003.
[6] P. K. T. Mok and K. N. Leung, “Design considerations of recent advanced low-voltage
low-temperature-coefficient CMOS bandgap voltage reference,” in Custom Integrated
Circuits Conference, 2004. Proceedings of the IEEE 2004, 2004, pp. 635–642.
[7] J.-H. Li, X. Zhang, and M. Yu, “A 1.2-V Piecewise Curvature-Corrected Bandgap
Reference in 0.5 m CMOS Process,” IEEE Trans. Very Large Scale Integr. VLSI Syst.,
vol. 19, no. 6, pp. 1118–1122, Jun. 2011.
[8] “LTC6655 - 0.25ppm Noise, Low Drift Precision References - Linear Technology.”
[Online]. Available: http://www.linear.com/product/LTC6655.
[9] “REF5050 | Series Voltage Reference | Voltage Reference | Description & parametrics.”
[Online]. Available: http://www.ti.com/product/REF5050.
[10] “MAX6126 Ultra-High-Precision, Ultra-Low-Noise, Series Voltage Reference -
Maxim.” [Online]. Available: http://datasheets.maximintegrated.com/en/ds/3623.pdf.
[11] C. M. Andreou, S. Koudounas, and J. Georgiou, “A Novel Wide-Temperature-Range,
3.9 ppm/°C CMOS Bandgap Reference Circuit,” IEEE J. Solid-State Circuits, vol. 47,
no. 2, pp. 574–581, Feb. 2012.
[12] R. Oberhuber, R. Prakash, and V. Ivanov, “A 1 ppm/°C bandgap voltage reference with
new second-order Taylor curvature compensation,” in 23rd IEEE International SOC
Conference, 2010, pp. 71–76.
10
[13] B. Wang, M. K. Law, and A. Bermak, “A Precision CMOS Voltage Reference
Exploiting Silicon Bandgap Narrowing Effect,” IEEE Trans. Electron Devices, vol. 62,
no. 7, pp. 2128–2135, Jul. 2015.
[14] Z. Zhou et al., “A 1.6-V 25-µA 5-ppm/ C Curvature-Compensated Bandgap Reference,”
IEEE Trans. Circuits Syst. Regul. Pap., vol. 59, no. 4, pp. 677–684, Apr. 2012.
[15] B. Ma and F. Yu, “A Novel 1.2–V 4.5-ppm/°C Curvature-Compensated CMOS Bandgap
Reference,” IEEE Trans. Circuits Syst. Regul. Pap., vol. 61, no. 4, pp. 1026–1035, Apr.
2014.
[16] Y. Li, Z. Liu, and D. Chen, “Efficient Verification Against Undesired Operating Points
for MOS Analog Circuits,” IEEE Trans. Circuits Syst. Regul. Pap., vol. 64, no. 8, pp.
2134–2145, Aug. 2017.
[17] A. Coyette, G. Gielen, R. Vanhooren, and W. Dobbelaere, “Optimization of analog fault
coverage by exploiting defect-specific masking,” in Test Symposium (ETS), 2014 19th
IEEE European, 2014, pp. 1–6.
[18] R. Gordon and A. Sadok, “An Overview of Mixed-Signal Production Test from a
Measurement Principle Perspective,” IEEE Des. Test, no. 99, pp. 1–1.
[19] S. Sunter, K. Jurga, P. Dingenen, and R. Vanhooren, “Practical random sampling of
potential defects for analog fault simulation,” in Test Conference (ITC), 2014 IEEE
International, 2014, pp. 1–10.
[20] L. Fang, M. Lemnawar, and Y. Xing, “Cost Effective Outliers Screening with Moving
Limits and Correlation Testing for Analogue ICs,” in Test Conference, 2006. ITC ’06.
IEEE International, 2006, pp. 1–10.
[21] A. Coyette, B. Esen, R. Vanhooren, W. Dobbelaere, and G. Gielen, “Automatic
generation of autonomous built-in observability structures for analog circuits,” in 2015
20th IEEE European Test Symposium (ETS), 2015, pp. 1–6.
11
CHAPTER 2. DESIGN OF LOW TEMPERATURE-COEFFICIENT BANDGAP
REFERENCE
Abstract
This chapter presents a precision voltage reference generator targeting sub-ppm
temperature coefficient over a wide temperature range. Unlike conventional curvature
correction techniques that attempt to cancel the temperature nonlinearity of VBE, the proposed
method is specifically targeted at extracting VGO from the temperature characteristic of VBE.
VGO is the band gap voltage of silicon extrapolated at zero Kevin and is temperature
independent over a very wide temperature range. Analytical constraints that lead to strategies
for creating an output voltage proportional to VGO when certain mismatches and offsets are
accurately trimmed. The proposed method is implemented in the GlobalFoundries 130nm
process. Simulation results show that the design can achieve temperature coefficients as low
as 0.7ppm/°C ranging from -40°C to 125°C over process corners.
2.1 Introduction
The accuracy of voltage reference determines the maximum achievable performance
of nearly all mixed-signal and radio-frequency systems [1], [2]. Increasing demands of
modern high-performance circuits such as voltage regulators, high-resolution data converters,
and precision measurement systems, pose a need for the design of high-accuracy, low
temperature coefficient (TC) voltage reference.
Although some approaches make use of gate-source voltage of MOSFETs operating
in weak inversion[3], most precision reference generators utilize the base-emitter voltage
(VBE) of a bipolar junction transistor (BJT). The reason is that the VBE is better characterized
over temperature and varies less than the threshold voltage and mobility of a MOSFET [4],
[5]. A standard VBE-based bandgap reference generator is implemented using a weighted
12
summation of a proportional-to-absolute-temperature (PTAT) voltage and the VBE, a
complementary-to-absolute-temperature (CTAT). However, because of the nonlinearity of
VBE over a temperature range, curvature compensation is usually required in order to
achieve a low temperature coefficient.
T36T35
Q1 Q2
Vr
R2
R1
VDD
First order BGR
VPTAT
VBE
V
T
Figure 2.1 Operation of a standard VBE-based bandgap reference
Challenges for designing precision bandgap reference generators have been
investigated, and various approaches to overcome these challenges have been developed
since the 1980s [6]–[9]. Over the past few years, efforts in high-precision reference study
have emerged in both industry [10]–[12] and academia [5], [13]–[16] and the TC values
achieved approach the ppm level. Makinwa, et al., in [17] pointed out that opamp offset and
nonlinear temperature dependency of VBE are the two dominant limiting factors for
achievable precision of a typical CMOS bandgap reference. This is because these two error
sources are non-PTAT and cannot be removed by a single temperature trim [17]. They
achieved high accuracy by eliminating these two non-PTAT errors with the use of chopping
and higher-order curvature correction techniques.
13
Table 2.1 Error sources in a typical CMOS BGR
Many high-order temperature compensation approaches for reducing the TC have
been investigated. Ivanov, et al., [13] proposed a second-order Taylor curvature
compensation, and A. Bermak, et al., [14] explored the silicon bandgap-narrowing effect of
BJT curvature reduction to perform residual curvature correction. Structures based on
piecewise-linear curvature compensation have also been investigated [2], [15]. The
piecewise compensation proposed in [15] added one more logarithmic curvature term to the
conventional exponential curvature for further reduction of TC at higher temperature. Some
researchers propose canceling high-order nonlinearities by generating a curve with high-
order temperature coefficient characteristics opposite to those of bipolar transistors. For
example, [16] utilized MOS transistors operating in weak inversion and [18] utilized a
current mirror to create a curvature-up bandgap reference, then added it to a conventional
curvature-down bandgap reference.
In most high-order compensation techniques, low temperature drift is achieved by
canceling the temperature nonlinearity of VBE and making the temperature coefficient zero at
14
a given reference temperature Tr , resulting in an output voltage with constant term equal or
proportional to VGO plus a term of Tr, where VGO is the band gap voltage of the silicon
extrapolated at 0K. In this chapter, we will present a voltage reference generator targeted at
extracting the silicon bandgap VGO from the temperature characteristic of the base-emitter
voltage in a bipolar transistor. Since VGO is a well-characterized, temperature independent
components [19], the proposed reference generator can achieve a temperature coefficient
smaller than 1ppm (termed sub-ppm) when certain mismatches and offsets are accurately
trimmed using existing methods. The essence of the proposed VGO extraction is to create a
voltage proportional to Tln(T) since it contains all the high-order nonlinearity in the VBE.
Even though many people have recognized this, there is no existing research showing that a
pure Tln(T) term was generated. In this work, we created a self-stabilized bootstrap structure
and when a set of equations are satisfied, we simultaneously obtain the nonlinear Tln(T) term
and have the voltage and current to be constant over a wide temperature range which means
the VGO extraction is achieved.
This research is focusing on investigating the fundamental theoretical efficacy of
realizing the VGO extraction. Analytical constraints for generating a reference voltage
proportional to the VGO are derived when the non-ideal error sources are ignored. Then the
effects of several non-ideal error sources on the proposed VGO extraction are discussed. It is
shown that the VGO extraction is still theoretical achievable when these practical error sources
are taking into considerations. The proposed method is implemented in a CMOS 130nm
process. Simulation results show that the design achieves a temperature coefficient as low as
0.7ppm/°C over a temperature range from -40°C to 125°C.
15
The remainder of this chapter is organized as follows: Section 2.2 reviews several
state-of-the-art high-order temperature compensation approaches and presents the general
concept of the proposed VGO extractor. Section 2.3 explains the proposed method through
one example structure and derives analytical constraints for VGO extraction. Section 2.4
discusses the effects of several error sources on the proposed method. Section 2.5
demonstrates the effectiveness of the method by implementing the design in a 130nm
process. Finally, conclusions are drawn in Section 2.6 .
2.2 Curvature Compensation and General Concept of VGO extractor
In this section, the analytical expression of the temperature characteristic of VBE will
be introduced first. Then, several state-of-the-art high-order temperature compensation
approaches for reducing the temperature coefficient of a reference generator will be reviewed
to motivate the VGO extraction. Finally, the general concept of the proposed VGO extractor
will be presented.
2.2.1 Temperature Characteristic of VBE
As an effective way to reducing the temperature coefficient of a VBE-based reference
generator, high-order curvature compensation has been widely investigated and employed in
the high-precision reference. In these high-order compensation techniques, low temperature
drift is achieved by canceling the temperature nonlinearity of VBE. To better understand the
details of the different types of curvature compensation and motivate the proposed method,
let us discuss the temperature characteristic of VBE first.
In 1980, Tsividis [4] proposed a well-recognized analytical expression for predicting
the temperature behavior of the IC-VBE characteristics of a BJT. Derived from the collector
current expression, the 𝑉𝐵𝐸 of a BJT transistor can be expressed as
16
( )( ) ( ) ln ln
( )
CBE GOr BE r GOr
r r C r
I TT kT T kTV T V V T V
T q T q I T
= + − − +
(2-1)
and if the collector current is proportional to 𝑇𝛿, (2-1) can be simplified as
( )( ) ( ) lnBE GOr BE r GOr
r r
T kT TV T V V T V
T q T
= + − − −
(2-2)
where 𝜂 is a process-dependent parameter and the typical value of 𝜂 is around 2~4. T is the
absolute temperature in Kelvin and 𝑇𝑟 is a reference temperature. Room temperature is
usually used as the reference, but it is not necessary. It should be pointed out that 𝑉𝐺𝑂𝑟 is the
extrapolated bandgap voltage of silicon at 0K which is the quantity we would like to extract.
IC is the collector current of the BJT.
Apply Taylor expansion to equation (2-2) at 𝑇 = 𝑇𝑟, we can express the VBE as (2-3),
( )( ) ( )rBE GOr
kTV T V T c T
q
= + − − +
(2-3)
where ( ) rGOr
kTV
q + − is the constant term, 𝜆 is the linear term and 𝑐(𝑇) is the curvature
term in which the curvature 𝑐(𝑇) is
( )( ) ( ln )r
r
k Tc T T T T
q T = − − − (2-4)
Figure 2.2 gives an example curvature in the GlobalFoudries 130nm process where
the prototype circuit is implemented in this research. Note that the curvature leads to about
10ppm/oC temperature coefficient from -40oC to 125oC in the conventional first-order BGR.
Therefore, this is a need to reduce or cancel the curvature for high precision reference
generator in general.
17
Figure 2.2 Example of curvature in the GlobalFoudries 130nm process
2.2.2 Curvature Compensation Approaches
To compensate the curvature in the VBE, many high-order temperature compensation
approaches have been studied. Three of them are used as an example for the purpose of
illustration.
In Bermak’ method, [14] the silicon bandgap-narrowing effect of BJT was explored
for curvature reduction. A simplified structure is illustrated in Figure 2.3. The main point of
this method is to bias the base of a BJT Q0 with a PTAT current. With the known Gummel-
Pool model, the temperature characteristic of the BJT current gain can be expressed as
0( )
XTB
r
TT
T
=
(2-5)
where 0 is the current gain at the reference temperature and XTB is the beta temperature
exponent.
-50 0 50 100 150-3
-2.5
-2
-1.5
-1
-0.5
0
Temperature(oC)
Curv
atu
re(m
V)
Curvature for = 3.282 and =1
18
Vce0
Vbe0(T)
Ib0(T)
Mp0
(T)Ib0(T)
Q0
Figure 2.3 Bermak’ curvature correction technique: bias a BJT base with a PTAT current
As a result, the collector current of Q0 will be proportional to 𝑇𝑋𝑇𝐵+1 . Applying
equations (2-2) and (2-5), the curvature of this structure can be written as
( )( ) ( ln )1 TB r
r
k Tc T T T T
qX
T − −−= − (2-6)
In (2-6), if 𝜂 and (1+XTB) are close to zero, the curvature will be approaching zero
and thus curvature reduction is accomplished. However, the effectiveness of the method will
be depended on process since both 𝜂 and XTB are process parameters. Furthermore, for the
purpose of VGO extraction, it requires the term (𝜂 − 1 − 𝑋𝑇𝐵) to be equal to zero which is
not easy due to the lack of the controbility of 𝜂 and XTB.
Structures based on piecewise-linear curvature compensation have also been
investigated [2], [15]. The piecewise compensation method proposed by M. Yu in [2] can be
illustrated with the simplified schematic of Figure 2.4(a). The major idea is to add a
logarithmic curvature term to first-order BGR for high-order curvature compensation. In this
method, the resistor R5 is biased with a PTAT current. The voltage across R5 is used to bias
the VGS of a PMOS transistor M1. Different types of resistor are used for R5 from the resistors
of the BRG core (R3, R4 are shown).
19
ICTAT IPTAT
IPTAT
INLR3
R4
R5
M1
VDD
VREF
First-order BRG CorePiecewise curvature
generator
First order BGR
V
T
Curvature corrected BGR
T1
Piecewise nonlinear
curvature corrected
voltage
(a) (b)
Figure 2.4 Curvature compensation by adding a logarithmic term (a) simplified schematic R3-R4=Rtype1 and
R5= Rtype2 (b) curvature compensation illustration
As a result, a nonlinear current INL will be generated at the drain of M1:
_ 1
_ 1
2
_ 1
0
exp( )
SG M THP
NL SG M THP
SG M THP
V V
I T V V
T V V
=
(2-7)
The generated nonlinear current INL will then be summed with the PTAT and CTAT
at node VREF. A curvature-corrected reference will be created at VREF and the compensation
effect is shown in Figure 2.4(b).
A similar method was developed by Renesas Electronics Corporation [24]. The
simplified schematic is shown in Figure 2.5 (a). In this method, the nonlinear current INL for
compensation is generated through a voltage to current converter (A2, Q3 and R6). INL can be
expressed as
2
32
0 ( )
( )6
NL REFC BE
T T
I V VT T
R
= −
(2-8)
20
Similarly, the generated nonlinear current INL will then be summed with the PTAT
and CTAT at node VREF to create a curvature-compensated voltage (Note: this is simplified).
ICTAT IPTAT
INL
R3
R4
VDD
VREFC
First-order BRG CorePiecewise curvature
generator
R6
VREF
Q3
V
TT2
T1
INL
VREF
VREFC
(a) (b)
INL
A2
Figure 2.5 Curvature compensation by adding the piecewise linear current (a) simplified schematic (b)
curvature compensation illustration
2.2.3 VGO Extraction in General
The conventional curvature correction techniques attempt to cancel the temperature
nonlinearity of VBE, resulting in an output voltage with a constant term equal or proportional
to VGO plus a high order term of temperature.
The question now arises: is it possible to remove both the T term and 𝑇ln 𝑇 of VBE of
(2-2) so that the temperature-independent term VGO can be extracted? Huijsing, et al., in [7]
first attempted to obtain a VGO-related output voltage using a standard bipolar process. Under
certain assumptions, they successfully derived a Vref proportional to VGO, and achieved
4ppm/°C in the temperature range 0 to125°C. In this work, we will discuss the VGO extraction
in a more geneal way and carfully investigate strategies and analytical constraints for VGO
extraction.
.
21
In general, a VGO extractor can be achieved through three or more different diodes,
and Figure 2.6(a) illustrates using multiple diodes to extract the VGO. Another
implementation uses the parasitic vertical BJT [25] of a P-type MOSFET as shown in Figure
2.6(b). This is low cost that can easily be integrated in a CMOS process.
gnd
Q1
V1 V2
vdd vdd
I1 I2
gnd
Q3
V3
vdd
I3
Q2
A AnA
gnd
nA A
Q1 Q2
V1 V2
vdd vdd
I1 I2
gnd
A
Q3
V3
vdd
I3
gnd
(a) (b)
Figure 2.6 Illustration of using (a) three diodes (b) three BJT connected as diodes, to extract the VGO
In Figure 2.6, Q1, Q2 and Q3 are three diodes, or BJTs connected as diodes, with area
ratios equal to n:1:1. I1, I2 and I3 are the currents injected into these three diodes. We will
make I1, I2, and I3 have properties such that 𝐼1 = 𝐹1 ∙ 𝑇𝛿1, 𝐼2 = 𝑚 ∙ 𝐼1, and 𝐼3 = 𝐹2 ∙ 𝑇𝛿2 ,
where m is the ratio of the currents I2 and I1, T is the absolute temperature in Kelvin, F1 and
F2 are two temperature independent coefficients, and 𝛿1 and 𝛿2 are two constant integer
numbers (𝛿1 ≠ 𝛿2). Under these conditions, the following relationships among the voltages
V1, V2 and V3 can be expressed as
2
2 1
3 2
ln
( , )
ln
BE GOr
PTAT
NL
V V V aT bT T
V V V g m n T
V V V cT dT T
= = + +
= − = = − = +
(2-9)
22
where m and n are design variables, g(m, n) is a function of m and n, and a, b, c, and d are
temperature-independent parameters that can be expressed using the following set of
equations
( )
( )
( )
( )
2
1
1
3 2
2 1
2 1
( )ln
( ) ( )ln
BE r GOr
r
r
BE r BE r
r
r
V T V ka T
T q
kb
q
V T V T kc T
T q
kd
q
−= + −
= − −
− = + − = −
(2-10)
Based on the above relationships, a linear combination resulting in a value of VGOr
can be configured. Let
1 2 3GOr BE PTAT NLV AV A V A V= + + (2-11)
leading to
1 1 2 3 1 3( , ) ln( )GOr GOrV AV A a A g m n A c T Ab A d T T= + + + + + (2-12)
Solving for equation (2-12), we obtain:
1
2
3
1
1
( , )
A
bcA a
g m n d
bA
d
=
= −
= −
(2-13)
It can be seen that the voltage given in (2-12) will be equal to VGOr , i.e, the VGOr
extraction will be achieved, when the equations given by (2-13) are satisfied. Note that in (2-
13), we can multiply A1, A2 and A3 by a coefficient 𝛼, resulting in a voltage proportional to
VGO, i.e., 𝛼 VGO.
2.2.4 Discussion
In the above mentioned VGO extraction, the temperature profile of I1, I2 and I3 is
important. Especially, we need I3 to have constant temperature power. There is no good way
23
gnd
nA A
Q1 Q2
V1 V2
vdd vdd
R1 ΔVBE
I1 I2
Figure 2.7 Generation of PTAT current using two BJTs
to generate the Tn when n is large than one. In order to achieve this, the biggest challenge is
that one needs to have a current to be constant which has the same difficulty level to have a
constant voltage. In this work, we realized it by creating a self-stabilized bootstrap structure.
In this structure, when a set of equations are satisfied, we simultaneously obtain the nonlinear
Tln(T) term and have the voltage and current to be constant over a wide temperature range
which means the VGO extraction is achieved.
2.3 One Implementation of Proposed Voltage Reference Generator
In this section, one implementation of the proposed voltage reference generator based
on VGO extraction will be introduced, and analytical conditions investigated, after which one
implementation of the proposed method will be presented.
2.3.1 Generation of Nonlinear Term Containing TlnT
Since in the process to be used, only PNP substrate BJT is accessible, in the following
analysis we will use PNP in the examples and assume collector current to be equal to emitter
current.
In standard bandgap topology, two BJTs are utilized to create a PTAT. The
generation of PTAT current using two BJTs is shown in Figure 2.7. If standard mechanisms
are applied to force Vo1=Vo2 and I1=I2, the voltage across the resistor R1 will be a PTAT
24
gnd
PTAT TI
A A
Q2 Q3
VNL
vdd vdd
Figure 2.8 Generation of nonlinear term containing TlnT
voltage, i.e., ∆𝑉𝐵𝐸 = 𝑉𝑇 ln 𝑛 , where 𝑉𝑇 is the thermal voltage, n is the ratio of the emitter
areas between Q1 and Q2. The resulting current in R1 is a PTAT current. A linear
combination of the PTAT voltage and CTAT voltage VBE can lead to first-order temperature
compensation. For low-voltage operation, the two voltages, ∆𝑉𝐵𝐸 and VBE will first be
converted into two currents using dividing resistors before being combined [9].
To achieve a low temperature coefficient, the nonlinear temperature dependence of
VBE must be considered. From (2-2), the nonlinearity of VBE is dominated by the term 𝑇ln𝑇.
While expressing VBE in a Taylor series and canceling the high-order T terms [15] is one
solution to achieve high-order temperature compensation, another approach is to generate a
nonlinear term proportional to 𝑇ln𝑇 [9], [16], [20]. Figure 2.8 illustrates the concept of
generating a nonlinear term containing TlnT using two BJTs Q2 and Q3. Suppose Q2 is biased
at a given PTAT current and Q3 is biased at a temperature-independent (TI) current. Then,
according to (2-2), the VBE of Q2 and Q3 can be written as (2-14) and (2-15) respectively,
25
gnd
nA A
Q1 Q2
V1 V2
vdd vdd
R1
I1 I2 TI
A
Q3
vdd
INL
PTAT
CTAT
PTAT
R2
R3
TI
vdd
R4
VrefVNL
Figure 2.9 Conceptual generation of temperature independent current
( )2 2( ) ( ) 1 lnBE GOr BE r GOr
r r
T kT TV T V V T V
T q T
= + − − −
(2-14)
( )3 3( ) ( ) 0 lnBE GOr BE r GOr
r r
T kT TV T V V T V
T q T
= + − − −
(2-15)
The voltage difference VNL is obtained by subtracting VBE3 from VBE2:
3,2 3 2( ) ( ) lnNL BE BE r BE r
r r
T kT TV V V T V T
T q T
= = − +
(2-16)
Note that the term ∆𝑉𝐵𝐸3(𝑇𝑟) − ∆𝑉𝐵𝐸2(𝑇𝑟) is not equal to zero and should not be
ignored as in [5], [9] when deriving accurate relationships for achieving VGO extraction, as
will be discussed in detail next.
2.3.2 VGO Extraction
Figure 2.9 illustrates the proposed concept for achieving the VGO extraction.
Transistors Q1 and Q2 are configured as in Figure 2.7 to generate a PTAT current, and
transistors Q2 and Q3 are set up as in Figure 2.8 to produce the nonlinear voltage VNL that
contains the term 𝑇ln𝑇. Resistor R3 is utilized to convert VNL to nonlinear current INL. A
buffer is placed between R3 and the emitter of Q3 such that INL will not affect the current
26
flowing into Q3. This is necessary because, as one requirement for remaining (2-16) valid, we
must ensure that IQ3 is temperature-independent. Resistor R2 is utilized to generate the CTAT
from VBE2. The PTAT current, CTAT current, and nonlinear current INL are summed at node
V2, resulting in a total current I2. Since I1=I2, equal currents of current CTAT and INL should
be drawn from node V1 to ensure that IQ2=IQ1=PTAT (how this can be achieved is not
included in Figure 2.9 for simplicity). We will now show how to determine appropriate ratios
among resistors R1, R2, and R3 to make I2 temperature-independent.
Current I2 is mirrored and applied to resistor R4 to generate output voltage Vref, that
can be expressed as
4 1,2 2 2,3
1 2 3
4 2 22 2,3
2 1 3
1 1 1
ln .
ref BE BE BE
BE BE
V R V V VR R R
R R RkTn V V
R q R R
= + +
= + +
(2-17)
From (2-2), (2-16), and (2-17), the proper ratios of 𝑅2/𝑅1 and 𝑅2/𝑅3 for VGO
extraction can be derived. Specifically, we treat T and Tln(T) as two independent basis
functions. Then take the derivative of Vref with respect to T and Tln(T); evaluate the
derivatives at T=Tr and set as zero i.e., 0, and 0ln
ref ref
T Tr T Tr
V V
T T T= =
= =
; slove the eqations to
obtain the resistor ratios as (2-18) and (2-19).
2
3
1R
R= − (2-18)
2 3 22
1
( ) ( ) ( ) ( 1).
ln
GOr BE r BE r BE r
r
V V T V T V TR
kTRn
q
− + − −= (2-19)
When (2-18) and (2-19) are satisfied, (2-17) is reduced to (2-20)
27
R1R2B
VA VB
I1I2
vdd
R2A
Vo
gnd
Q1 Q2
R4
VRef
I4
1
I3
Q3
R3A
R3BINL
INL
n 1
A1
A2
Figure 2.10 One implementation of the proposed method
4
2
ref GOr
RV V
R= (2-20)
It can be seen that the reference voltage in (2-20) is proportional to VGOr. Strictly speaking,
while the value of VGOr is dependent on Tr [4], but it is temperature-independent over a very
wide temperature range (e.g., -40 °C -125°C), so VGO=VGOr is assumed in many references
[5], [14] and frequently also in practice.
One possible implementation of the proposed method is shown in Figure 2.10. The
basic structure of this implementation is similar to that given in [9], but more constraints are
posed for the purpose of extracting VGO, and the proposed method is not limited to this
structure only. In Figure 2.10, currents I1 - I4 are equal and will be temperature-independent
when the resistor ratios are properly adjusted. Resistors R2A, R2B are equal and R3A, R3B are
equal. When resistors are properly sized, (2-20) gives the theoretical output voltage at Vref
where the overall TC should be near zero.
Notice this structure is only one implementation of the proposed method. One can
easily extend the general VGO ideal to various bandgap structures.
28
Referring to the discussion of Section 2.3 , the practical TC of the circuit increases
with non-ideal factors such as resistor/current mirror mismatches, opamp offset, TC of
resistors (TCR) and etc. In the following subsection, we will talk about the effects of several
error sources based on the example circuit shown in Figure 2.10, and discuss the theoretical
possibility of reducing or removing these non-ideal error sources.
2.4 Discussion of Non-Ideal Error Source
As we emphasized in the introduction, this research is focusing on investigating the
fundamental theoretical efficacy of realizing the VGO extraction. So far, we have shown that
without the consideration of non-ideal source, we are able to generate a reference voltage
proportional to the VGO. In this section, we will derive the effects of several error sources on
the proposed VGO extraction and show the VGO extraction is still theoretical achievable when
these practical error sources are taking into considerations.
We will focus on the non-PTAT error sources showing in Table 2.1 since it is known
that those PTAT error sources can be simply removed by a single temperature trim [17]. In
particular, we will discuss the temperature dependence of resistors (TCR), temperature
dependence of BJT current gain () and opamp offset.
2.4.1 Temperature dependence of resistors (TCR)
For resistors, one good thing is the ratios instead of the absolute values of resistors are
what really matter. Thus, a typical design convention is to use the same type of resistors with
the same TCR. However, even if the same type of resistors is utilized, the TC of the output
voltage may still be affected. To illustrate this, suppose all the resistors R1-R4 have some
TCR with value 𝜆. If we still want Vref to be approximately equal to 𝑅4/𝑅1 ∗ 𝑉𝐺𝑂𝑟, then I4
should not be ideally temperature-independent and indeed we need to intentionally make
29
𝐼4(𝑇) = 𝑉𝑟𝑒𝑓/𝑅4(𝑇) . In this case, (2-2) is no longer valid, and we should use (2-1) to
express VBE3 with
3
3
( ) 1
( ) 1 ( )r r
I T
I T T T =
+ − (2-21)
Based on this, (2-18) and (2-19) should be modified to become:
2
2 223
1( 1)
1
1 1 22
r
r rr
r
R T
R T TT
T
−−
= =+ −
+ −
(2-22)
( )2 3 2 2 2
2
1
1( ) ( 1) ( ) ( ) 1
1 2
ln
r rGOr BE r BE r BE r r
r r
r
kT kTV V T V T V T T
q q T TR
kTRn
q
−− + − + − − + + − =
(2-23)
These ratios will result in high-order temperature terms at Vref, and therefore, for applications
requiring extremely low TC, resistors with very low TCR are required.
2.4.2 Temperature dependence of BJT current gain
When a substrate BJT is used, it is actually biased through the emitter. Note that the
collector current of a BJT is a fraction of its emitter current where they are related by :
1
=
+ (2-24)
When temperature characteristic of is taking into consideration, equation (2-1) then
should be expressed as
constant
( ) ( ) ln ln
( )= ( ) ln
( )
( ) ( )
( ) ( )BE
E
r
GOr BE r GOr
r r
B
E r
E
r
T I TT kT T kTV T V V T V
T q T IT q
kT
q
T
TV T
T
=
= + − − +
+
(2-25)
Substitute the temperature characteristic of the showing at (2-5) into (2-25), we can
obtain [21]
30
0
constant
0
(1 )
( ) ( ) ln
1r
r
TB
TB
X
BE BE XT
T
T
TkTV T V T
q
=
+
= +
+
(2-26)
This introduces additional curvature in the VBE(T) and it is only significant for small
values of 0 and large values of XTB [21].
In order to look into the effect of XTB on VBE(T), treat XTB as the variable in (2-26) and
take the Tylor expansion at XTB=0, we can obtain
constant
0
1( , ) ( , ) ln
(1 )r
BE BE
T
T
kV T XTB V T XTB T XTB
q =
= +
+ (2-27)
In (2-27), it can be seen that the coefficient of XTB is related to the basis function
Tln(T). In another word, it does not introduce new high order terms except T and Tln(T). As a
conclusion, the error induced by the temperature dependence of BJT current gain can be
trimmed out by adjusting the resistor ratios of 𝑅2/𝑅1 and 𝑅2/𝑅3.
2.4.3 Opamp offset
The offset of the opamp is another important error source which affects the derivation
of the resistor ratios in the VGO extraction. In the example circuit of Figure 2.10, two opamps
have been used, i.e., A1 and A2. To simplify the illustration, we will separately analyze them.
When the opamp offset of A2 is taking into consideration, the equivalent circuit can
be shown as Figure 2.11.
In this case, (2-17) needs to be modified as
4 1 1 12 2,3 2
1 2 3 3
lnref BE BE OS
R R R RkTV n V V V
R q R R R
= + + −
(2-28)
31
+ −
R1R2B
VA VB
I1I2
vdd
R2A
Vo
gnd
Q1 Q2
R4
VRef
I4
1
I3
Q3
R3A
R3BINL
INL
n 1
A1
A2
Vos2
VC
Figure 2.11 Equivalent circuit when opamp offset of A2 is injected
Now, we repeat the procedure in section 2.3.2 for deriving the resistor ratios of
𝑅2/𝑅1 and 𝑅2/𝑅3. If VOS2 has no temperature drift, the resistor ratios of (2-18) and (2-19)
are still valid. This is because the eqation set of 0, and 0ln
ref ref
T Tr T Tr
V V
T T T= =
= =
will remain
the same if 𝜕𝑉𝑂𝑆2
𝜕𝑇= 0.
If VOS2 has a temperature drift, things will be slightly different. For simplicity,
suppose VOS2 has a constant temperature coefficient following the above-mentioned
procedure, we can obtain the following modified ratio for R2/R1
2 3 22
1
( ) ( ) ( ) ( 1) ( 1).
ln
GOr BE r BE r BE r r
r
V V T V T V T TR
kTRn
q
− + − − + −= (2-29)
In summary, the offset of opamp A2 can be trimmed out by adjusting the resistor
ratios even it has temperature drift.
When the opamp offset of A2 is taking into consideration, the equivalent circuit can
be shown as Figure 2.12.
32
+−
R1R2B
VA VB
I1I2
vdd
R2A
Vo
gnd
Q1 Q2
R4
VRef
I4
1
I3
Q3
R3A
R3BINL
INL
n 1
A1
A2
Vos1
VC
Figure 2.12 Equivalent circuit when opamp offset of A1 is injected
In this case, (2-17) could not be modified straightforwardly. By writing the node
equation at VA and VB, we can obtain
2 1 2,1 1 2,3 1
2 1 3
2 2 2,3
2 3
4
1 1 1( ) ( ) ( )
1 1( )
BE OS BE OS BE OS
BE Q BE
ref
I V V V V V VR R R
I V I VR R
V IR
= − + − + −
= + +
=
(2-30)
From (2-30), the current flowing into Q2 will be
2 2,1 1
1 1 2 3
1 1 1 1( )Q BE OSI V V
R R R R= − + + (2-31)
It can be seen IQ2 is no longer a PTAT current which violates the original assumption.
It is worth to point out that to deal with the offset, existing offset techniques such as
chopping methods can be easily combined with the proposed method.
33
Figure 2.13 Bandgap voltage versus absolute temperature and the tangent line for Tr=300K
2.5 Simulation Results
This section will demonstrate the capability of the proposed method of achieving a
low temperature coefficient. The circuit shown in Figure 2.10 was implemented in the
GlobalFoundries 130nm process, and t. The bandgap voltage versus absolute temperature is
shown in Figure 2.13. The tangent line for Tr=300K is also shown as a red dashed line from
which we can obtain the extrapolated value of VGO, i.e., VGO=VGOr =1.148V. P+ Poly resistor
with a positive TC1 and negative TCend is utilized, and it can be shown that when the W/L
ratio of the unit resistance is chosen to be 1u/5u, the TCR is about 0.5ppm/°C. In this design,
R1=18.16k, R2A=R2B=158.60k, R3A=R3B=48.51k, and R4=93.29k. The widely used 7-
transistor opamps are used as buffers. The resulting current consumption of this design is
103.7uA.
Figure 2.14 shows the simulation results for the output voltage over the temperature
34
Figure 2.14 Output voltage over process
(a) (b)
Figure 2.15 Output voltage over process with (a)one-point and (b)two-points calibration
0 50 100
Temp(oC)
664.8
664.85
664.9
664.95
665
665.05
Vo(m
V)
Vo over Corner after Trim
tt
fs
sf
ff
ss
range 40°C to 125°C for five different process corners. The nominal TC is about 0.25ppm/°C
and worst-case TC value is 2ppm/°C. The output voltage level is about 665mV,
approximately equal to 𝑅4/𝑅1 ∗ 𝑉𝐺𝑂. Figure 2.15 shows one-point and two-point calibration
35
results that reflect a worst-case TC value of about 0.7ppm/°C.
Table 2.2 summarizes the comparison of the proposed method to the state-of-the-art
high-precision voltage reference generators. It can be seen that the proposed method has the
potential of creating a voltage reference that has qualitatively better temperature dependence.
Table 2.2 Comparison with the state-of-the-art high-precision voltage reference generators
Ref. [18] [22]
[14] [16] [23] [15] [5] [24] This
work
Year 2015 2015 2015 2014 2014 2012 2012 2012 -
Publication TCAS ISSCC
TED TCAS Electron
. Lett. TCAS JSSC VLSI
Syp.
-
Supply (V) 1.2 1.3-2.6 1.2 1.2 1.6 2.5 0.9-5.5 1.5
Power (uA) 120 4.3 36 416 25 38 3.9 103
Reference(V) 0.735 1.21 1.1402 0.767 0.495 1.285 0.6177 0.615 0.665
Temp range
(C)
-40-120 -40-120 -55-125 -40-120 -40-125 -40-100 -15-150 -50-150 -40-125
Best TC
(ppm/C)
4.2 7 4.1 3.5 6 5 3.9 5.69 0.7
Average
TC(ppm/C)
9.3 - - - - - 15.6 - -
Samples 8 - 12 8 8 5 5 31 -
PSRR(dB) -30
@100k
- -54
@100
-37
@100k
- -55
@10k
- -
Area (mm2) 0.063 0.034 0.05 0.036 0.09 0.04 0.102 0.1 0.046
Type BG BG BG BG Sub-
BG
Curvatu
re
VGO
extract
ion
Process (um) 0.13 0.13 0.18 0.18 0.028 0.5 Bi 0.35 0.13 0.13
2.6 Conclusion
This chapter proposed a voltage reference generator targeted at extracting the silicon
band-gap value VGO from the temperature characteristic of the base-emitter voltage in a
bipolar transistor. The fact that VGO is temperature independent over a very wide temperature
range makes it possible to achieve a very low temperature coefficient. Analytical constraints
that lead to strategies for creating an output voltage equal to VGO when certain mismatches
and offsets are accurately trimmed were carefully investigated. Then the effects of several
non-ideal error sources on the proposed VGO extraction are discussed. It is shown that the VGO
36
extraction is still theoretical achievable when these practical error sources are taking into
considerations. The proposed method was implemented in the GlobalFoundries 130nm
process. Simulation results show that the design can achieve temperature coefficients as low
as 0.7ppm/°C over the temperature range -40°C to 125°C.
The proposed VGO extraction has the potential of creating a voltage reference that has
qualitatively better temperature dependence. The study of the analytical constraints and
practical non-ideal error sources will enable future researches of precisely extracting the VGO
and creating extremely low temperature coefficient reference generators. This will, in turn,
benefit the high performance mixed-signal and radio-frequency systems.
37
2.7 References
[1] P. K. T. Mok and K. N. Leung, “Design considerations of recent advanced low-voltage
low-temperature-coefficient CMOS bandgap voltage reference,” in Custom Integrated
Circuits Conference, 2004. Proceedings of the IEEE 2004, 2004, pp. 635–642.
[2] J.-H. Li, X. Zhang, and M. Yu, “A 1.2-V Piecewise Curvature-Corrected Bandgap
Reference in 0.5 m CMOS Process,” IEEE Trans. Very Large Scale Integr. VLSI Syst.,
vol. 19, no. 6, pp. 1118–1122, Jun. 2011.
[3] K. Ueno, T. Hirose, T. Asai, and Y. Amemiya, “A 300 nW, 15 ppm/°C, 20 ppm/V
CMOS Voltage Reference Circuit Consisting of Subthreshold MOSFETs,” IEEE J.
Solid-State Circuits, vol. 44, no. 7, pp. 2047–2054, Jul. 2009.
[4] Y. Tsividis, “Accurate analysis of temperature effects in I/SUB c/V/SUB BE/
characteristics with application to bandgap reference sources,” IEEE J. Solid-State
Circuits, vol. 15, no. 6, pp. 1076–1084, Dec. 1980.
[5] C. M. Andreou, S. Koudounas, and J. Georgiou, “A Novel Wide-Temperature-Range,
3.9 ppm/°C CMOS Bandgap Reference Circuit,” IEEE J. Solid-State Circuits, vol. 47,
no. 2, pp. 574–581, Feb. 2012.
[6] B. S. Song and P. R. Gray, “A precision curvature-compensated CMOS bandgap
reference,” IEEE J. Solid-State Circuits, vol. 18, no. 6, pp. 634–643, Dec. 1983.
[7] M. Gunawan, G. C. M. Meijer, J. Fonderie, and J. H. Huijsing, “A curvature-corrected
low-voltage bandgap reference,” IEEE J. Solid-State Circuits, vol. 28, no. 6, pp. 667–
670, Jun. 1993.
[8] G. Rincon-Mora and P. E. Allen, “A 1.1-V current-mode and piecewise-linear curvature-
corrected bandgap reference,” IEEE J. Solid-State Circuits, vol. 33, no. 10, pp. 1551–
1554, Oct. 1998.
[9] P. Malcovati, F. Maloberti, C. Fiocchi, and M. Pruzzi, “Curvature-compensated
BiCMOS bandgap with 1-V supply voltage,” IEEE J. Solid-State Circuits, vol. 36, no. 7,
pp. 1076–1081, Jul. 2001.
[10] “LTC6655 - 0.25ppm Noise, Low Drift Precision References - Linear Technology.”
http://www.linear.com/product/LTC6655.
[11] “ REF5050 | Series Voltage Reference | Voltage Reference | Description &
parametrics.” http://www.ti.com/product/REF5050.
[12] “ MAX6126 Ultra-High-Precision, Ultra-Low-Noise, Series Voltage Reference -
Maxim.” http://datasheets.maximintegrated.com/en/ds/3623.pdf.
38
[13] R. Oberhuber, R. Prakash, and V. Ivanov, “A 1 ppm/°C bandgap voltage reference with
new second-order Taylor curvature compensation,” in 23rd IEEE International SOC
Conference, 2010, pp. 71–76.
[14] B. Wang, M. K. Law, and A. Bermak, “A Precision CMOS Voltage Reference
Exploiting Silicon Bandgap Narrowing Effect,” IEEE Trans. Electron Devices, vol. 62,
no. 7, pp. 2128–2135, Jul. 2015.
[15] Z. Zhou et al., “A 1.6-V 25-µA 5-ppm/ C Curvature-Compensated Bandgap Reference,”
IEEE Trans. Circuits Syst. Regul. Pap., vol. 59, no. 4, pp. 677–684, Apr. 2012.
[16] B. Ma and F. Yu, “A Novel 1.2–V 4.5-ppm/°C Curvature-Compensated CMOS Bandgap
Reference,” IEEE Trans. Circuits Syst. Regul. Pap., vol. 61, no. 4, pp. 1026–1035, Apr.
2014.
[17] G. Ge, C. Zhang, G. Hoogzaad, and K. A. A. Makinwa, “A Single-Trim CMOS
Bandgap Reference With a 3σ Inaccuracy of ±0.15% From −40°C to 125°C,” IEEE J.
Solid-State Circuits, vol. 46, no. 11, pp. 2693–2701, Nov. 2011.
[18] Q. Duan and J. Roh, “A 1.2-V 4.2- High-Order Curvature-Compensated CMOS
Bandgap Reference,” IEEE Trans. Circuits Syst. Regul. Pap., vol. 62, no. 3, pp. 662–
670, Mar. 2015.
[19] W. Bludau, A. Onton, and W. Heinke, “Temperature dependence of the band gap of
silicon,” J. Appl. Phys., vol. 45, no. 4, pp. 1846–1848, Apr. 1974.
[20] G. Bernardinis, “Adjustable second-order-compensation bandgap reference,”
US8547165 B1, 01-Oct-2013.
[21] M. A.P. Pertijs and J. H. Huijsing, “Precision temperature sensors in CMOS
technology”, Springer, 2006
[22] G. Maderbacher, S. Marsili, M. Motz, T. Jackum, J. Thielmann, H. Hassander, H.
Gruber, F. Hus, and C. Sandner, “5.8 A digitally assisted single-point-calibration CMOS
bandgap voltage reference with a 3 #x03C3; inaccuracy of #x00B1;0.08% for fuel-gauge
applications,” in Solid- State Circuits Conference - (ISSCC), 2015 IEEE International,
2015, pp. 1–3.
[23] D. F. Bowers and E. J. Modica, “Curvature-corrected low-noise sub-bandgap reference
in 28 nm CMOS technology,” Electronics Letters, vol. 50, no. 5, pp. 396–398, Feb.
2014.
[24] S. Sano, Y. Takahashi, M. Horiguchi, and M. Ota, “A sub-1V 3.9 uW bandgap reference
with a 3 inaccuracy of +-0.34% from -50C to +150 C using piecewise-linear-current
curvature compensation,” in 2012 Symposium on VLSI Circuits (VLSIC), 2012, pp. 22–
23.
39
[25] W. Bludau, A. Onton, and W. Heinke, “Temperature dependence of the band gap of
silicon,” J. Appl. Phys., vol. 45, no. 4, pp. 1846–1848, Apr. 1974.
40
CHAPTER 3. AUTO-IDENTIFICATION OF POSITIVE FEEDBACK LOOPS IN
MULTI-STATE VULNERABLE CIRCUITS
A systematic method is proposed for automatically identifying positive feedback
loops (PFLs) in analog/mixed-signal circuits. The method first converts the netlist of a circuit
into a directed dependency graph (DDG) that captures critical relationships among branch
currents and node voltages. It then utilizes graph theory techniques to find all feedback loops
from the DDG and, finally, develops criteria for determining the PFLs. Since multiple states
result from PFLs, this method could identify a circuit’s vulnerability to undesigned operating
points by considering circuit structure only without need for the computation of DC
solutions. The proposed approach has been implemented as a program and simulation results
show it could identify all PFLs very robustly.
3.1 Introduction
Many basic analog circuits, such as self-stabilized bias generators, voltage and
current references, and Schmitt-triggers [1,2,3], frequently utilized as subcircuits in large-
scale circuit, are well known to sometimes possess multiple DC operating points or multiple
states. The presence of multiple states sometimes causes these circuits to fail to function as
designed [4]. Therefore it is worthwhile to verify the presence of such multiple states before
the fabrication of circuits. Unfortunately, according to [5], the commonly used simulators
provide only one solution even though multiple states may be present.
The task of identifying circuits with multiple states can be addressed in two ways: (a)
by discovering more than one operating point, or (b) by identifying certain topological
structural features. Definitely, a circuit can be claimed to possess multiple states once more
than one operating points have been found. However, the known related work [6,7,8] is
oriented toward searching for all operating points which is time-consuming for even small-
41
Figure 3.1 A feedback structure
scale circuits. The concept of developing topological criteria in helping analyze the operating
points of circuits has attracted many researchers’ attention. Nielsen and Willson
demonstrated that a necessary and sufficient condition for any transistor network to possess
more than one solution is that the topological substructure shown in Figure 3.1, termed a
feedback structure, be present [9]. Nishi derived several similar topological criteria for the
existence and uniqueness of solutions of nonlinear circuits containing controlled sources
[10]. Such theorems are very useful in structurally identifying multi-state vulnerable circuits,
especially for simple circuits where it can be done by inspection. Although a deterministic
algorithm for obtaining the complementary tree structure for Nishi’s criterion has been
proposed [11], it was still inefficient for large circuits. Also, since all of these efforts employ
diodes and bipolar junction transistors (BJTs) as nonlinear devices, these methods are not
applicable for CMOS circuits. Gajani proposed an approach [5] based on topology
partitioning for finding possible multiple solutions, enabling analysis of medium-size circuits
containing BJTs and/or MOSFETs. But no explicit feedback loop definition was provided,
and the lack of distinction between positive feedback loops and negative feedback loops
(NFLs) would increase the computation time.
In this chapter, we introduce clear definitions of PFLs and NFLs for analog/mixed-
signal CMOS circuits and bring a systematic approach to automatically identifying them. The
42
proposed method is highly efficient in determining whether a circuit, especially a large-scale
circuit, is vulnerable in terms of multiple states, by avoiding the tedious work of computing
DC solutions. Locating sub-circuits containing PFLs allows easier application of intact-loop
or broken-loop continuation methods [12].
In the next section, several definitions for feedback loops based on circuit netlist are
introduced. In section 3.3 , the procedure for identifying PFLs is illustrated by applying the
algorithm to the bootstrapped 𝑉𝑡 reference circuit described in [12]. Section 3.4 reports the
PFLs identification results for several well-known circuits in which stable multiple operating
points often occur. Section 3.5 gives the summary of this work.
3.2 Feedback Loops
In this section, we will first discuss several definitions showing how to construct a
DDG from the netlist, followed by a definition of feedback loops derived from DDGs.
The netlist of a circuit is composed of a list of the instances used in a design.
Together with each instance is an ordered list of net names with connections to its pins. An
instance can include MOSFETs, resistors, diodes or independent sources. Nets are the wires
that connect instances together in the circuit, and pins are the connection points of an
instance.
Definition 1: define a Channel as the part between two pins of any instance that
conducts current from one pin to another; in a circuit, each instance has one channel. A
channel is denoted as 𝑐(𝑛1, 𝑛2), with 𝑐 being the name of the instance and 𝑛1, 𝑛2 being the
incident nets of the two pins, e.g., 𝑀1(𝑉12, 𝑔𝑛𝑑), representing the channel of 𝑀1 , as shown
in Figure 3.2.
43
vdd
M1 M2
M3
M4 M5
V12
V21
I1 I2 V21
V12
I2I1
gnd
Figure 3.2 Inverse widlar (a) branch-current and controlling voltage (b) directed dependency graph
(a) (b)
Definition 2: define a branch in the netlist 𝑁 as a sequence of the form
𝑛𝑖0, 𝑐𝑗1(𝑛𝑖0, 𝑛𝑖1), 𝑛𝑖1, 𝑐𝑗2(𝑛𝑖1, 𝑛𝑖2), … . , 𝑐𝑗𝑘(𝑛𝑖𝑘−1, 𝑛𝑖𝑘), 𝑛𝑖𝑘
which consists of alternating nets 𝑛𝑖𝑡−1and channels 𝑐𝑗𝑡(𝑡 = 1, … , 𝑘) of netlist 𝑁 with any net
and any channel being visited at most once. The initial net 𝑛𝑖0 is the power supply net
(denoted as "𝑣𝑑𝑑") and the terminal net 𝑛𝑖𝑘 is ground (denoted as "𝑔𝑛𝑑"). The instances
contributing channels to a branch are called instances of that branch. A Branch Current (BC)
is defined as the current flowing through a branch.
For example, the left branch of the inverse widlar shown in Figure 3.2(a) can be
written as: 𝑣𝑑𝑑, 𝑀4(𝑣𝑑𝑑, 𝑉12), 𝑉12, 𝑀1(𝑉12, 𝑔𝑛𝑑), 𝑔𝑛𝑑 , where M4, M1 are the instances of
this branch and I1 is the BC.
Definition 3: consider a circuit having 𝑚 (𝑚 > 2) branches 𝐵1, 𝐵2, … , 𝐵𝑚 whose
corresponding BCs are 𝐼1, 𝐼2, … , 𝐼𝑚. Define a Controlling voltage (CV) as a voltage of any
net in 𝐵𝑗 (excluding "𝑣𝑑𝑑" and "𝑔𝑛𝑑", hereinafter the same) that controls the gate-source
voltage of any transistor of 𝐵𝑖 (𝑖, 𝑗 = 1, 2, … , 𝑚. 𝑖 ≠ 𝑗). The designation “controlling” means
44
that, in small signal analysis, a small change of this controlling voltage will lead to a change
in the gate-source voltage and thus the branch-currents 𝐼𝑖.
A CV can be found in two cases: (1) the gate of any transistor of 𝐵𝑗 connects (directly
or through resistors, hereinafter the same) to a net of 𝐵𝑖, and this gate voltage is a controlling
voltage 𝑉𝑖𝑗; e.g., 𝑉12 and 𝑉21 in Figure 3.2 2(a); (2) if the source of transistor 𝐵𝑗 connects to a
net of 𝐵𝑖, this source voltage is a controlling voltage 𝑉𝑖𝑗. This relationship is described as
having two dependencies: current-to-voltage dependency 𝐼𝑖 → 𝑉𝑖𝑗 and voltage-to-current
dependency 𝑉𝑖𝑗 → 𝐼𝑗; e.g., 𝐼1 → 𝑉12 and 𝑉12 → 𝐼2 in Figure 3.2(a).
Definition 4: A directed dependency graph is a directed graph with nodes
representing either the branch current or controlling voltage and with oriented arcs
representing the two dependencies: for voltage-to-current dependency 𝑉 → 𝐼 , there is an
oriented arc going from node 𝑉 to node 𝐼; for current-to-voltage dependency 𝐼 → 𝑉, there is
an oriented arc going from node 𝐼 to node 𝑉. The DDG of Figure 3.2(a) is shown in Figure
3.2(b).
Definition 5: given a dependency graph, a feedback loop is defined as a connected
subgraph involving at least four nodes such that each node has only one arc leaving and one
arc entering. For example, based on Figure 3.2(b), the circuit of Figure 3.2(a) has one
feedback loop: 𝐼1 → 𝑉12 → 𝐼2 → 𝑉21 → 𝐼1.
The definition of PFL requires the concept of sign, so we will define PFL in the next
section after introducing the sign of dependency.
45
vdd
M1
M2
M4 M3
R3
I1 I2
A
B
C
B
C
A
I1 I2M1 (B C gnd gnd)
M2 (A B C gnd)
M3 (A A vdd vdd)
M4 (B A vdd vdd)
R3 (C gnd)
gnd
(b)
(a)
(e)
M1 (B gnd)
M2 (A C)
M3 (A vdd)
M4 (B vdd)
R3 (C gnd)
(c)
B1: vdd, M4, B, M1, gnd
B2: vdd, M3, A, M2, C, R3, gnd
(d)
Figure 3.3 Bootstrapped Vt reference circuit (a) schematic (b) netlist (c) channels list (d)
branches (e) directed dependency graph
3.3 PFLs Identification
In this section, the procedure of identifying PFLs will be presented. First, how to
obtain BC and CV are presented. This is followed by a description of constructing a DDG
and identifying PFLs from DDG.
3.3.1 Analyze the Netlist
The netlist representation of a circuit is chosen for the algorithm. The most common
way for representing the circuit netlist is 𝑁(𝑉, 𝐸(𝑉)) with𝑉 = 𝑉1, 𝑉2, 𝑉3, … , 𝑉𝑛 being a set
of n instances and 𝐸(𝑣) = (𝑒1, 𝑒2, 𝑒3, … , 𝑒𝑚), 𝑚 = |𝑣| being the incident nets of
instance 𝑣(𝑣 ∈ 𝑉) [13]. Here, |𝑣| stands for the number of pins of 𝑣. For example, |𝑣| =
2 for resistors and diodes that are two-pin instances and |𝑣| = 4 for MOSFETs since they
46
are modeled as four-pin instances. Figure 3.3(b) shows the netlist of the bootstrapped 𝑉𝑡
reference circuit shown in Figure 3.3(a). It’s a list of the instances used in the schematic
followed by their incident nets. Note that the incident nets of MOSFET have the following
ordering: drain, gate, source, and body, and it is assumed that the body of a PMOS is
connected to "𝑣𝑑𝑑" and body of an NMOS is connected to "𝑔𝑛𝑑".
3.3.2 Determine the Channel List
The channel list can be represented by 𝑁(𝑉, 𝐶(𝑉)) with 𝐶(𝑉) = 𝑐(𝑛1, 𝑛2) being the
channel of instance 𝑣 that can be derived from 𝐸(𝑣). Note that, when |𝑣| = 2, 𝐶(𝑣) is
equivalent to 𝐸(𝑣), and when |𝑣| ≥ 2, the only type of instance of concern is that of a
transistor. For MOSFETs, the channel is between the drain and source except when the drain
and source are incident to the same net and the MOSFET is functioning like a diode; in that
case, the channel of MOSFET is between the body and source. Figure 3.3(c) shows the
channel list of Figure 3.3(a).
3.3.3 Construct DDG
To construct a graph, we have to know the nodes and edges of it. The nodes of DDG
are branch-current nodes and controlling voltage nodes and the edges are the dependencies
between the two types of nodes. Both can be obtained by processing the circuit
netlist 𝑁(𝑉, 𝐸(𝑉)).
From the channel list 𝑁(𝑉, 𝐶(𝑉)) we can search the branches between net "𝑣𝑑𝑑" and
net "𝑔𝑛𝑑". This process is similar to finding all paths between two nodes in a graph[13].
Therefore, a depth-first search algorithm[14] can be applied to obtain the branches of a
47
channel list. As an example, the branches of the channel list in Figure 3.3(c) are shown in
Figure 3.3(d).
According to definition 3, the controlling voltages can be identified by following
every branch and checking the gate-source connections of each transistor based on the circuit
netlist. There are several types of controlling voltages:
• If a source is fixed and the gate is incident to a net of any other branch, then the
gate voltage is a controlling voltage.
• If a gate is fixed and the source is incident to a net of any other branch, then the
source voltage is a controlling voltage.
• If both gate and source are incident to nets of other branches, both are controlling
voltages.
Here ‘fixed’ is defined as one net connected to "𝑣𝑑𝑑" , gnd, or an independent
source. Note that the diode-connected transistors are actually created two-terminal rectifying
devices and therefore are perceived as diodes when searching for controlling voltages. A
branch without transistors is termed a self-determining branch and no dependencies exist
between self-determining branches and other branches.
Take Figure 3.3(d) for example. Branch 𝐵1 has two transistors M4 and M1; from the
circuit netlist shown in Figure 3.3(b), we know that the gate of M4 is incident to net 𝐴 which
is a net of 𝐵2, so 𝐴 is a determining voltage and we obtain dependencies: 𝐼2 → 𝐴, 𝐴 → 𝐼1;
similarly, for M1 we have dependencies: 𝐼2 → 𝐶, 𝐶 → 𝐼1. For branch 𝐵2, since M3 is diode-
connected, it has one transistor M2 and the following dependencies can be obtained: 𝐼1 →
𝐵, 𝐵 → 𝐼2. The DDG of this circuit is shown as Figure 3.3(e).
48
3.3.4 Identify Feedback Loops and Determine The Sign
Note that the DDG is a directed graph, so detection of feedback loops from DDG can
be achieved by utilizing standard graph theory techniques [12,17]. We adopted Johnson’s
method [16] that can find all the feedback loops of a graph in time bounded by 𝑂((𝑛 +
𝑒)(𝑐 + 1)) and space bounded by 𝑂(𝑛 + 𝑒) , where there are 𝑛 vertices, 𝑒 edges and 𝑐
feedback loops.
As an example, two feedback loops can be identified for the DDG shown in Figure
3.3(e). They are:
𝐼1 → 𝐵 → 𝐼2 → 𝐴 → 𝐼1 (3-1)
𝐼1 → 𝐵 → 𝐼2 → 𝐶 → 𝐼1 (3-2)
It is concluded in [9] that the presence of a feedback structure is a necessary condition
that any transistor network must satisfy to possess the property of bistability. To provide
more insight into this necessary condition, we will define PFLs and NFLs in the following
way:
First, the sign of each dependency has to be assigned. Given a dependency Y→X,
define the sign of this dependency to be the sign of ∂y/∂x in small signal analysis.
For voltage-to-current dependency Y→X, y is the voltage of the controlling voltage
Y and x stands for the current of branch-current X. Positive dependency implies that a small
increase in this voltage will lead to a current increase, and negative dependency implies that a
small increase in this voltage will lead to a current decrease. Similar arguments hold for
current-to-voltage dependencies.
The sign of dependencies can be summarized and classified into the eight categories
shown in Table 3.1.
49
_
B
A
I1 I2
_
++C
BI1 I2
+ +
_+
(a) (b)
Figure 3.4 Sign of dependencies for Figure 3.2(e) (a) the upper loop (b) the bottom loop
Applying the criterion of Table 3.1 to Figure 3.3, we can obtain the sign for each edge
of these two loops, which is shown in Figure 3.4.
Table 3.1 The Sign of Different Dependencies
Voltage to current dependency
Sign Current to voltage
dependency
Sign
𝑉𝐺,𝑃𝑀𝑂𝑆𝑎 → 𝐼 − 𝐼 → 𝑉𝑆,𝑃𝑀𝑂𝑆 −
𝑉𝐺,𝑁𝑀𝑂𝑆 → 𝐼 + 𝐼 → 𝑉𝑆,𝑁𝑀𝑂𝑆 +
𝑉𝑆,𝑃𝑀𝑂𝑆 → 𝐼 + 𝐼 → 𝑉𝐷,𝑃𝑀𝑂𝑆 +
𝑉𝑆,𝑁𝑀𝑂𝑆 → 𝐼 − 𝐼 → 𝑉𝐷,𝑁𝑀𝑂𝑆 −
𝑎 . 𝑉𝐺,𝑃𝑀𝑂𝑆 stands for the gate voltage of PMOS transistor,
Now a positive feedback loop can be defined as a feedback loop containing a positive
even number of negative dependencies, and a negative feedback loop can be defined as a
feedback loop containing an odd number of negative dependencies.
For example, Figure 3.4(a) has two negative signs and Figure 3.4(b) has one negative
sign, meaning that (1) is a PFL and (2) is a NFL. It should be pointed out the dependency
I1→B has a different sign in the two loops. That is due to the fact that in the upper loop, B is
the drain of PMOS M4, while in the bottom loop, B is the drain of NMOS M1.
50
I2I1
(a) (b)
VDD
M1
M3 M4
R1
R2
R4R3
M2
R5
M5
M7
I3
I4
M6A
D
B
CA
D
B
C
I1 I2 I3
I4
Figure 3.5 Voltage regulator (a) schematic (b) DDG
3.4 Simulation Results
In this section, we report the results of applying the proposed algorithm to the voltage
regulator and self-biased bandgap reference, circuit types where stable multiple operating
points often occur. The feedback loops are identified from the DDG. PFLs are designated by
determining the sign of each dependency for every feedback loop.
Figure 3.5 shows that the voltage regulator has three feedback loops given by: (3-3)-
(3-5)
𝐼4 → 𝐷 → 𝐼3 → 𝐶 → 𝐼4 (3-3)
𝐼4 → 𝐷 → 𝐼2 → 𝐵 → 𝐼3 → 𝐶 → 𝐼4 (3-4)
𝐼4 → 𝐷 → 𝐼1 → 𝐴 → 𝐼2 → 𝐵 → 𝐼3 → 𝐶 → 𝐼4 (3-5)
Figure 3.6 provides the dependency sign for (3-3)-(3-5), and it can be concluded that
(3-3) and (3-4) are NFL and (3-5) is PFL.
51
(a)
A
D
B
C
I1 I2 I3
I4
D
C
I3
I4
D
B
C
I2 I3
I4
(b)
(c)
+
_
+
+
+
+
_+
+
+
_ _+ +
+
+
+
+
Figure 3.6 Sign of dependencies for each loop shown in Figure 3.5(b)
Figure 3.7 is another example schematic of a self-biased bandgap reference.
M14 M15 M1 M2
M3 M4
M10
M11M12 M13
R1 R3
VA
VB
gnd
I2I3 I5
I6 I7
vdd
R2
V1
Vo
V3
M9
V2
I4
M8
M7
M5
I1
M6
Vo
Vo1
Figure 3.7 Schematic of self-biased bandgap reference
52
I1
I2
Vo1
V1 I3 I6
I7
VoVA
VB
I5V2 I4 V3
Figure 3.8 DDG of self-biased bandgap circuit shown in Figure 3.7
(a) (b)
(c)
(d)
I1
I2
Vo1
Vo
I5V2 I4 V3
I1
I2
Vo1
V1 I3
Vo
I5V2 I4 V3
I1
I2
Vo1
V1 I3 I6 VoVA
I1
I2
Vo1
I7
Vo
VB
_
+
+_
_
+ +_
+
+
_
+ _
+ _
+ _
_
++__
_
_
+_
+
+
_
_
+
+
I1
Vo
I5V2 I4 V3
(e)
+
_
++_
_
Figure 3.9 Sign of dependencies for each loop shown in Figure 3.8
53
The DDG of Figure 3.7 is shown in Figure 3.8, from which five feedback loops can be
identified and the sign of their dependencies are shown in Figure 3.9. It can be concluded that
this bandgap reference has the two PFLs shown in Figure 3.9(a)-(b) and the three NFLs
shown in Figure 3.9(c)-(e).
3.5 Conclusion
This chapter introduces a novel method for identifying all feedback loops and
determining positive feedback loops in a circuit. This method depends on the DDG that
reflects the relationships of branch currents and node voltages in the circuit. Since positive
feedback loops are the sources of multiple states, this method could verify a circuit’s
vulnerability to multiple states simply by its structure, a big advantage in terms of efficiency,
especially for large-scale analog/mixed-signal CMOS circuits. The method has been
implemented as a program and simulation results show its effectiveness and efficiency in
identifying all feedback loops and determine whether a circuit is vulnerable to multiple
states.
54
3.6 References
[1] G. C. M. Meijer and J. B. Verhoeff, “An Integrated Bandgap Reference,” Solid State
Circuits Conf. (ESSCIRC), 1975 First European, pp.40–41, 2–5, Sept. 1975.
[2] C. Zhao, J. He, S.-H. Lee, K. Peterson, R. L. Geiger and D. Chen, “Linear Vt-based
temperature sensors with low process sensitivity and improved power supply headroom,”
in Proc. IEEE Int. Symp. Circuits Systems,pp.2553–2556, May 2011.
[3] L. B. Goldgeisser, M. M. Green, “A method for automatically finding multiple operating
points in nonlinear circuits,” IEEE Trans Circuits Syst. I, vol. 52, pp776–84. 2005.
[4] Y. T. Wang, D.G. Chen, R. L. Geiger, “Practical methods for verifying removal of Trojan
stable operating points,” in Proc. IEEE Int. Symp. Circuits Systems, pp.2658-2661 May
2013.
[5] G. Gajani, A. Brambilla, and A. Premoli, "Numerical determination of possible multiple
DC solutions of nonlinear circuits," IEEE Trans Circuits Syst. I, vol. 55, pp. 1074–1083,
2008.
[6] J. F. Victor, H. M. Luis, S. R. Arturo, “Applying an iterative decomposed piecewise-
linear model to find multiple operating points,” in Proc. Europ. Conf. Circuit Theor. Des.
(ECCTD), pp. 978–981, 2007.
[7] S. Pastore, “Fast and efficient search for all DC solutions of PWL circuits by means of
oversized polyhedra”. IEEE Trans. Circuits Syst. I, vol. 58, pp. 2270–2279 , 2009.
[8] M. Tadeusiewicz, S. Hałgas, “A Contraction Method for Locating All the DC Solutions
of Circuits Containing Bipolar Transistors,” Circuits,Systems and Signal Processing, vol.
31, pp. 1159–1166, June 2012.
[9] R. O. Nielsen and A. N. Willson, “A fundamental results concerning the Topology of
transistor circuits with multiple equilibria,” Proc. IEEE, vol. 68, no. 2, pp. 196–208,
1980.
[10] T. Nishi and L. O. Chua, “Topological criteria for nonlinear resistive circuits containing
controlled sources to have a unique solution,” IEEE Trans. Circuits Syst., vol. CAS–31,
pp. 722–741, 1984.
[11] C. Mass, “Algorithmic remarks on the Nishi-Chua uniqueness criterion for electrical
networks containing controlled sources,” IEEE Trans Circuits Syst., vol. 36, pp1510-
1520
[12] H. Wen and M. M. Green, "Use of a continuation method for analyzing startup circuits,"
in Proc. IEEE Int. Symp. Circuits Systems, pp.1527–1530, May 2010.
55
[13] C. J. Alpert, A. B. Kahng, “Recent directions in netlist partitioning: a Survey,” Integr.
VLSI J., vol.19, pp. 1–81, 1995.
[14] M. Migliore, V. Martorana, “An algorithm to find all paths between two nodes in a
graph,” Journal of Computational Physics, vol. 87, pp. 231–236, March 1990.
[15] T. H. Cormen, C. E. Leiserson, R. L. Rivest, and C. Stein, Introduction to Algorithms,
2nd ed., MIT Press and McGraw-Hill, 2001, pp. 540–549.
[16] D. B. Johnson, “Finding all the elementary circuits of a directed graph,” SIAM J.
Comput., vol. 4, pp. 77–84, Mar. 1975.
[17] J.C. Tiernan, “An efficient search algorithm to find the elementary circuits of a graph,”
Communications of the ACM 13, pp. 722–726, 1970.
56
CHAPTER 4. SYSTEMATIC BREAKING-LOOP METHOD FOR VERIFICATION
AGAINST UNDESIRED OPERATING POINTS
A systematic method is proposed for automatically identifying and breaking positive
feedback loops (PFLs) in a Trojan States Vulnerable Circuit. The method first converts the
netlist of a circuit into a directed dependency graph (DDG), then partitions the DDG into
strongly connected components (SCCs). It then employs graph theory technique to detect all
PFLs and locate breakpoints for every SCC. The proposed method can identify a circuit’s
vulnerability to Trojan States only its structure, avoiding the computation of DC solutions,
and it also can provide insight on how and where to break PFLs such that break-loop
continuation methods can be applied. With Sub-Bandgap reference and widlar-Banba
examples, it is demonstrated that the proposed approach can effectively identify all PFLs and
break-points.
4.1 Introduction
Many basic analog circuits, such as self-stabilized bias generators, voltage and
current references, and Sschmitt-triggers [1-2], are well known to possess multiple DC
operating points or multiple states; and these circuits are frequently utilized as subcircuits in
large-scale circuit. The presence of undesirable stable DC operating points (hereinafter we
use the designation Trojan States or TS to stand for “undesired stable DC operating points”)
sometimes causes these circuits to fail to provide proper function [3]. Therefore it is
worthwhile to obtain awareness of the presence of Trojan States before circuit fabrication.
Unfortunately, according to [4], the commonly used simulators provide only one solution
when TS are present.
The task of identifying circuits with Trojan States can be addressed in two ways: (a)
by finding more than one stable operating point or (b) by identifying certain topological
57
structures. If using (a), it should be pointed out that there is no need to figure out all possible
operating points, since we can claim that a circuit possesses Trojan State once we found more
than one stable operating points. However, the known related work [5-7] has bren developed
to search for all operating points, a time-consuming process even for small-scale circuits. The
idea of developing topological criteria has attracted much research attention to helping
analyze the circuit operating points. Nielsen and Willson demonstrated that a necessary and
sufficient condition for any transistor network to possess more than one solution is that a
topological substructure, termed a feedback structure, be present [8]. Nishi derived several
similar topological criteria for the existence and uniqueness of the solutions of nonlinear
circuits [9]. Such theorems are very useful for structurally identifying TS-vulnerable circuits,
especially for simple circuits where it can be done by inspection. Later, a deterministic
algorithm for obtaining a complementary tree structure for Nishi’s criterion has been
proposed [10]. However, all of these efforts employ diodes and bipolar junction transistors
(BJTs) as nonlinear devices, so these methods are not applicable to CMOS circuits. In [4],
Gajani, based on topology partitioning, proposed an approach for finding possible multiple
solutions to analyzing medium-sized circuits containing BJTs and/or MOSFETs. But no
explicit feedback loop definition was provided; also, the lack of distinction between positive
feedback loops and negative feedback loops (NFLs) would increase the computation time. In
[11], an efficient break-loop homotopy method for verification against Trojan States was
proposed. It targeted searching only intervals containing TS by breaking PFLs instead of
computing operating points. However, it assumed that the PFLs were already known and
didn’t provide a systematic approach for breaking PFLs.
58
This chapter introduces a systematic approach to automatically identifying and
breaking all the PFLs for analog/mixed-signal CMOS circuits. The proposed method
constructs a directed dependency graph (DDG) from the netlist of a circuit and partitions it
into strongly connected components (SCCs). For each SCC, it then utilizes graph theory
techniques to detect all the PFLs and locate the break-points (minimum set of nodes that can
open all the PFLs if removed). The located break-points allows easier application of intact-
loop or break-loop continuation methods [11-12]. A block diagram depicting a summary of
proposed methodology is shown in Figure 4.1.
The following section illustrates an approach to constructing a directed dependency
graph from the netlist through an example of the bootstrapped 𝑉𝑡 reference described in [12].
The SCC concept is also briefly described in this section. In section III, the procedure for
PFL detection and break-points identification for each SCC is introduced. Section 4.6
reports the identifying results of PFLs and breakpoints for two circuits. Section 4.7 gives a
brief summary of this work.
Obtain the circuit netlist
Construct the Directed Dependency
Graph
Partition the DDG into SCCs
For each SCC, detect the loops and
determine the sign of each loop
Identify the break-points for each
SCC
Figure 4.1 Flow chart of proposed method
59
C
B
A1
I1 I2
(b)
A2
vdd
M1
M2
M4 M3
R3
I1 I2
B
C
gnd
(a)
A2A1
+
−
Figure 4.2 Broken PFLs for Wilson bias generator (a) Break at the schematic (b) Break at the DDG
4.2 Break-loop Homotopy Method
This section will first introduce the break-loop Homotopy method for circuits
containing PFLs and then discuss how to utilize that method to identify the presence or
absence of Trojan states.
Homotopy methods have been widely used to find DC operating points of a circuit
[10, 11]. Conventional Homotopy methods are known to suffer from time-efficiency issues,
especially when the resolution requirement is stringent. An improved break-loop Homotopy
method was proposed in [9, 12]. This method is effective and efficient for the purpose of
Trojan-state detection for three reasons: (1) It does not need to find all DC operating points.
Since whenever any solution rather than the designers’ given solution is found, the circuit
can be identified as having a Trojan state. (2) It targeted to search only for intervals
containing the operating points rather than computing exact values for operating points. (3) It
introduces a computationally-efficient contract-and-divide algorithm that dramatically
reduces computation time.
60
The break-loop homotopy method first breaks all the PFLs at circuit nodes
corresponding to all vertices in the breakpoint set of the circuit. Each circuit node identified
by this process is broken into two nodes, one serving as an input node and the other serving
as an output node. An independent voltage source is then connected to each input node and,
if the input current is not zero, a dependent current source connected to the output node. By
sweeping the independent voltage sources throughout the predetermined operating range
(e.g., ground to Vdd), the relationship between the input and output voltage at each node pair,
termed the “return map”, can be obtained. Operating points of the circuit are the points on
the return map where the input and output voltages are equal.
A Wilson bias generator will again be used as an example to illustrate the procedure.
As shown in Figure 4.2, A is chosen as the breakpoint set. The vertex A in the DDG of
Figure 4.2 is broken into two vertices: A1 and A2 as shown in Figure 4.2(b). It can be seen
that A1 has an outgoing arrow and A2has an ingoing arrow, so in correspondence with the
circuit schematic of Figure 4.2(a), node A1 serves as an input node and node A2 serves as an
output node. Node A1 in Figure 4.2(a) is then connected to a voltage source and node A2is
left floating because its input current is zero.
The return map of A2 versus A1 at two different temperatures is shown in Figure 4.3.
An interesting observation is that this circuit has only one operating point at 25 oC but will
have three operating points at 125 oC.
Note that the example shown in Figure 4.2(a) only has one positive loop so the
breaking of the loop can be determined by inspection. However, many circuits that become
large and complex due to feedback structure and smart compensation techniques may contain
61
Figure 4.3 Return map for Wilson bias generator (a) Blue: curve for VA1= VA2 (b) Red: return map
when temperature is 25oC (c) Black: return map when temperature is 125 oC
0 1 2 3 4 50
1
2
3
4
5
VA1
(V)
VA
2(V
)
Return Map for Wilson Circuit
VA2
=VA1
VA2
@ T=25oC
VA2
@ T=125oC
several positive feedback loops and determining where to break the loop is not that
straightforward, as will be further discussed in the next section.
4.3 A Multi-loop Example
In this section, a slightly more complicated example, a voltage regulating circuit by
Jullien [13], will be discussed. It should be pointed out that the feedback loops in this circuit
are nearly impossible to determine by inspection, and the circuit is ihighly vulnerable to
Trojan state that are virtually impossible to verify using existing standard methods.
The schematic of a low dropout (LDO) series voltage regulator is shown in Figure
4.4. This circuit is used to provide the power supply for a Bandgap Reference (BGR) that
also is used to generate bias voltages and tail current for an error amplifier. Note that while
there is only one PFL for each of the individual blocks, the LDO, the BGR, and theerror
amplifier, these blocks are coupled with one another, resulting in 31 PFLs and 30 NFLs
62
VBG1
VBG1
VBG2
VBG2
Charge
PumpRectifier
RF1
RF2
M15 M16
M14M13
M12M11
M10M9
M8 M7
M6RF1
CF
M19
M20
M26 M25
Q1 Q2
M3
M4
M1M2
R1
C4
M22 M24
M21 M23
M29
M28
M27
M5
R3
R2
R5
R4
R’F2
R”F2
R6 R7
VDDB
VDDHStart-up Circuit
Power-on-Reset CircuitError Amplifier
BGR Core
VDD
A
C
B
D
G
E
F
HK
L
Figure 4.4 A full CMOS Voltage regulating circuit
(found by the proposed loop-identifying algorithm). It's safe to say that the normal human
mind would not be capable of manually detecting these many loops.
Even if the designers were to be aware of the existence of these loops, deciding how
to break all those PFLs still presents a great challenge. By applying the proposed method, the
break point set can be easily found. For example, one possible set is C, G, validated by
removing node C and G in the circuit DDG and verifying that no PFLs exist in the remaining
graph. The 2D break-loop Homotopy method described in [9] was next applied to node C and
G, producing the simulation results shown as Table 1. As an example, [0.82, 0.89] means that
an operating point exists when the voltage at node C is between 0.82~089V and the voltage
at node G is between 1.35~1.45V. It can be seen that the example circuit would have a
Trojan State at 125oC if a start-up circuit were not added.
63
Table 4.1 Simulation Results of Voltage Regulating Circuit
W/wo Start-
up Circuit
Temperature
(oC) Have multi- State?
Solution Intervals for Nodes C and G
(V)
w/wo 25 No [0.82, 0.89]X[1.35, 1.45]
wo 125 Yes
[0.82, 0.89]X[1.35, 1.45]
[1.44, 1.51]X[1.35, 1.45]
[1.79, 1.86]X[1.35, 1.45]
w 125 No [0.65, 0.69]X[1.09, 1.25]
4.4 Strongly-Connected Components
In this section, we will first describe how to construct a directed dependency graph
(DDG) from the netlist of a circuit, then discuss how to decompose the DDG into strongly-
connected components (SCCs).
4.4.1 Constructing the DDG
Although some of the aspects regarding construction of the DDG have already been
described in the author’s previous work [13], to better introduce the proposed method, a
concise description of DDG construction will be given.
To create a graph, we need to obtain its nodes and edges. The nodes of the proposed
DDG include both branch-current nodes and controlling-voltage nodes, while the edges are
the dependencies between the two types of nodes. Since both the nodes and edges are
obtained through processing the circuit netlist and instance channels, a brief description of
those elements will be presented before discussing the DDG in detail.
Assume the circuit netlist is represented by 𝑁(𝑉, 𝐸(𝑉)) with 𝑉 = 𝑉1, 𝑉2, 𝑉3, … , 𝑉𝑛 being
a set of n instances and 𝐸(𝑣) = (𝑒1, 𝑒2, 𝑒3, … , 𝑒𝑚), 𝑚 = |𝑣| being the incident nets of
instance 𝑣(𝑣 ∈ 𝑉) [14]. Here |𝑣| stands for the number of pins of 𝑣 . For example, |𝑣| =
2 for resistors and diodes, two-pin instances, while |𝑣| = 4 for MOSFETs, since they are
64
modeled as four-pin instances. Figure 4.5(b) shows the netlist, a list of the instances used in
the schematic followed by their incident nets. of the bootstrapped 𝑉𝑡 reference circuit shown
in Figure 4.5(a). Note that the incident nets of MOSFET are in order: drain, gate, source and
body.
From the circuit netlist 𝑁(𝑉, 𝐸(𝑉)) we can derive the channel list 𝐺(𝑉, 𝐶(𝑉)) with
𝐶(𝑉) = 𝑐(𝑛1, 𝑛2) being the channel of instance 𝑣, defined as the path between two pins of 𝑣
that conducts current from one pin to another. Note that 𝐶(𝑉) can be derived from 𝐸(𝑣), i.e.,
when |𝑣| = 2, 𝐶(𝑣) is equivalent to 𝐸(𝑣), and when |𝑣| ≥ 2, the only type of instance of
concern is the MOSFETin which the channel is between the drain and source except when
the drain and source are incident to a same net, in which case the MOSFET functions like a
diode, and in that case, the MOSFET channel is between the body and the source. For
example, Figure 4.5(c) shows the channel list corresponding to Figure 4.5(a).
vdd
M1
M2
M4 M3
R3
I1 I2
A
B
C
B
C
A
I1 I2M1 (B C gnd gnd)
M2 (A B C gnd)
M3 (A A vdd vdd)
M4 (B A vdd vdd)
R3 (C gnd)
gnd
(b)
(a)
(e)
M1 (B gnd)
M2 (A C)
M3 (A vdd)
M4 (B vdd)
R3 (C gnd)
(c)
B1: vdd, M4, B, M1, gnd
B2: vdd, M3, A, M2, C, R3, gnd
(d)
Figure 4.5 (a) schematic (b) netlist (c) channels list (d)
branches (e) directed dependency graph
65
We now demonstrate how to search the branch-current nodes and controlling-voltage
nodes from the channel list 𝐺(𝑉, 𝐶(𝑉) as follows:
Taking the channel list 𝐺(𝑉, 𝐶(𝑉) as a graph, with a branch defined as a path
between vertex "𝑣𝑑𝑑" and vertex "𝑔𝑛𝑑" in 𝐺. For example, the branches of the channel list
of Figure 4.5(c) are shown in Figure 4.5(d). A branch is defined in this way because we want
our DDG to reveal relationships or dependencies between the current flowing in the branches
and the node voltages controlling the current. Since the process of searching the branches of
a channel list is similar to that of finding all paths between two nodes in a graph [15], a
depth-first search algorithm [16] can be directly applied.
According to [13], the controlling-voltages and the dependencies between the branch-
current and controlling-voltage can be identified by analyzing the relationships between the
current flowing in each branch and gate-source connections of each transistor.
Consider for example Figure 4.5(d). Branch 𝐵1 has two transistors M4 and M1, and
from the circuit netlist shown in Figure 4.5(b), we know that the gate of M4 is incident to net
𝐴 which is a net of 𝐵2, so 𝐴 is a controlling-voltage and we can designate the dependencies
as: 𝐼2 → 𝐴, 𝐴 → 𝐼1; similarly, for M1 we have dependencies: 𝐼2 → 𝐶, 𝐶 → 𝐼1. For branch 𝐵2,
since M3 is diode-connected, it has one transistor M2 and dependencies can be obtained
as: 𝐼1 → 𝐵, 𝐵 → 𝐼2. The DDG of this circuit is shown in Figure 4.5(e).
4.4.2 Strongly-Connected Components
A Strongly Connected Component 𝐻 of a directed graph or digraph 𝐺 is a directed
subgraph of 𝐺 such that for every pair of vertices 𝑢 and 𝑣 in 𝐻, there is a directed 𝑢 − 𝑣 path
and also a directed 𝑣 − 𝑢 path in 𝐻 [17]. By convention, the trivial graph (with only one
vertex) is strongly-connected.
66
V1 V2
V4
V3
V5 V6
e1
e2
e3
e4
e5
e6
e7
e9
e8
Figure 4.6 Example directed graph
Any directed graph can be partitioned into a set of disjoint strongly-connected
components. For example, Figure 4.5(e) is itself strongly connected. The digraph shown in
Figure 4.6 has four disjoint SCCs: 𝐻1: (𝑉1, Ø), 𝐻2: (𝑉2, Ø), 𝐻3: (𝑉6, Ø),
𝐻4: (𝑉3, 𝑉4, 𝑉5, 𝑒4, 𝑒5, 𝑒6) . To decompose a digraph G into strongly-connected
components, Tarjan [18] presented an elegant algorithm with 𝑂(𝑛 + 𝑒) running time for an
input graph with 𝑛 vertices and 𝑒 edges.
The motivations for partitioning the DDG into SCCs are: on one hand, it enhances
efficiency of the break-loop homotopy method for verification against TS, especially for
large-scale circuits, since the break-loop method can be applied to each SCC independently;
on the other hand, it improves the process of detecting break-points. This will be further
discussed in the following section.
4.5 Identify and Break PFLs
In this section, the procedure for detecting the PFLs and then breaking them for each
SCC will be discussed. We will first give a brief overview of Feedback Vertex Set concepts
and then demonstrate how to utilize this graph theory technique to identify the break-points.
4.5.1 Identity Positive Feedback Loops
Notice that sinve each SCC is a directed graph, detecting feedback loops from an
SCC can be achieved by utilizing standard graph theory techniques. We have adopted
67
Johnson’s method as described in [19] that can find all feedback loops of a graph in a time
bounded by 𝑂((𝑛 + 𝑒)(𝑐 + 1)) and space bounded by 𝑂(𝑛 + 𝑒), where 𝑐 is the number of
feedback loops. For example, two feedback loops can be identified for the DDG shown in
Figure 4.5(e). They are:
𝐼1 → 𝐵 → 𝐼2 → 𝐴 → 𝐼1 (4-1)
𝐼1 → 𝐵 → 𝐼2 → 𝐶 → 𝐼1 (4-2)
According to the criteria described in [13], (4-1) is a PFL and (4-2) is a NFL. It
should be pointed out that all trivial SCCs with |𝑉| = 1 have no loops and all non-trivial
SCCs with |𝑉| ≥ 2 have at least one loop. For example, for Figure 4.6, component 𝐻4 has
only one loop: 𝑉3 → 𝑉4 → 𝑉5 → 𝑉3.
4.5.2 Break Positive Feedback Loops
We use breakpoints to represent a minimum set of controlling-voltage nodes which
can break all the PFLs if removed in a DDG. The concept of Feedback Vertex Set (FVS) can
be adopted to help locate the break-points. It is briefly described as follows:
Let 𝐺 be a directed graph. A Feedback Vertex Set 𝐹 for 𝐺 is a set of vertices in 𝐺
such that every directed cycle in 𝐺 contains at least one vertex in 𝐹, or equivalently, that the
removal of 𝐹 from graph 𝐺 leaves a directed acyclic graph. Here, if we define FVS to have
the minimum number of vertices, then a FVS can be used as break-points. Note that the
break-points for a digraph is not unique, even though its size is unique. For example, both
𝐴 and 𝐵 can be used as break-points for the digraph of Figure 4.5(e).
The FVS problem is a classic NP-complete problem that appeared in the first list of
NP-complete problems in Karp’s paper [20]. It is practically efficient in our application since
(i) the DDG has been partitioned into SCCs such that the size of each SCC is small (ii) it is
68
P3
P0
N4
N5
P1 P2
N0
P4P5
N2 N3N1
P6
D
F
E
C
A
B
G
Q2
Q1
vdd
gnd
I1I2 I3
I4
I5
Figure 4.7 Schematic of the Sub-Bandgap reference
assumed that the size of breakpoints 𝐹 for each SCC satisfy |𝐹| ≤ 2 where |𝐹| is the size of
breakpoints. Assumption (ii) is reasonable because the |𝐹| > 2 means that a circuit would
have more than two coupled PFLs, which would be rare for practical circuits. |𝐹| > 2 also
means that, for the break-loop continuation method, at least three voltage source would
inefficiently need to be inserted and swept simultaneously.
[21] discusses the parameterized FVS problem on directed graphs (DFVS) defined as
follows: given a digraph 𝐺 and a parameter 𝑘, either construct a FVS of at most 𝑘 vertices for
𝐺 or report that no such set exists. In this work, the DFVS problem is resolved with running
time 4𝑘𝑘! 𝑛𝑂(1) so it can be applied to our case when parameter 𝑘 = 2, and is practically
efficient because of this small value of 𝑘.
4.6 Results
In this section, the effectiveness of the proposed approach is demonstrated by
reporting the results of applying the algorithm to both the Sub-Bandgap reference circuit
reported in [22] and the widlar-Banba circuit. The strongly-connected component is
identified for both circuit and also PFLs and breakpoints are pointed out for each SCC.
69
I2
I1
A
B
I3C
FI4 G
I5E
H1
H2
Figure 4.8 DDG showing SCCs of Figure 4.7
Figure 4.7 is the schematic of a Sub-Bandgap reference circuit. Figure 4.8 shows that
it has two SCCs: 𝐻1 , 𝐻2 , where 𝐻1 has one NFL and 𝐻2 has three PFLs. The size of
breakpoint for 𝐻2 is 2 that can be A, C. Figure 4.9(a) is the schematic of the widlar-Banba
circuit, Figure 4.9(b) shows that it has two SCCs: 𝐻1 , 𝐻2, where 𝐻1 has two PFLs and
𝐻2 has one PFL. The size of break-points for 𝐻1 is 1 that can be 𝑉𝑜 . The size of
breakpoints for 𝐻2 is 1 that can be either 𝑉2 or 𝑉3.
4.7 Conclusion
This chapter introduces a novel method of identifying all the PFLs in a circuit and
determine breakpoints for breaking all PFLs. The method first constructs the DDG and
partitions it into SCCs, then utilizes graph theory techniques to detect all the PFLs and locate
breakpoints for each SCC. On one hand, the method can verify a circuit’s vulnerability to
Trojan States simply by its structure since positive feedback loops are the sources of Trojan
States; on the other hand, the method provides a systematic approach for how and where to
break PFLs such that break-loop continuation methods can be applied. The proposed
approach will be demonstrated through two examples with results that show it can effectively
identify all the PFLs and breakpoints.
70
M11 M12 M1 M2
M3 M4
M9 M10
R1 R2
VAVB
gnd
I2 I3
I5 I6
vdd
R2
V1
Vo
Vbias
I4
M8
M7
M5
I1
M6
Vo
Vo1
M15 M16
M17
M13 M14
V2
V3I7 I8
M18
M19 M20
I9
Vbias
Banba Widlar
V4
(a)
I1
I2
Vo1
V1 I3 I5
I6
Vo
VA
VB
I9Vbias I4 V4
I8
I7
V2
V3
H1 H2
(b)
Figure 4.9 Widlar-banba circuit (a) schematic (b) DDG showing the strongly connected components
71
4.8 References
[1] G. C. M. Meijer and J. B. Verhoeff, “An Integrated Bandgap Reference,” Solid State
Circuits Conf. (ESSCIRC), 1975 First European, pp.40–41, 2–5, Sept. 1975.
[2] C. Zhao, J. He, S.-H. Lee, K. Peterson, R. L. Geiger and D. Chen,“Linear Vt-based
temperature sensors with low process sensitivity and improved power supply
headroom,” in Proc. IEEE Int. Symp. Circuits Systems,pp.2553–2556, May 2011.
[3] Y. T. Wang, D.G. Chen, R. L. Geiger, “Practical methods for verifying removal of
Trojan stable operating points,” in Proc. IEEE Int. Symp. Circuits Systems, pp.2658-
2661 May 2013.
[4] G. Gajani, A. Brambilla, and A. Premoli, "Numerical determination of possible multiple
DC solutions of nonlinear circuits," IEEE Trans Circuits Syst. I, vol. 55, pp. 1074–1083,
2008.
[5] J. F. Victor, H. M. Luis, S. R. Arturo, “Applying an iterative decomposed piecewise-
linear model to find multiple operating points,” in Proc. Europ. Conf. Circuit Theor. Des.
(ECCTD), pp. 978–981, 2007.
[6] S. Pastore, “Fast and efficient search for all DC solutions of PWL circuits by means of
oversized polyhedra”. IEEE Trans. Circuits Syst. I, vol. 58, pp. 2270–2279 , 2009.
[7] M. Tadeusiewicz, S. Hałgas, “A Contraction Method for Locating All the DC Solutions
of Circuits Containing Bipolar Transistors,” Circuits,Systems and Signal Processing,
vol. 31, pp. 1159–1166, June 2012.
[8] R. O. Nielsen and A. N. Willson, “A fundamental results concerning the TSology of
transistor circuits with multiple equilibria,” Proc. IEEE, vol. 68, no. 2, pp. 196–208,
1980.
[9] T. Nishi and L. O. Chua, “Topological criteria for nonlinear resistive circuits containing
controlled sources to have a unique solution,” IEEE Trans. Circuits Syst., vol. CAS–31,
pp. 722–741, 1984.
[10] C. Mass, “Algorithmic remarks on the Nishi-Chua uniqueness criterion for electrical
networks containing controlled sources,” IEEE Trans. Circuits Syst., vol. 36, pp. 1510-
1520, 1989.
[11] Y. Li and D. Chen, “Efficient analog verification against Trojan states using divide and
contraction method,” in 2014 IEEE International Symposium on Circuits and Systems
(ISCAS), 2014, pp. 281–284.
[12] H. Wen and M. M. Green, "Use of a continuation method for analyzing startup circuits,"
in Proc. IEEE Int. Symp. Circuits Systems, pp.1527–1530, May 2010.
72
[13] Z. Liu, Y. Li, R. L. Geiger, and D. Chen, “Auto-identification of positive feedback
loops in multi-state vulnerable circuits,” in 2014 IEEE 32nd VLSI Test Symposium
(VTS), 2014, pp. 1–5.
[14] C. J. Alpert, A. B. Kahng, “Recent directions in netlist partitioning: a Survey,” Integr.
VLSI J., vol.19, pp. 1–81, 1995.
[15] M. Migliore, V. Martorana, “An algorithm to find all paths between two nodes in a
graph,” Journal of Computational Physics, vol. 87, pp. 231–236, March 1990.
[16] T. H. Cormen, C. E. Leiserson, R. L. Rivest, and C. Stein, Introduction to Algorithms,
2nd ed., MIT Press and McGraw-Hill, 2001, pp. 540–549.
[17] K. Ruohonen,“Graph theory,” pp. 28, 2013.
[18] R. Tarjan, “Depth-first search and linear graph algorithms,” SIAM J. Comput., pp. 146–
160, 1972.
[19] D. B. Johnson, “Finding all the elementary circuits of a directed graph,” SIAM J.
Comput., vol. 4, pp. 77–84, Mar. 1975.
[20] R. M. Karp, “Reducibility among combinatorial problems,” Complexity of Computer
Computations, R. E. Miller and J. W. Thatcher, Eds. Plenum Press, New York, pp. 85-
103, 1972.
[21] J. Chen, Y. Liu, S. Lu, B. O'sullivan, I. Razgon. “A fixed-parameter algorithm for the
directed feedback vertex set problem,” Journal of the ACM (JACM), vol.55, October
2008.
[22] B. G. Adriana, T. L. Viswanathan, T.R.Viswanathan, “A Low-Supply-Voltage CMOS
Sub-Bandgap Reference,” IEEE Trans. Circuits Syst. II, vol. 55, pp. 609–613 , 2008.
73
CHAPTER 5. IMPROVING TIME-EFFICIENCY OF FAULT-COVERAGE
SIMULATION FOR MOS ANALOG CIRCUIT
In analog fault simulation, a number one challenge is that simulation time could grow
rapidly and become prohibitive as circuit size becomes large. This chapter proposes a
systematic method for significantly improving time efficiency in estimating fault coverage
for analog fault simulation. In the proposed method, a circuit under test (CUT) is first
partitioned into independent sub-circuits. This is accomplished by mapping the circuit into a
graph, decomposing the graph into strongly connected components (SCCs), and generating a
sub-circuit for each SCC. The impacts of potential faults directly entering a sub-circuit are
then simulated and recorded using the sub-circuits, and this would be expected to be
considerably more time efficient than fault simulation using the much larger whole circuit.
Finally, fault detectability at the given test-points is evaluated based on the fault impacts and
sensitivity among the different sub-circuits. As a first step toward quick estimation of fault
coverage, this chapter focuses on DC testing. Simulation results show that fault coverage of
DC tests can be estimated sufficiently accurately with simulation time being reduced by 10X
for the benchmark circuit, or by approximately the number of SCCs. For a much larger
circuit, the number of SCCs is expected to be much larger and the time-saving factor would
be much larger.
5.1 Introduction
During the past few years, there has been a rapid integration of semiconductor chips
into automotive and other mission-critical systems in which failure or malfunction may result
in great loss or severe impact on human life, so there naturally is increasing pressure to
guarantee that the underlying integrated circuits (ICs) be fault-free, i.e., to ensure that circuits
with manufacturing defects are detected and rejected by fault-coverage testing in production.
74
Since it might take months for inadequate test coverage to be revealed by, for example, an
excessive number of customer-returned faulty devices[1], [2], it is then often too late to
modify the design and/or develop new tests to increase fault coverage. Fault simulation is an
effective, economical approach to evaluating the coverage of a given test that provides
immediate feedback to both design and test engineers such that improved design and test
procedures can be achieved to increase production-test coverage before devices are shipped
to customers.
After decades of innovation, fault coverage simulation for digital circuits has
achieved great success, with test escape rates reaching below 0.1 defective parts per million
(dppm) [3], [4]. However, fault simulation for analog circuits has lagged far behind, and
there is a lack of existing commercially-available analog fault simulators [5]. Although
analog circuits typically constitute only a small fraction of modern mixed-signal ASICs, they
represent a major cause of customer returns in the industry [3], [6], so there is an urgent need
to develop practical and efficient methods for analog fault simulation at reasonable cost and
time.
One bottleneck that has made the development of commercial analog fault simulators
impractical is the amount of time and cost for simulating the impractically large number of
potential faults in industrial circuits. For example, as is reported in [5], simulating 2068
defects of an industrial circuit takes about 72 hours. Various improvements to fault
simulation have been proposed, including sampling techniques [5], [7]–[9] and simulation
frameworks [10], [11]. Goncalves and Teixeira [7] employed stratified sampling to group the
number of overall possible defects into homogeneous sub-groups. Guerreiro, et al.,
[8]proposed a fault list compression technique that partitioned the fault list into strata and
75
identified a set of “representative” faults. Ozev, et al., [9], [12]–[14] developed several
methods targeting near zero dppm test quality, including methods based on outlier analysis,
importance sampling modeling, and fault probability models. Sunter, et al., [5] proposed
likelihood-weighted random sampling (LWRS) to select the smallest number of potential
defects. Blanton, et al., [10], [11] proposed fast and accurate defect simulation frameworks
based on layout-injected defects. In summary, most of these methods focused on reducing the
number of simulated faults to save simulation time while maintaining required quality levels.
This chapter introduces a novel method focusing on reducing the time required for
simulating each single faulty circuit. The central idea is to simulate partial circuits instead of
an entire circuit using a directed-dependency graph to partition a large circuit into relatively
small independent sub-circuits. The time for simulating a sub-circuit is expected to be much
less than the time for simulating the much larger whole circuit. In particular, the impacts of
potential faults directly entering a sub-circuit are simulated and recorded using the sub-
circuits. The fault detectability and overall fault coverage at given test-points are evaluated
based on the recorded fault impacts and sensitivity among different sub-circuits. Circuit
partition is accomplished by creating a directed dependency graph from the circuit netlist,
identifying the SCCs of the graph, and generating a sub-circuit for each SCC.
The objective of this chapter is not to cover all types of faults or to improve analog
fault coverage, but to estimate fault coverage with sufficient accuracy in a shorter time
compared to that used by conventional methods for a given test set. As a first step toward
quick estimation of fault coverage, this chapter focuses on DC tests. The time saved can be
used for more tests, e.g., AC or transient, under given simulation time constraints. Recently,
Dobbelaere, et al., [15] have pointed out the desirability of DC tests for analog fault coverage
76
analysis due to their low cost, widespread applicability and availability. It has been shown
that fault coverage can be improved at very low cost by introduction of new DC fault models
and testing approaches [15].
A benchmark circuit composed of most widely-used analog blocks will be utilized to
demonstrate and validate the proposed method. Simulation results show that fault coverage
can be estimated sufficiently accurately with simulation time reduced by 10X, approximately
the number of SCCs. For a much larger circuit, the number of SCCs is expected to be much
larger and the time-saving factor would be correspondingly larger.
The remainder of this chapter is organized as follows. Section II previews a skeleton
of the proposed method. Section III illustrates how to construct the DDG for an example
circuit. Section IV describes how to partition a circuit into SCC sub-circuits and the
procedure for performing fault simulation based on the SCC sub-circuits. Section V describes
how to combine the simulated fault impacts with backward sensitivity analysis to evaluate
fault coverage. Section VI demonstrates the effectiveness of the proposed method by
applying the method to a benchmark circuit. Section VII and Section VIII offer discussion
and conclusions, respectively.
5.2 Overview of Proposed Method
Before discussing the proposed approach in detail, let us define several terms used
throughout this chapter. A defect is an unintended physical change in the manufactured
circuit. A fault is a defect that causes a circuit component to fail or not meet rated
specifications. Faults can be of two types: catastrophic and parametric. A catastrophic
fault, or hard fault, is defined as a fault that leads to a change in circuit topology. Hard faults
include short and open circuits. A parametric fault, also called a soft fault, is a fault that
translates into variations in the component parameters. At the circuit or product level, a
77
defective part is one whose specifications do not meet the rated specifications, due either to
fault(s) in the circuit or other causes.
Fault coverage (FC) is an important test metric used to express test quality of an
integrated circuit. It is defined as the percentage of modeled faults that can be detected by the
test. Another widely-used quality metric is defect level (DL) or test escapes [8], defined as
the ratio of the number of faulty devices shipped to customers to the total number of devices
shipped. DL can be expressed as a function of FC by the well-known Williams-Brown
equation [16]. To meet a high level of quality, it is necessary to minimize DL and maximize
FC. Quantitatively predicting defect levels using fault coverage is difficult, but achieving
high fault coverage does ensure low DL and high quality[17].
Fault simulation is an approach to FC estimation that injects hypothetical physical
defects into a design and verifies that the manufacturing test or verification suite can detect
them. The widely-used fault-oriented methodology [18] follows three phases: 1) obtain the
detection limits at the test-points by simulating the fault-free circuit C0; 2) under single fault
assumption, inject the fault list 𝐹=F1, F2, … Fn one by one into the designed circuit C0
[19] to create faulty circuits C1, C2, … , Cn; 3) simulate each faulty circuit and report fault
detection failure if the results violate detection limits. During fault simulation, a “single
fault” assumption, meaning that only one fault will occur in a circuit at a time, is typically
made.
In conventional analog fault simulation, the number one challenge is that the overall
simulation time could grow exponentially and become prohibitively long as circuit size
becomes large. This occurs mainly because the number of sites for potential faults in modern
mixed-signal circuit blocks can be impractically large, e.g., tens of thousands [5]. To worsen
78
Circuit netlist
Strongly connected
components
Directed dependency
graph
Fault simulation
SCC Sub-circuits
Fault coverage
evaluation
Faulty Sub-circuits
Given
Fault list
Reduced acyclic
graph
Figure 5.1 Flowchart of the proposed method
the problem, as circuit size increases, the time for simulating every faulty circuit will increase
significantly. For example, simulating every fault may require time ranging from minutes to
days [2]. Sampling or selecting “representative” faults from the fault list offers one way to
reduce simulation time that been explored in various literature references [5], [7], [8].
Another way to reduce simulation time is to relax simulator accuracy, but this will inevitably
reduce the estimation accuracy of fault coverage and the achievable speedup is only 2~10X
[5].
In this work, a new method for significantly reduce the time required for simulating
each faulty circuit Ci (i=1,2…n) will be introduced. The proposed method, complementary to
the mentioned sampling techniques, can be readily combined with these techniques to either
significantly reduce simulation time for a given sampled subset of the fault list, or simulate
significantly more faults (larger sampled subset) within a given time budget.
The flowchart of the proposed method is illustrated in Figure 5.1. The circuit netlist is
79
first converted to a directed dependency graph (DDG). Then, using graph theory techniques,
the DDG are partitioned into a set of disjoint strongly connected components (SCC). The
SCCs information is made use of in two aspects. On one hand, it is utilized to reduce the
DDG to a simple acyclic graph where each super vertex stands for one SCC. On the other
hand, a sub-circuit, termed a SCC sub-circuit, is created for each SCC,. Using these SCC
sub-circuits and the given fault list 𝐹 , faults 𝐹𝑖 (i = 1,2 … n) are injected to the
corresponding SCC sub-circuits one-by-one to create n faulty circuit Ci′(i = 1,2 … n). These
faulty circuits, generated based on SCC sub-circuits, are each much smaller in size than the
faulty circuit Ci (i=1,2…n) generated based on the whole circuit. The impacts of potential
faults directly entering a sub-circuit are then simulated and recorded using the sub-circuits, a
process expected to be much more time-efficient than fault simulation of the whole circuit.
Finally, the fault detectability at the given test-points is evaluated based on the fault impacts
and a reduced acyclic graph.
5.3 Directed Dependency Graph
In this section, we will first illustrate how to construct the DDG for the simple
example circuit shown in Figure 5.2. SCC concepts will then be defined and identified.
5.3.1 Directed Dependency Graph
The concept of directed dependency graphs (DDG) has been widely used in general
and by the authors in [20], [21] to successfully address analog verification issues and achieve
excellent results. An EDA tool was developed and implemented in Cadence Virtuoso to
automatically convert a circuit netlist to a DDG. An important property of the DDG is that it
captures critical dependencies between the voltages and currents of a circuit. For the purpose
of decomposing a circuit to a sub-circuit, this property is very useful because it allows one to
80
V1 V2
V3
e1
e2
e3
Figure 5.2 A simple directed graph example
know which voltages and currents are correlated. In this chapter, the DDG will be defined in
a similar manner and demonstrated through the example circuit.
In graph theory, a directed graph G is a pair (V, E) where: 1) V is a set whose
elements are called vertices. 2) E is a set of ordered pairs of vertices, called directed edges or
arcs. The arc from vertex 𝑢 to vertex 𝑣 is written as (𝑢, 𝑣) and the other pair (𝑣, 𝑢) is the arc
in the opposite direction. Figure 5.2 shows a simple example of a directed graph. The circles
stand for vertices and the labels inside the circles refer to vertex names, hence 𝑉 =
𝑉1, 𝑉2, 𝑉3. The oriented arrows represent the directed edges, hence 𝐸 = 𝑒1, 𝑒2, 𝑒3. The
graph in Figure 5.2 can therefore be expressed as
𝐺 = (𝑉1, 𝑉2, 𝑉3, (𝑉1, 𝑉2)(𝑉3, 𝑉2), (𝑉2, 𝑉3))
Now we will apply this directed graph concept to define the DDG of a circuit and
illustrate it through the example circuit shown in Figure 5.3(a).
A node of a circuit refers to a point where two or more circuit elements meet. For two
nodes to be different, their voltages must be different. For example, 𝑉1 and 𝑉𝑜 are two nodes
of the circuit shown in Figure 5.3(a). To avoid confusion, the term “node” will be used only
when describing a circuit schematic and “vertex” will be used with reference to graphs
throughout the rest of this chapter.
For a circuit under test(CUT), a directed dependency graph is defined as a directed
graph DDG(V, E), where the vertex set V represents all voltages and currents in the circuit
81
M3 M4
M1 M2
V1
V2
I1
I4
M5
M6
I9
Vo
M9
M7
M8
I3
I6IR1 R1
I2I5I7
I8
I9
gnd
vdd
V3
V4
(a)
I1
I4
I3
V1
V2
I5
I6
I9
IR1V3
I2
Vo
I7
I8
V4
(b)
Figure 5.3 Example circuit: Widlar bias generator, (a) schematic (b) DDG
and the edge set E stands for the directed dependencies between voltages and currents. The
sets V and E of a DDG will be described in detail below.
First, the vertex set V of a DDG(V, E) has two types of vertices: a voltage vertex and
a current vertex.
• A voltage vertex represents the voltage at a node in a circuit.
For notational convenience, we will label a voltage vertex using the corresponding
node name. For example, 𝑉1, 𝑉2 are two voltage vertices for the circuit in Figure 5.3(a).
82
• A current vertex is defined as the total physical current across a device in the
circuit.
We denote a current vertex as I(X, Y, GATE) or I for simplicity. It refers to the
current flowing from node X to node Y. Note that if we have MOSFETS that directly
contribute current to this I, then GATE is the set of nodes to which the gates of these
MOSFETs are connected; otherwise, GATE is an empty set. As an example, I1(vdd, V2,
V1) stands for the current I1 shown in Figure 5.3(a) that flows from “vdd” to “V2”. In this
case there is only one MOSFET M1 that contributes current to I1, hence its GATE has only
one element V2 that stands for the gate of M5.
Second, the edge set E of a DDG(V, E) is composed of all possible directed
dependencies between two vertices in V. A directed dependency is defined based on the
definition of current vertex.
Given a current vertex I(X, Y, GATE), or I for simplicity, there are five possible
directed dependencies 𝑋 → 𝐼, 𝐼 → 𝑋, 𝑌 → 𝐼, 𝐼 → 𝑌, 𝐺𝐴𝑇𝐸 → 𝐼.
To make this definition clearer, four things should be pointed out. 1) The arrow “→”
is used to represent the direction of dependency. For example, 𝑋 → 𝐼 represents the
dependency from 𝑋 to 𝐼. Each directed dependency corresponds to a directed edge in the
DDG, e.g., (𝑋, 𝐼). 2) The dependency 𝐺𝐴𝑇𝐸 → 𝐼 is composed of dependencies from each
element in 𝐺𝐴𝑇𝐸 to 𝐼. 3) The concept of “dependency”, e.g., 𝑋 → 𝐼 means that the partial
derivative of 𝐼 with respect to 𝑋 will be non-zero. In other words, a small change in the value
of 𝑋 will cause a change in the value of 𝐼. 4) The word “possible” is used to reflect that, if X
is vdd, then 𝐼 → 𝑣𝑑𝑑 is not a dependency because it is assumed that power supply (e.g. vdd
or gnd in Figure) will not be affected by the internal circuit. On the other hand, 𝑣𝑑𝑑 → 𝐼 is a
83
dependency by definition but will not be included in the DDG, because since there will be no
faults occurring at power supply, there is no need to include supply-related dependencies
(Remember that the purpose of the DDG is to investigate the relationships of internal nodes).
As a result, if X is vdd, the dependencies will be 𝑌 → 𝐼, 𝐼 → 𝑌, 𝐺𝐴𝑇𝐸 → 𝐼. Similarly, if Y is
gnd, the dependencies will be 𝑋 → 𝐼, 𝐼 → 𝑋, 𝐺𝐴𝑇𝐸 → 𝐼.
Now, based on the above definitions, we will show how to construct the DDG for the
circuit shown in Figure 5.3(a). First, it can be shown that the circuit has five voltage vertices
and nine current vertices, i.e., V=vdd, gnd, V1, V2, V3, V4, Vo, I1, I2, …, I9. Second,
twenty-six directed dependencies can be identified. Finally, the DDG of Figure 5.3(a) is
shown in Figure 5.3(b). The circles represent voltage or current vertices and the oriented
arrows represent the directed dependencies. This process can be performed automatically and
efficiently using the mentioned EDA tool with running time linear with circuit size.
5.3.2 Strongly-Connected Components
The strongly-connected component is an important concept in standard graph theory.
Any directed graph can be partitioned into a set of disjoint strongly-connected components.
Several graph theory terms summarized below will be used through this chapter .
Let G= (V, E) be a directed graph:
• A path in 𝐺 is a finite sequence of alternating vertices and
edges: 𝑣𝑖0, 𝑒𝑗1, 𝑣𝑖1, 𝑒𝑗2, … , 𝑒𝑗𝑘 , 𝑣𝑖𝑘 , where directed edge 𝑒𝑗𝑡 = (𝑣𝑖𝑡−1, 𝑣𝑖𝑡) for 𝑡 = 1,2, … 𝑘 .
Any vertex or edge is visited at most once.
• A directed graph 𝐻 is strongly-connected if for every pair of vertices in 𝐻, say
𝑢 and 𝑣, there is at least one path from 𝑢 to 𝑣 and at least one path from 𝑣 to 𝑢. By
convention, the trivial graph (with only one vertex) is strongly-connected.
84
I1
I4
I3
V1
V2
I5
I6
I9
IR1V3
I2
Vo
I7
I8
V4
SCC1 SCC2 SCC3
Figure 5.4 The SCCs for the DDG shown in Figure 2.3(b)
• A Strongly-Connected Component (SCC) 𝐻 of 𝐺 is a subgraph of 𝐺 such that 𝐻 is
strongly-connected, but if we add any vertices or arcs to 𝐻, it is no longer strongly
connected.
• A sink SCC of G is an SCC that has no edges leaving it. A source SCC of G is an
SCC that has no edges entering it. A directed graph has at least one sink SCC and
one source SCC.
A detailed description of an SCC can be found in [22]. The most important property
of an SCC is that, for vertices 𝑢 and 𝑣, if 𝑢 and 𝑣 are in the same SCC, then 𝑢 and 𝑣 will have
bi-directional dependency, meaning that any voltage or current change at 𝑢 (𝑣) will cause
voltage or current change at 𝑣 (𝑢) following the 𝑢 − 𝑣 (𝑣 − 𝑢 ) path. On the other hand, if
𝑢 and 𝑣 are in different SCCs, then 𝑢 and 𝑣 will have one-directional dependency. This SCC
property provides the basis for portioning a circuit into sub-circuits. Only one-directional
dependency can exist between nodes in different sub-circuits. Details will be presented later.
To decompose a digraph G into strongly-connected components, Tarjan [23]
presented an algorithm with a 𝑂(𝑛 + 𝑒) running time, for an input graph with 𝑛 vertices and
𝑒 edges. As an example, after applying Tarjan’s algorithm to the DDG shown in Figure
85
5.3(b), three SCCs can be identified. They are shown in Figure 5.4 as SCC1~SCC3 and
dashed shadows are used to separate them.
For convenience in describing the method, we define an output vertex 𝑉𝑜 of a SCC 𝐻
as a vertex with outgoing edges leaving H. Similarly, an input vertex 𝑉𝑖 is defined as a vertex
with incoming edges. These input/output vertices are the interconnection points among
different SCCs. For example, in Figure 5.4, 𝑉4 is the output vertex of SCC1 and I9 is the
input vertex of SCC2.
5.4 Fault Simulation with Sub-circuits
In this section, we will show how to make use of the constructed graph to partition a
target circuit into smaller sub-circuits called “SCC sub-circuits”. The procedure and time
efficiency of performing fault simulation based on the SCC sub-circuits will then be
discussed.
5.4.1 SCC Sub-circuits
Notice that the DDG is created in such a way that every vertex has a corresponding
node or an instance in the circuit schematic, so one can easily map the SCC back to a circuit
netlist, i.e., find all the nodes and instances for an SCC because instance connections inside
an SCC sub-netlist are inherent from the original fault-free circuit. To generate a netlist that
can be executed by simulators like Spectre or UltraSim, additional manipulations must be
performed at the interconnection points among different SCCs. This idea is summarized in
the following procedure:
1) Find the circuit nodes that correspond to the input/output vertices of the SCCs.
2) Break these nodes into a pair of “breaking points”. For each “breaking points” pair,
one side is the output vertex of the preceding SCC and the other side is the input vertex of the
succeeding SCC.
86
M7
M8
I7
I8
V4
vdd
gnd
M3 M4
M1 M2
V1
V2
I1
I4
M9
I3
IR1R1
I2
I9
gnd
vdd
V3
M5
M6
Vo
I6
I5
vdd
Vdc=V4,desired
Vdc=V1,desired
gnd
(a)
M3 M4
M1 M2
V1
V2
I1
I4
M9
I3
IR1 R1
I2
I9
gnd
vdd
V3
M5
M6
Vo
I6
I5
vdd
Vdc=V4,desired
gnd
(b)
Figure 5.5 (a) SCC sub-circuits of example widlar circuit (b) a sub-circuit
generated from the combination of SCC2 and SCC3
3) Connect an independent voltage source to the side that is an SCC input. The
nominal voltage at this “broken node” is set to that of the added voltage source. In other
words, the results from simulating the fault-free circuit can be used, because under the single
fault assumption, when we perform fault simulation for a specific SCC, other parts of the
circuit are fault-free.
Following this procedure, the circuit is partitioned into sub-circuits whose number is
equal to the number of SCCs, so as a result, each SCC sub-circuit will contain all instances
that contribute current vertices to that SCC. The preceding SCC sub-circuit does not load the
succeeding SCC sub-circuit, because if this were not the case, there would have existed
87
another dependency from the succeeding SCC to the preceding SCC in the DDG and these
two SCCs would have merged into one SCC. In other words, the “broken” nodes are
typically transistor gates with infinite impedance.
Figure 5.5(a) shows the SCC sub-circuits of the example widlar circuit, with three
SCC sub-circuits that correspond to the three SCCs in the DDG of Figure 5.4 identified. The
input vertex of SCC2 is V4 , so a voltage source with Vdc=V4,desired is added. Similarly, the
input vertex of SCC3 is V1 , so a voltage source Vdc=V1,desired is added.
Now, for a hypothetical potential fault 𝐹𝑖, we first determine the SCC sub-circuit that
Fi will directly impact and denote the determined sub-circuit as C0′. Fi is then injected into
C0′ to create a faulty circuit Ci′. By comparing the simulation results of the fault-free sub-
circuit C0′ and the faulty circuit Ci′, voltage or current changes at the output vertices of this
SCC can be determined. These voltage or current changes are termed “fault impacts”, a term
used throughout this chapter. Notice that this process of performing fault simulation for a
potential fault essentially follows the standard three-phase fault-oriented methodology
mentioned in Section II, with the major difference that the proposed method uses sub-circuits
rather than the whole circuit. For example, when simulating a short-circuit fault between
drain and source of transistor M8, the SCC1 sub-circuit will be utilized because M8 is an
instance in the SCC1 sub-circuit. The fault impact will then be obtained at the output node
V4. It should be noted that, if required, a sub-circuit can be generated from the combination
of two or more adjacent SCCs. For example, when simulating the short-circuit fault between
V1 and Vo, SCC2 and SCC3 can be combined to generate a sub-circuit as shown in Figure
5.5(b). Moreover, the user could choose to always use the sub-circuit of Figure 5.5(b) for all
faults in SCC2 and SCC3.
88
The above procedure is repeated for all potential faults in a fault list 𝐹, and it can be
seen that the faulty circuit Ci′(i = 1,2 … n) generated based on SCC sub-circuits is much
smaller in size than the faulty circuit Ci (i=1,2…n) generated based on the whole circuit.
That is why the simulation time of the proposed method is significantly reduced. This is
extremely advantageous especially when the circuit is large. More details related to time
efficiency will be discussed in the next subsection.
5.4.2 Time Efficiency
In this subsection, we will compare the time efficiency for the proposed sub-circuit
based fault simulation with that for conventional fault simulation.
Suppose a) simulation time is linear with circuit size; b) the time for simulating the
fault-free circuit C0 is approximately equal to the time for simulating a faulty circuit Ci
(i=1,2…n). Then, for conventional fault simulation, the total time 𝑇𝑐𝑜𝑛𝑣 can be expressed as:
0 0
1
n
conv
i
T t n t=
= = (5-1)
where 𝑛 is the number of faults in the fault list and 𝑡0 is the time for simulating the fault-free
circuit C0.
Similarly, for the proposed sub-circuit based fault simulation, the total time 𝑇𝑝𝑟𝑜𝑝 can
be expressed as:
1 1
, withm m
prop j j j
i j
T k t k n= =
= = (5-2)
where 𝑛 is the number of faults in the fault list, 𝑚 is the number of SCCs, 𝑡𝑗 is the time for
simulating a fault-free sub-circuit 𝑗, and 𝑘𝑗 is the number of faults related to sub-circuit 𝑗. To
provide more insight into the difference between 𝑇𝑐𝑜𝑛𝑣 and 𝑇𝑝𝑟𝑜𝑝, we assume that all SCC
89
sub-circuits have equal size such that 𝑡𝑗 =𝑡0
𝑚, for 𝑗 = 1,2, … , 𝑚. With this assumption, Eq. (5-
2) can be simplified to:
0
1
mconv
prop j
i
t TT k
m m=
= (5-3)
From Eq. (5-3), we can see that the proposed method reduces the fault simulation
time by a factor approximately equal to the number of SCCs. This conclusion is made based
on the assumption that simulation time is linear with circuit size. In reality, simulation time is
typically nonlinear with circuit size, and this will most likely result in a larger time-saving
factor.
In summary, a method for partitioning the CUT into multiple sub-circuits has bee
described in this section. Using these sub-circuits, an efficient fault simulation can be
performed for a given fault list. We will next discuss how to utilize the simulated results to
evaluate the fault coverage.
5.5 Fault Coverage Evaluation
In the previous section we identified the sub-circuits for each SCC such that fault
impacts could be simulated and obtained at output vertices of the SCC sub-circuits. This
section will show how to combine the simulated fault impacts with backward sensitivity
analysis to more effectively evaluate the fault coverage.
As is discussed in section II, a fault is reported as detected if the simulation results
violate the detection limits, the bounds of the accepted voltage or current ranges at the test-
points. The decision function g(), defined by Eq. (5-4), is used to decide whether a given IC
should be passed as good or failed as faulty for a given measurement.
1 ( )
( )0 ( )
nom L nom Upass if D Dg
fail otherwise
+ +=
. (5-4)
90
where is a measured current or voltage variable at the observation points, nom is the
nominal value of ; DL is the lower detection limit, a negative number, and DU is the upper
detection limit, a positive number. DL and DU can be provided by the designer, based on
production test limits, or based on Monte-Carlo simulations. Approaches to optimal setting of
detection limits based on obtaining faulty and fault-free probability distributions from
Monte-Carlo analysis are presented in [24], [25]. In this chapter, the test-points and
corresponding detection limits are assumed to have been determined, and for simplicity these
detection limits are assumed to be symmetric with respect to the nominal value, meaning that
|DL| is equal to DU , and we can denote either of them simply as D.
Note that while the detection limits are obtained at the test-points for the whole
circuit, in the proposed method fault impacts are obtained at nodes that correspond to the
output vertices of the SCC sub-circuits, and these nodes do not necessarily belong to the
given tests points , so certain manipulations must be performed to build connections between
the fault impacts at SCC outputs and the detection limits at the overall test points. A method
based on a simple weighted graph and sensitivity analysis is proposed for accomplishing this.
5.5.1 Directed Acyclic Graph
First of all, let us introduce another graph technique to reduce the DDG to a simple
acyclic graph for convenience in performing backward sensitivity analysis. Assuming that a
directed graph G is decomposed into SCCs, if one uses a single super-vertex to represent
each SCC, the resulting graph will be ‘shrunk’, and this shrunk graph is guaranteed to be a
directed acyclic graph ( DAG) with no loops [26]. There is motivation to apply this graph
manipulation in the DDG because there only forward paths will remain in an acyclic graph,
so backward sensitivity analysis will be straightforward.
91
To designate an SCC, rather than using one super-vertex, we will use the
corresponding output vertices of each SCC because the fault impacts are characterized at the
output of each SCC. Among these output vertices, edges will be drawn from vertex 𝑢 to
another vertex 𝑣 if 𝑢 can reach 𝑣 in graph G. The gain in edges can be calculated using
various methods such as Mason’s formula [27] or state-space equations [28] that are outside
the focus of this chapter. The method we adopted to calculate these gains can be briefly
summarized by the following three steps. First, a weighted sensitivity graph is created for
each SCC. Second, using the weighted graph, the input/output gain for each SCC will be
calculated using standard methods [28]. Third, repeat the above procedure for all SCCs
(except source SCCs). The result will be to obtain gains among the output vertices of all
adjacent SCCs because the inputs to an SCC are the output vertices of its preceding SCCs.
As an example, the simplified directed acyclic graph corresponding to Figure 5.4 is
shown in Figure 5.6. The fault impacts for SCC1, SCC2, and SCC3 related faults will be
referred to V4, V1 and Vo , respectively. The gain from V4 to V1 is denoted as G1 and the gain
from V1 to Vo is G2.
5.5.2 Backward Sensitivity Analysis
Sensitivity-based methods such as LIMSoft [29] for analog fault testing have been
previously investigated. The LIMSoft method evaluates the effects of all hard faults on the
output parameters by use of two SPICE circuit simulations and generates a test vector
V1 VoV4
G1 G2
DoD1/oD4/o
SCC1 SCC2 SCC3
Figure 5.6 The directed acyclic graph for Figure 5.3
92
through gradient functions, so it requires a ‘linear’ assumption for the entire circuit. In the
proposed method, we combine the circuit partitioning and sensitivity analysis. In particular,
the fault impacts at the output of each SCC sub-circuit still rely on simulations and only the
sensitivities among the SCC outputs are calculated and used to evaluate the fault coverage, so
the proposed method is expected to have better fault coverage estimation accuracy while at
the same time reducing simulation time.
With the weighted acyclic graph introduced in the previous subsection, we now can
show how the proposed backward sensitivity analysis works. Suppose 𝑉𝑜 is the chosen test
point for the example circuit and the detection limit at 𝑉𝑜 is 𝐷𝑜 . The sensitivity analysis
begins at the SCC3 related faults. If the impact in 𝑉𝑜 due to a fault is greater than |𝐷𝑜|, this
fault can be detected at vertex 𝑉𝑜 and will be reported as detected, otherwise it will be
reported as undetected. When all SCC3-related faults have been checked, we will move
backward one level in the DAG. Following the edge from 𝑉1 to 𝑉𝑜, the equivalent detection
limit at 𝑉1 is calculated to be 𝐷1/𝑜 = 𝐷𝑜/𝐺2,labeled in red text in the DAG shown in
Figure 5.6. Notice that we call this an “equivalent detection limit” because it is the fault
impact required for SCC2 related faults to be detected at 𝑉𝑜 (not at 𝑉1). Similarly, if the
impact in 𝑉1 due to a SCC2 related fault is greater than |𝐷1/𝑜|, this fault can be detected at
vertex 𝑉𝑜 and we will report this fault as detected. Although the proposed method does not
make a “linear circuit” assumption, we use small-signal local linearization in the fault-free
circuit for the purpose of propagating the detection limits from the test-points to the various
nodes of the circuits. If a fault impact (obtained by simulating a sub-circuit) is large and
exceeds the linear range, this implies that the fault is detected.
93
Continuing with backward propagation in this manner, we can obtain a list of all
faults that can be detected at vertex 𝑉𝑜, and if a circuit has multiple test-points, we can do the
same for each of them. A fault will be detected as long as it is reported as detected at one test
point. Finally, the fault coverage is evaluated as the number of faults that could be detected
divided by the total number of faults in the fault list that will be simulated. It can be
expressed as Eq. (5-5).
Number of detected faults
FCNumber of simulated faults
= (5-5)
During backward sensitivity analysis, there are two situations that should be made
clear because in these situations the calculation of gains and equivalent detection limits will
not be a straightforward as in the above simple DAG example. One such situation is when
multiple vertices exist in some SCCs, and another is when multiple paths exist from one
vertex to a test point. These situations will be described and addressed by the following
discussion.
First, as has been mentioned, while we use corresponding output vertices (possibly
more than one) to represent each SCC in the directed acyclic graph, in the directed acyclic
graph example shown in Figure 5.6, each SCC only has a single output vertex. Figure 5.7(a)
shows an artificial DAG where SCC1 has two output vertices N1 and N2. By the definition
of SCC we know that there will be paths from N1 to N2 and paths from N2 to N1, even if we
do not show them in the DAG. In such a case, there will be multiple independent equivalent
detection limits from every output vertex of SCC1 to all its succeeding SCCs. For example,
the equivalent detection limits for N1 and N2 can be calculated and illustrated as in Figure
5.7(b). D1/3 is the calculated detection limit at N1 for SCC1-related faults to be detected at
94
N3 and D1/4 is the calculated detection limit at N1 for SCC1-related faults to be detected at
N4.
Second, when multiple paths exist from a vertex to a test point, multiple equivalent
detection limits will be obtained for the same vertex. Even though we still call them
equivalent detection limits, they are intermediate quantities and not true detection limits. To
illustrate this, consider the simplified graph shown in Figure 5.8, and suppose there are m
paths from N1 to N2, so that m equivalent detection limits, 𝐷1/2(𝑖)
(𝑖 = 1,2, … , 𝑚) will be
obtained at vertex N1. When m is one, the single equivalent detection limit obtained is the
true detection limit. The example DAG of Figure 5.6 is in this category. When m is greater
N2N1
D2D(1)1/2
D(2)1/2
D(m)1/2
Figure 5.8 A simplified graph where multiple paths exist from one vertex to a
test point vertex to a test point
N1 N3
N4N2
D3
D4
N1 N3
N4N2
D3
D1/3
D4
D2/3
D1/4
D2/4
SCC1G1
G2
G3
G4
(a) (b)
Figure 5.7 (a)an artificial DAG where SCC1 has two output vertices N1 and
N2; (b) calculation of equivalent detection limits for N1 and N2
95
than one, we need to calculate the true equivalent detection limit. We know that the gains of
these paths can be obtained by
2
1/2
( 1,2,..., )i
DG i m
D= = . (5-6)
All the paths with positive gains can be added to obtain the net gain of all the positive gain
paths, 𝐺𝑝. Similarly, all the negative gains can be combined to get 𝐺𝑛.
Now, if the absolute values of 𝐺𝑝 and 𝐺𝑛 are close to one another, all faults in this
SCC have low sensitivity at the test point. To mathematically decide whether the absolute
values are close, we calculate the relative difference (dr) between the absolute value of 𝐺𝑝
and 𝐺𝑛 as:
( )
100%.,
p n
r
p n
G Gd
mean G G
−= (5-7)
Whenever dr is less than a chosen 𝛿, say 5%, then all faults in this SCC are reported as
undetected at this vertex.
If dr is greater than the chosen 𝛿 , the true equivalent detection limit 𝐷1/2 can be
calculated by Eq. (5-8).
2
1/2
i
p n
DD
G G=
+. (5-8)
The delta parameter is an indication of how close the gains in the positive and
negative paths can be before declaring the sensitivity to be too low. If delta is chosen to be
very small, we could be overestimating the sensitivity, and we could label the fault as
detectable when it might not be, resulting in a more liberal estimate of fault coverage than the
true fault coverage. On the other hand, if delta is chosen to be very large, we could be
underestimating the sensitivity, and the fault could be labeled as undetected even when it
96
T55
T56
T57
T58
T47
T48
T49
T50
T12
T14
T16
T18
VDD
T15
T17
T11
T13
T33
T34
T31 T32
T59
T60
T61
T62
T51
T52
T53
T54
T20
T22
T24
T26
VDD
T23
T25
T19
T21
T28
T27
T29 T30
T2
T4
T6
T8
T5
T7
T1
T3
T9
T10
T36T35
T37
T63
T64
T39T40
T41 T42
T44T43 T46
T45
VD
DV
SS
VSS
VSS
R9
T8 C2
V2
V3 V4
V1
R6
R6
R5 R2R3 R1
T38
p6
p7
p8
wp3
wp4
wp3
wp4
wp3
wp4
wp3
wp4
b2
b1
p5
p4
wp1
wp2
p9
p10
n6
n7
n8
n4
n2
n6
n6
n6
n1 wn1
wn2
wn1
wn2
wn1
wn2
wn3
wn4
b3
n5
vin vip
vin vip
b3
b1
b2
b4
Vr
vo1 vout
vstart
Vr Vr
VrVr
Vaa
Vab
VabVaa
Vr
vpa vpbvpbvpa
vnbvna
vnbvna
P-cascode
biasing
Opamp
biasing 1
P-type
WidlarOpamp core
N-cascode
biasing
Opamp
biasing 2
N-type
WidlarBanba
Simulation Setup
vip
vin vout
Opamp core
R4
Vref
generator
Vref
Figure 5.9 Benchmark circuit
might be detectable, a more conservative estimate of fault coverage. In the implementation, a
flag will be raised when dr is small to suggest that additional tests are required to determine
whether more accurate fault coverage estimation is needed.
It should be mentioned that, in the fault coverage evaluation process, the running time
is 𝑂(𝑚), where m is the number of SCCs. This time is insignificant compared to the time
required for fault simulation. Furthermore, the running time associated with generating the
DDG and SCC sub-circuits is also linear with circuit size, so fault simulation dominates the
overall running time of the proposed method.
5.6 Case Study
In this section, the proposed method is applied to the benchmark circuit shown in
Figure 5.9, chosen because it is composed of widely-used analog blocks such as a bandgap
97
SCC4
SCC1
SCC2
SCC12
SCC10SCC5
SCC9
SCC6
SCC11
SCC7
SCC3
Vstart
Vr
vo1
vinwp3,wp4
b1,b2
wn1,wn2
b3
wn1,wn2
SCC8wp3,
wp4
Opamp Core
Banba core
Star-up
circuit
N-type
Widlar
P-type
Widlar
P-cascode
biasing
Opamp
biasing 1
Opamp
biasing 2
N-cascode
biasing
Vr
Vref
generator
wp3,wp4
wn1,wn2
Figure 5.10 A ‘simplified’ graph of the benchmark circuit in Figure 5.9
reference, a widlar bias generator, and an op amp. The schematic netlist of the benchmark
circuit contains 64 transistors, 9 resistors, and 1 capacitor.
The circuit can be automatically converted to a DDG using the mentioned EDA tool
(the resulting graph will not be shown because of its complexity). 12 SCCs are then
identified using the graph techniques described. For purposes of illustration, a ‘simplified’
graph of the benchmark circuit is shown in Figure 5.10 with blocks highlighted using dashed
boxes. It can be seen that the identified SCCs correspond to different blocks of the circuit and
the directed edges denote the interactions or dependencies between adjacent blocks. The
labels on these edges represent the names of the connecting nodes, the output vertices of
corresponding preceding SCCs. A label on one edge may contain more than one node, e.g.,
wn1, wn2, meaning that multiple connecting nodes exist between the two adjacent blocks.
Based on the identified SCC, the target circuit can be partitioned into 12 SCC sub-circuits.
To demonstrate the time efficiency of the proposed method, consider a fault list contains 338
98
selected faults resulting from: (1) a classic 5-fault MOSFET model [30], namely, open drain,
open source and source-drain, drain-gate, source-gate shorts; (2) short and open faults for
resistors and capacitors. A value of 10 Ω was chosen for the resistance values used to model
the shorts and 1 GΩ for the resistance values used to model the opens.
Two important things can be pointed out: 1) While this demonstration of the proposed
method focuses on hard faults, the proposed method is not limited only to hard faults, and it
is possible that detecting soft faults could also be important for quality tests or broader
application aspects. 2) The proposed method is insensitive to the fault model. For a given
fault model and given DC tests, the proposed method tries to achieve the same fault
detectability (with less simulation effort) than in conventional fault simulation. As is well-
known, there are different strategies for modeling the possible faults of a MOSEFT. For
example, while open-gate faults modeled as large-resistances in series with transistor gate
terminals can be added to the fault list in [3], with this model and considering only DC tests,
they will not be detected either by the conventional method of simulating the whole circuit,
or by simulating the sub-circuit as proposed. Recently, ON Semiconductor, in ITC’16 [15]
introduced a new technique for modeling an open gate transistor in DC tests using a
transistor operating in the subthreshold region, implemented by inserting a voltage-controlled
voltage source between the gate and the source terminals of a given transistor and utilizing
the drain-source voltage as the controlling voltage. This model enables testability of open-
gate faults with DC tests in both the conventional and the proposed methods. Furthermore,
the fault list can be extracted from the layout that shows the physical spatial relationship of
conducting materials, using methods like Inductive Fault Analysis (IFA) [5] and tools
described in [31].
99
The proposed fault-simulation performance was compared to conventional fault
simulation, using Virtuoso Spectre for simulation. The reported simulation times are the
average times for running the benchmark circuit ten times considering that Spectre is running
on a multi-core server. Simulation results are summarized in Table 5.1. The row titled ‘Fault
simulation time’ shows the total time taken by Spectre to perform DC simulations both for
the fault-free circuit and all the faulty circuits. It can be seen that the average fault simulation
time is reduced from 585.19s to 39.18s, a time-saving factor of 15 slightly larger than the
number of SCCs. This may be due to the fact that simulation time is nonlinear with circuit
size. On the other hand, the fault coverage for the proposed fault simulation is 75.14%, close
to the 78.11% coverage of conventional fault simulation. To validate that fault simulation
dominates the overall running time of the proposed method, we also provide another running
time for comparison. In the conventional method, ‘Other time’ includes injecting faults into
the CUT, creating faulty circuit netlists, configuring the simulator (e.g., accuracy options,
working directory etc.) and calculating the fault coverage results. In the proposed method,
‘Other time’ as expected is slightly larger because additional time is consumed for graph
manipulation operations such as generating the DDG and SCC sub-circuits.
Table 5.1 Performance Summary
Proposed Conventional Unit
# of faults simulated 338 338 -
# of faults detected 254 264 -
Fault coverage 75.14 78.11 %
Fault simulation time 39.18 585.19 s
Other time 23.78 14.25 s
100
We observed estimation inaccuracy for the proposed method, and this was expected
because of the tradeoff between simulation time and estimation accuracy. For undetected
faults in the proposed method, while we could repeat fault simulation using the whole circuit
netlist to accomplish fault coverage closer to that of conventional fault simulation, the cost
would be in added simulation time. The proposed method can be readily combined with
sampling techniques described in the literature [5], possibly dramatically reducing the
simulation time for estimating coverage based on a given number of selected defects. This
seems very promising for quick coverage assessment considering the fact that conventionally
simulating 2068 defects in an industrial circuit takes about 72 hours [5]. On the other hand,
the smaller simulation time required for each individual fault allows simulation of a greater
number of faults within a given simulation time, helping to improve coverage estimation
accuracy that is proportional to the square root of the number of simulated faults [5].
5.7 Discussion
From the above discussion, it can be said that the proposed method reduces fault
simulation time by a factor approximately equal to the number of SCCs during fault coverage
assessment for MOS analog circuit test evaluation.
The method proposed in this chapter is not a replacement for other techniques
mentioned that focus on reducing the number of simulated faults. It is instead complementary
to those methods and it seems highly possible to combine the proposed method with
‘sampling’ techniques to achieve a further time reduction. It is well-known that analog fault
analysis is a challenging problem and the methods described here only solve a small part of
it.
The theoretical foundation of partitioning a large-size circuit into small sub-circuits
requires a well-defined DDG. In this chapter, during construction of the graph, only the
101
dependencies for MOSFET transistors are introduced in detail. While the concept of creating
a dependency graph and partitioning the circuit based on that graph can be extended to
circuits containing bipolar transistors (BJT) or diodes, the extension to BJTs is not trivial
because the impedance at the base of a BJT cannot be generally regarded as infinite like that
of a MOSFET. Approaches to solving this problem are currently under study.
As is mentioned in the introduction, in this chapter we focused on quick fault-
coverage estimation for DC tests, and for those faults caused by energy storage elements and
known to be not detectable by DC tests, e.g., the capacitor in the benchmark circuit, existing
AC or transient fault analysis methods could be applied to improve the coverage.
Furthermore, for complex mixed-signal circuits that include clocking, fault-coverage testing
based only on DC tests might be insufficient, so the authors are also investigating approaches
to improving the time-efficiency of AC or transient analysis for analog fault simulation.
For the purposes of illustrating the proposed method, catastrophic faults were
assumed, but the method would work for parametric faults as well.
5.8 Conclusion
The systematic method introduced in this chapter significantly improves time
efficiency in estimating fault coverage for MOS analog fault simulation of DC tests. In the
proposed method, the circuit under test is partitioned into independent sub-circuits using
particular graphing techniques, followed by fault simulation performed using these sub-
circuits, an approach expected to be much more time-efficient than fault simulation using the
entire circuit. Fault coverage was estimated using both determination of simulated fault
impacts and backward sensitivity analysis. The proposed method can estimate fault coverage
with sufficient accuracy and reduce fault simulation time by a factor approximately equal to
102
the number of SCCs. Simulation results based on a benchmark circuit were used to validate
the proposed method.
103
5.9 References
[1] S. Sunter, “Closing the loop between analog design and test,” in 2016 IEEE
International Symposium on Circuits and Systems (ISCAS), 2016, pp. 894–897.
[2] S. Sunter, K. Jurga, and A. Laidler, “Using Mixed-Signal Defect Simulation to Close
the Loop Between Design and Test,” IEEE Trans. Circuits Syst. Regul. Pap., vol. 63,
no. 12, pp. 2313–2322, Dec. 2016.
[3] A. Coyette, G. Gielen, R. Vanhooren, and W. Dobbelaere, “Optimization of analog fault
coverage by exploiting defect-specific masking,” in Test Symposium (ETS), 2014 19th
IEEE European, 2014, pp. 1–6.
[4] R. Gordon and A. Sadok, “An Overview of Mixed-Signal Production Test from a
Measurement Principle Perspective,” IEEE Des. Test, no. 99, pp. 1–1.
[5] S. Sunter, K. Jurga, P. Dingenen, and R. Vanhooren, “Practical random sampling of
potential defects for analog fault simulation,” in Test Conference (ITC), 2014 IEEE
International, 2014, pp. 1–10.
[6] L. Fang, M. Lemnawar, and Y. Xing, “Cost Effective Outliers Screening with Moving
Limits and Correlation Testing for Analogue ICs,” in Test Conference, 2006. ITC ’06.
IEEE International, 2006, pp. 1–10.
[7] F. M. Goncalves and J. P. Teixeira, “Sampling techniques of non-equally probable
faults in VLSI systems,” in 16th IEEE VLSI Test Symposium, 1998. Proceedings,
1998, pp. 283–288.
[8] N. Guerreiro, M. Santos, and P. Teixeira, “Fault list compression for efficient analogue
and mixed-signal production test preparation,” in Design of Circuits and Integrated
Systems, 2014, pp. 1–6.
[9] E. Yilmaz, A. Meixner, and S. Ozev, “An industrial case study of analog fault
modeling,” in VLSI Test Symposium (VTS), 2011 IEEE 29th, 2011, pp. 178–183.
[10] W. C. Tam and R. D. Blanton, “Physically-aware analysis of systematic defects in
integrated circuits,” in Test Conference (ITC), 2011 IEEE International, 2011, pp. 1–10.
[11] W. C. Tam and R. D. Blanton, “SLIDER: Simulation of Layout-Injected Defects for
Electrical Responses,” IEEE Trans. Comput.-Aided Des. Integr. Circuits Syst., vol. 31,
no. 6, pp. 918–929, Jun. 2012.
[12] W. C. Tam and R. D. Blanton, “SLIDER: A fast and accurate defect simulation
framework,” in VLSI Test Symposium (VTS), 2011 IEEE 29th, 2011, pp. 172–177.
104
[13] E. Yilmaz and S. Ozev, “Defect-based test optimization for analog/RF circuits for near-
zero DPPM applications,” in IEEE International Conference on Computer Design,
2009. ICCD 2009, 2009, pp. 313–318.
[14] E. Yilmaz and S. Ozev, “Fast and Accurate DPPM Computation Using Model Based
Filtering,” in Test Symposium (ETS), 2011 16th IEEE European, 2011, pp. 165–170.
[15] E. Yilmaz, G. Shofner, L. Winemberg, and S. Ozev, “Fault analysis and simulation of
large scale industrial mixed-signal circuits,” in Design, Automation Test in Europe
Conference Exhibition (DATE), 2013, 2013, pp. 565–570.
[16] B. Esen, A. Coyette, G. Gielen, W. Dobbelaere, and R. Vanhooren, “Effective DC fault
models and testing approach for open defects in analog circuits,” in 2016 IEEE
International Test Conference (ITC), 2016, pp. 1–9.
[17] T. W. Williams and N. C. Brown, “Defect Level as a Function of Fault Coverage,”
IEEE Trans. Comput., vol. 30, no. 12, pp. 987–988, 1981.
[18] C. Xue and R. D. S. Blanton, “Predicting IC Defect Level Using Diagnosis,” in 2014
IEEE 23rd Asian Test Symposium, 2014, pp. 113–118.
[19] B. Kruseman et al., “Defect Oriented Testing for analog/mixed-signal devices,” in Test
Conference (ITC), 2011 IEEE International, 2011, pp. 1–10.
[20] S. K. Sunter, “Defect injection for transistor-level fault simulation,” US8984460 B2,
17-Mar-2015.
[21] Z. Liu, Y. Li, Y. Duan, R. L. Geiger, and D. Chen, “Identification and break of positive
feedback loops in Trojan States Vulnerable Circuits,” in 2014 IEEE International
Symposium on Circuits and Systems (ISCAS), 2014, pp. 289–292.
[22] Z. Liu, Y. Li, Y. Duan, R. L. Geiger, and D. Chen, “Identification and break of positive
feedback loops in Trojan States Vulnerable Circuits,” in 2014 IEEE International
Symposium on Circuits and Systems (ISCAS), 2014, pp. 289–292.
[23] K. Ruohonen, Graph theory, Graafiteoria lecture notes, TUT. 2013.
[24] R. Tarjan, “Depth-First Search and Linear Graph Algorithms,” SIAM J. Comput., vol.
1, no. 2, pp. 146–160, Jun. 1972.
[25] S. J. Spinks, C. D. Chalk, I. M. Bell, and M. Zwolinski, “Generation and Verification of
Tests for Analog Circuits Subject to Process Parameter Deviations,” J. Electron. Test.,
vol. 20, no. 1, pp. 11–23, Feb. 2004.
105
[26] Z. Wang, G. Gielen, and W. Sansen, “A novel method for the fault detection of analog
integrated circuits,” in Proceedings of IEEE International Symposium on Circuits and
Systems - ISCAS ’94, 1994, vol. 1, pp. 347–350 vol.1.
[27] D. Sanjoy, “Note three: Strongly Connected components.” [Online]. Available:
http://www.cc.gatech.edu/~mihail/D.dasgupta/3.pdf. [Accessed: 19-Dec-2016].
[28] C.-H. Wang, “Computer-aided manipulation of mason’s formula and its applications,”
Int. J. Circuit Theory Appl., vol. 20, no. 4, pp. 357–370, Jul. 1992.
[29] Z. Bubnicki, Modern Control Theory. Springer Science & Business Media, 2005.
[30] N. B. Hamida, K. Saab, D. Marche, B. Kaminska, and G. Quesnel, “LIMSoft:
automated tool for design and test integration of analog circuits,” in Proceedings
International Test Conference 1996. Test and Design Validity, 1996, pp. 571–580.
[31] T. Olbrich, J. Perez, I. A. Grout, A. M. D. Richardson, and C. Ferrer, “Defect-oriented
vs schematic-level based fault simulation for mixed-signal ICs,” in Proceedings
International Test Conference 1996. Test and Design Validity, 1996, pp. 511–520.
[32] A. Jee and F. J. Ferguson, “Carafe: an inductive fault analysis tool for CMOS VLSI
circuits,” in Digest of Papers Eleventh Annual 1993 IEEE VLSI Test Symposium,
1993, pp. 92–98.
106
CHAPTER 6. IMPROVING ANALOG FAULT-COVERAGE WITH SYSTEMATIC
TEST-POINTS SELECTION AND CONCURRENT SAMPLING
6.1 Introduction
Quality requirements for modern integrated circuit (IC) applications, such as those in
the aerospace and automotive areas, are becoming increasingly stringent. This trend poses
grand challenges to the important process of improving fault coverage, i.e., to prevent
malfunctioning ICs from being shipped to customers.
While testing for faults in the digital part of System-on-Chips (SoCs) is typically
achieved with scan chains [1], replicating this success for analog circuits is not as
straightforward. In general, the primary analog outputs provide very limited observability,
making it virtually impossible to achieve high fault coverage for analog circuits without
observing internal nodes [2]. For example, while fault coverage of a voltage regulator circuit
was shown to be only about 30 percent when only the primary output was observed, fault
coverage jumped to 86 percent if some of the internal nodes were observed [3]. Some
preliminary methods for identifying the required minimal set of observation points to achieve
high fault coverage for catastrophic faults have been investigated in [4].
Although researchers tend to believe that observing some internal nodes is one
effective technique for improving fault coverage, exactly how to access these nodes still
remains challenging in reality. Some form of the Analog test bus (ATB) has traditionally
been utilized for over 30 years to access internal nodes [5]–[7], and it continues to be one of
the most popular embedded test access methods for analog observability. However, the ATB
has some major limitations. Large RC loading and kickback among probe nodes make it very
challenging or nearly impossible to meet high-quality requirements, especially when real-
time fault detection is considered. Other methods have recently been proposed to overcome
107
some of these limitations, e.g., the Local Detection and Transmission System (LDTS) [2], in
which local threshold detection blocks are added at internal nodes and coupled to an
oscillator. The triggering of this oscillator when defects are detected leaves traces in the
power consumption. While this method enables fault detection it does not enable fault
diagnosis. In addition, since its fault detection is based on a single bit, the LDTS method is
unsuitable for detecting parametric faults. It is known that hard faults can manifest as
parametric effects in a circuit, e.g., as an open or a short of one finger of a MOSFET.
Furthermore, in cases such as automotive ICs etc., the requirement of guaranteeing
functional safety and reliability gives rise to the need for real time, post-deployment
monitoring of ICs to detect even latent faults, and none of the above-mentioned strategies are
suitable for real time monitoring.
This chapter proposes an approach to improving fault coverage in analog circuits
using systematic test-point selection and concurrent sampling. The central idea is to identify
a test point set (TPS) by using a recursive backward method. The determined TPS is
expected to increase the observability of certain faults that otherwise would be undetectable
at the primary outputs of the overall system. A technique for concurrent sampling with local
digitization is introduced to measure a multitude of analog DC voltages [8], and by
concurrentlymonitoring these test point voltages, the fault coverage can be significantly
improved, making real-time monitoring possible. The main contributions of this chapter are
summarized as follows.
• The proposed method can significantly improve the test coverage of embedded
analog functions by monitoring internal test-points; determination of these test-
points is automatic and systematic.
108
• By using concurrent sampling with local digitization, the proposed method allows
simultaneous monitoring of multiple nodes with multi-bit resolution; moreover, it
enables real-time measurement of analog voltages.
• The proposed method is suitable for detecting parametric faults as well as hard
fault-induced parametric effects because of its capability for monitoring test-
points with multi-bit resolution.
• The design overhead and loading effects introduced by the concurrent sampling
method are much smaller than those of conventional analog test buses.
The remainder of this chapter is organized as follows. Section 6.2 previews the
skeleton of the proposed method. Section 6.3 uses an example circuit to describe an
effective method of identifying a set of test-points using a recursive backward method.
Section 0 describes how to combine the recursive backward method and concurrent
sampling. Section 0 demonstrates the effectiveness of the proposed method by applying it to
a benchmark circuit. Section 0 offers concluding remarks.
6.2 Overview of Proposed Method
Fault coverage (FC) is an important test metric that expresses test quality of an
integrated circuit. It is defined as the percentage of modeled faults that can be detected by the
test. There are several major tasks in practical fault coverage analysis.
1. Model the effect of manufacturing defects and obtain a fault list to be simulated.
2. Determine the test-points that achieve the desired FC.
3. Take measurements at these test-points of a circuit under test (CUT) at these test-
points and send the results out for evaluation.
4. Use the measurement data to decide whether a fault exists in the CUT.
109
Circuit Netlist
TPS at sink SCCs
FC evaluation
Fault listDDG & SCCs
Final TPS
Fault
simulation
Achieve desired FC?
or DDG is empty
Reduced DDG
Layout
Y
N
Concurrent Sampling
Figure 6.1 Flowchart of the proposed method
The fault list can be generated based on customer returns, design experience,
schematic-based models, or layout-based models [9], [10]. Sampling techniques for selecting
“representative” faults to simulate have been studied [11]–[13].
Because of their low cost and widespread applicability, the importance of DC tests
for analog fault coverage analysis has been pointed out in [14]. It is shown that fault
coverage can be improved at very low cost by introduction of new DC fault models and
testing approaches [14].
In this chapter, we will focus on addressing Tasks 1 and 2 above.
The flowchart of the proposed method is illustrated in Figure 6.1. The method starts
by converting the circuit netlist into a directed dependency graph (DDG) that is then
partitioned into a set of disjoint strongly connected components (SCCs). The SCC
information is utilized to reduce the DDG to a simple acyclic graph with each SCC
represented as a super vertex. This enables us to determine a TPS at the sink SCCs, and fault
110
detectability and FC at the TPS can then be evaluated. If the FC does not meet the desired
requirement, a recursive backward propagation method can be used to include additional
internal nodes to cover more faults. During each iteration, a reduced DDG is created (by
removing sink SCCs) and a reduced fault list can be generated (by removing detected faults).
In the reduced DDG, new sink SCCs are obtained and additional nodes are added to the TPS.
A final satisfactory TPS is obtained when either the FC meets the desired requirement or the
resulting reduced DDG is empty. Concurrent sampling along with local digitization
techniques is then utilized to export the analog TPS voltages for monitoring.
6.3 Test-Points Set
In this section, we define a method to systematically determine a set of test-points
(TPS) to improve fault coverage. We first define a method to construct the DDG and to
partition it into disjoint strongly connected components using the simple example circuit
shown in Fig.2. The recursive backward method for determining a TPS is then presented.
6.3.1 Directed Dependency Graph
The concept of directed dependency graphs (DDG) has been successfully used for
analog fault analysis by the authors in [4], [15] to achieve excellent results. An EDA tool
was developed and implemented in Cadence Virtuoso to automatically convert a circuit
netlist into a DDG. An important property of the DDG is that it captures a circuit’s critical
dependencies between voltages and currents. For the purpose of decomposing a circuit into
sub-circuits, this property is very useful because it allows us to know which voltages and
currents are correlated. In this subsection, we will briefly use one example circuit to review
the related definitions and point out some concepts that will be utilized in the next
subsection.
111
For a CUT, a directed dependency graph is defined as a directed graph DDG(V, E),
where the vertex set V represents all voltages and currents in the circuit and the edge set E
stands for the directed dependencies between voltages and currents. As an example, the DDG
of Figure 6.2(a) is shown in Figure 6.2(b). For notational convenience, we label a vertex
(either current or voltage) in the graph using the corresponding circuit variable names. The
motivation for constructing a graph representation of a circuit is that permits standard graph
theory techniques to be employed in systematically decomposing it into subgraphs and to
apply recursive methods. We will next introduce SCC concepts and show how to employ
standard graph theory techniques to decompose a DDG into SCCs.
Any directed graph can be partitioned into a set of disjoint strongly-connected
components [16]. The most important property of an SCC is that for vertices 𝑢 and 𝑣, if
𝑢 and 𝑣 are in the same SCC, then 𝑢 and 𝑣 will have bi-directional dependency. This means
that any voltage or current change at 𝑢 (𝑣) will cause voltage or current change at 𝑣 (𝑢)
following the 𝑢 − 𝑣 (𝑣 − 𝑢 ) path. On the other hand, if 𝑢 and 𝑣 are in different SCCs, then
𝑢 and 𝑣 will have uni-directional dependency. This SCC property provides the basis for
partitioning a circuit into sub-circuits. Only one-directional dependency exists between nodes
lying in different sub-circuits. A sink SCC of is one with no edges emanating from it. As an
example, three SCCs are identified for the DDG shown in Figure 6.2(b), where the dashed
shaded regions are used to separate the SCCs. This example only has one sink SCC, SCC3.
If we use a single super-vertex to represent each SCC, the resulting graph is ‘shrunk’.
This shrunk graph is guaranteed to be a directed acyclic graph (DAG) [15] with forward
paths only and hence a straightforward recursive backward analysis is possible. Figure 6.3
shows the DAG for the DDG shown in Figure 6.2.
112
M3 M4
M1 M2
V1
V2
I1
I4
M5
M6
Vo
M9
M7
M8
I3
I6IR1 R1
I2I5I7
I8
I9
gnd
vdd
V3
V4
(a)
I1
I4
I3
V1
V2
I5
I6
I9
IR1V3
I2
Vo
I7
I8
V4
SCC1 SCC2 SCC3
(b)
Figure 6.2 Example circuit: Widlar bias generator, (a) schematic (b) DDG with with SCCs
6.3.2 Recursive Backward Propagation Method
In this subsection, a formal method based on graph theory and DDGs and SCCs
concepts used to systematically determine a TPS will be developed.
For a given circuit, a test point (TP) is a selected node in the CUT where certain faults
can be detected by observing or monitoring vertex v. Due to the way a circuit is converted
into the DDG, it is possible to find a vertex in the DDG with the same name as one in the
circuit. The terms “observe” and “monitor” mean measuring and comparing the voltage of
this circuit node. A test point set is a set or a group of test-points.
113
SCC1 SCC2 SCC3
Figure 6.3 The DAG for the DDG shown in Figure 6.2
It has been shown in [4] that a set Si formed by taking one vertex from each sink SCC
of a DDG has the property that all potential faults can be theoretically detected at these
vertices. This is due to the fact that any vertex in the DDG has a path to vertices in Si so that
a fault that affects an arbitrary vertex in the DDG can propagate to Si. The reason we qualify
our statement as “theoretical” is because the propagation of a fault to test-points does not
guarantee that the fault will cause a large enough voltage or current change at the test-points
for it to be detected. We next introduce through a simple example the recursive backward
propagation method of adding test-points.
Suppose we have the DAG shown in Figure 6.4(a). It has three SCCs (SCC1, SCC2
and SCC3). First of all, we will determine which SCC a fault will directly impact. The term
“impact” means causing a voltage or current change to a vertex of the DDG. As shown in
Figure 6.4(a), 𝑓11, 𝑓12, … , 𝑓1𝑛 are the faults that directly impact SCC1; 𝑓21, 𝑓22, … , 𝑓2𝑚 are the
faults that directly impact SCC2, and so on. The impact of each fault can be simulated using
either standard defect-oriented method [17] or the method introduced in [15] for speedup
consideration.
The recursive backward method starts from the sink SCC (or sink SCCs), SCC3 in
Figure 6.4(a). Suppose 𝑉𝑜 is the identified TP for SCC3. Following the strategies
introduced in [15], we label the detectability of all faults at test point 𝑉𝑜 . Suppose the
detection range at 𝑉𝑜 is 𝐷𝑜. If the impact in 𝑉𝑜 due to a fault is greater than |𝐷𝑜|, this means
that this fault can be detected at 𝑉𝑜 and we will label it with ‘1’; otherwise we will label it
114
SCC1 SCC2 SCC3
... ... ...f11 f12 f1n f21 f22 f2m f31 f32 f3k
SCC1 SCC2 SCC3 Vo
0 1 1 0 0 1 1 1 1
G1SCC1 SCC2
f11f21 f22
1 1 0
V1
(a)
(b)
(c)
... ... ...f11 f12 f1n f21 f22 f2m f31 f32 f3k
Figure 6.4 Recursive backward method (a) DAG with fault impacts in each SCC (b) first iteration
(c) second iteration
with ‘0’ as shown in Figure 6.4(b). Again, while this is one possible way to determine fault
detectability, it is not necessary. After all sink SCCs have been examined, if all faults have
been labeled with ‘1’, this means that complete fault coverage has been achieved. If there are
still faults labeled with ‘0’, to detect them we must add additional vertices as test-points . To
achieve this, we first remove the existing sink SCCs from the DDG to producde a reduced
DDG. In the reduced DDG, new sink SCCs are obtained and we can define corresponding
TPS for this new set of sink SCCs. Note that the process of making them into actual test-
points is described in the next section. The afore-described procedure is then used to
determine fault detectability at this TPS. Each as yet undetected fault is then further labeled
as ‘1’ or ‘0’ depending on whether or not it is detectable at the new TPS. If one such fault is
115
indeed detectable at the new TPS, the vertex corresponding to the new TPS is added to the
previous TPS.
Figure 6.4(b) shows the first iteration in which SCC3 is the original sink SCC and 𝑉𝑜
is the selected TP. Figure 6.4(c) shows the second iteration where SCC2 is the new sink SCC
and 𝑉1 is identified as the new TP. This recursive process can be repeated until either all
faults are labeled as detected or the reduced DDG becomes empty. The algorithm is
presented below.
Algorithm: Recursive backward method to obtain TPS Input: DDG, fault_list Obtain SCCs and sink SCCs for the DDG, TPS= ∅ While fault_list ≠ ∅ & DDG≠ ∅
For each sink SCC(i) Do Determine the TP of SCC(i) For each fault f in the fault_list
If f is detectable at TP then Label f as ‘1’ fault_list = fault_list –f TPS = TPS U TP
End if End For Remove vertices of sink SCC(i) from the DDG
End for In the reduced DDG, obtain new sink SCCs
End while
6.4 Concurrent Sampling with Local Digitization
In this section, a method of combining the recursive backward method and concurrent
sampling is introduced. Since the output of the recursive backward method is a list of nodes
that need to be measured, the next step is to develop an actual hardware implementation to
make these test-points observable.
116
Local digitization is performed using the architecture shown in Figure 6.5. Each node
that needs to be monitored drives the ‘+’ input of a comparator (also called a local digitizer),
while the ‘-‘ input is driven by a voltage reference 𝑉𝑟𝑒𝑓. The node voltage is “measured” by
sweeping 𝑉𝑟𝑒𝑓 in a range (say from a low to a high value) and recording the 𝑉𝑟𝑒𝑓 value at
which the output of the comparator switches from 1 to 0. The step size of 𝑉𝑟𝑒𝑓 can be varied
depending on the desired resolution,. Similarly, care in designing the 𝑉𝑟𝑒𝑓 generation circuit
depends on the desired accuracy.
Figure 6.5 Local Digitization
Voltage nodes in the TPS resulting from the backward-recursive method are
concurrently sampled with local digitizers and held in digital storage elements (FFs), as
shown in Figure 6.6, and FF contents can be read out in one of many ways. Figure 6.6
suggests an implementation in which the FF contents are shifted out through one or more
scan chains. An IJTAG network [18] can also be used to send out the data, as discussed in
[8].
D Q
NodeUnder Test
FF
Local
Connection
VREF
CLK
Scan_Enable
Comparator: 1-Bit Digitizer
FF
Local Connection
117
Figure 6.6 Architecture of the proposed Concurrent Sampling method
This CS method overcomes several limitations of the ATB. In local digitization, a
comparator can be used instead of a full ADC to avoid area and power overhead. The variety
of test-points requires flexibility in measurement resolution, and from the authors’ experience
in real implementation, the group of nodes can be roughly divided into three categories: 1)
Most nodes, for example, switches controlling nodes in digital trimming circuits, require only
1-bit resolution. 2) Some nodes, e.g., biasing voltages of cascode transistors, require medium
resolution. Three or four-bit resolution is enough to verify that transistors are working in
saturation. 3) Very few nodes, e.g., the supply voltage of analog blocks, may require testing
with high resolution. Sincde measurement resolution is controlled by VREF step size, we can
achieve flexible resolution by controlling VREF sweep and select suitable MUXs and
comparators.
With a given ATB-ADC pair, only one node can be measured at a time due to large
RC loading and kickback effects. With the proposed local digitization, cross-coupling of
nodes between different blocks is totally eliminated, so multiple nodes can be measured at
the same time with the shared VREF sweep. This significantly reduces conversion time,
Node 1
Node 2
Node n
Analog and Mixed-signal IP(s)
1-BitDigitizer
1-BitDigitizer
1-BitDigitizer
DAC
CLK Scan_Enable
VREF
Scan Chain
TDO
118
especially in SoCs with a large number of test-points. Note that the ground reference voltage
inside a block is itself a test point. Comparator sharing, voltage node ordering, and VREF
phase control can all be further implemented to reduce area overhead and total measurement
time. These enhancements are beyond the scope of this chapter and will not be further
discussed.
Table 6.1 Differences between ATB and CS
Analog Test Bus Concurrent Sampling
Dif
feren
ces
One node at a time Multiple nodes concurrently
Large 1-hot MUX Small decoded MUXs
Large variable RC load Small static local RC load
Upper layer metals Lower layer metals
Production test • Production test
• Real-time monitoring
Differences between ATB and CS are summarized in Table 6.1. It can be seen that,
by using concurrent sampling with local digitization, the proposed method allows
simultaneous monitoring of multiple nodes with multi-bit resolution along with real-time
measurement of analog voltages. Design overhead and loading effects introduced by the
concurrent sampling method are much smaller than for a conventional analog test bus.
6.5 Case Study
In this section, the proposed method is applied to the benchmark circuit shown in
Figure 5.9. To demonstrate the effectiveness of the proposed method, a fault list containing
268 selected faults given by the user will be considered. Virtuoso Spectre was used for
simulation.
119
Results from the iterations of the proposed recursive backward method are
summarized in Table 6.2. First, the system outputvout is used as the test point, and the
fault coverage is only 33.21 %. During the first iteration, four sink SCCs were found and
vout, Vref, n6, p7 was determined as the TPS. For this situation, the overall fault coverage
increased to 77.61%. During the second iteration, the original four sink SCCs are removed
from the graph, and in the reduced graph two new sink SCCs can be identified and another
two test-points ‘vpa’ and ‘Vaa’ added to the overall TPS, resulting in a FC of 85.07%.
Finally, after three iterations, the graph has again been traversed to produce a final achieved
T55
T56
T57
T58
T47
T48
T49
T50
T12
T14
T16
T18
VDD
T15
T17
T11
T13
T33
T34
T31 T32
T59
T60
T61
T62
T51
T52
T53
T54
T20
T22
T24
T26
VDD
T23
T25
T19
T21
T28
T27
T29 T30
T2
T4
T6
T8
T5
T7
T1
T3
T9
T10
T36T35
T37
T63
T64
T39T40
T41 T42
T44T43 T46
T45
VD
DV
SS
VSS
VSS
R9
T8 C2
V2
V3 V4
V1
R6
R6
R5 R2R3 R1
T38
p6
p7
p8
wp3
wp4
wp3
wp4
wp3
wp4
wp3
wp4
b2
b1
p5
p4
wp1
wp2
p9
p10
n6
n7
n8
n4
n2
n6
n6
n6
n1 wn1
wn2
wn1
wn2
wn1
wn2
wn3
wn4
b3
n5
vin vip
vin vip
b3
b1
b2
b4
Vr
vo1 vout
vstart
Vr VrVr
Vr
Vaa
Vab
VabVaa
Vr
vpa vpbvpbvpa
vnbvna
vnbvna
P-cascode
biasing
Opamp
biasing 1
P-type
WidlarOpamp core
N-cascode
biasing
Opamp
biasing 2
N-type
WidlarBanba
Simulation Setup
vip
vin vout
Opamp core
R4
Vref
generator
Vref
Figure 6.7 Benchmark circuit with the test-points highlighted with different color a) Red: from iteration 0; b) Blue: from
iteration 1; c) Green: from iteration 2; d) Purple: from iteration 3
120
coverage of 89.55%. The test-points identified in this recursive procedure is highlighted with
different color in Figure 6.7.
With the CS method, glitches resulting from node switching, comparator CLK and
VREF sweeps are attenuated by an order of magnitude compared to those when using the
ATB. Simple strongARM latch comparators are used, with each taking ~10 um2 of area and
negligible quiescent current in the GlobalFoundries 130num process. After the comparator
sharing technique was implemented, area and power overhead of the CS method is no longer
a problem.
Table 6.2 Iterations of The Recursive Backward Method
Iteration TPS Overall FC
0 vout 33.21%
1 vout, Vref, n6, p7 77.61%
2 vout, Vref, n6, p7, vpa, Vaa 85.07%
3 vout, Vref, n6, p7, vpa, Vaa, p4, n5, Vsart 89.55%
Table 6.3 provides the comparison of the proposed TPAC method with state-of-the-
art methods. It can be seen that the proposed method provides an efficient solution to
searching for test-points to significantly improve the FC. Because of the use of concurrent
sampling, soft-fault detection, fault diagnosis, and real-time monitoring become possible.
Table 6.3 Comparison with the state-of-the-art methods
Paper Reduce
Simulation time
Improve
FC
Detect soft
fault
Fault
diagnosis
Real time
Monitoring
Sunter’13 YES NO YES NO NO
Coyette’16 NO YES NO YES NO
Proposed YES YES YES YES YES
121
6.6 Conclusion
This chapter presents a systematic procedure for improving the test coverage of
embedded analog functions without requiring much added design overhead. This is achieved
by monitoring the voltage of a few test-points in the circuit with concurrent sampling. A
recursive backward method has been proposed for automatically selecting these test-points
and a concurrent sampling technique has been introduced for monitoring these points. Using
the proposed method, the fault coverage can be greatly improved and soft-fault detection,
fault diagnosis, and real-time monitoring become possible. This work could be applied to
manufacturing testing or for real-time fault detection.
122
6.7 References
[1] L.-T. Wang, C. E. Stroud, and N. A. Touba, System-on-Chip Test Architectures:
Nanometer Design for Testability. Burlington : Elsevier Science, 2010.
[2] A. Coyette, B. Esen, R. Vanhooren, W. Dobbelaere, and G. Gielen, “Automatic
generation of autonomous built-in observability structures for analog circuits,” in 2015
20th IEEE European Test Symposium (ETS), 2015, pp. 1–6.
[3] A. Coyette, B. Esen, W. Dobbelaere, R. Vanhooren, and G. Gielen, “Automatic
generation of test infrastructures for analog integrated circuits by controllability and
observability co-optimization,” Integr. VLSI J., vol. 55, pp. 393–400, Sep. 2016.
[4] Z. Liu, S. K. Chaganti, and D. Chen, “Toward complete analog fault coverage with
minimal observation points using a fault propagation graph,” in 2016 IEEE
International Symposium on Circuits and Systems (ISCAS), 2016, pp. 1282–1285.
[5] P. P. Fasang, D. Mullins, and T. Wong, “Design for testability for mixed analog/digital
ASICs,” in Proceedings of the IEEE 1988 Custom Integrated Circuits Conference,
1988, p. 16.5/1-16.5/4.
[6] C. L. Wey, “Built-in self-test (BIST) structure for analog circuit fault diagnosis,” IEEE
Trans. Instrum. Meas., vol. 39, no. 3, pp. 517–521, Jun. 1990.
[7] L. T. Wurtz, “Built-in self-test structure for mixed-mode circuits,” IEEE Trans. Instrum.
Meas., vol. 42, no. 1, pp. 25–29, Feb. 1993.
[8] N. Liu, S. K. Chaganti, Z. Liu, D. Chen, and A. Majumdar, “Concurrent Sampling with
Local Digitization - An Alternative to Analog Test Bus,” in 2018 IEEE
International Symposium on Circuits and Systems (ISCAS), 2018.
[9] J. P. Shen, W. Maly, and F. J. Ferguson, “Inductive Fault Analysis of MOS Integrated
Circuits,” IEEE Des. Test Comput., vol. 2, no. 6, pp. 13–26, Dec. 1985.
[10] A. Jee and F. J. Ferguson, “Carafe: an inductive fault analysis tool for CMOS VLSI
circuits,” in Digest of Papers Eleventh Annual 1993 IEEE VLSI Test Symposium,
1993, pp. 92–98.
[11] F. M. Goncalves and J. P. Teixeira, “Sampling techniques of non-equally probable
faults in VLSI systems,” in 16th IEEE VLSI Test Symposium, 1998. Proceedings,
1998, pp. 283–288.
[12] N. Guerreiro, M. Santos, and P. Teixeira, “Fault list compression for efficient analogue
and mixed-signal production test preparation,” in Design of Circuits and Integrated
Systems, 2014, pp. 1–6.
123
[13] S. Sunter, K. Jurga, P. Dingenen, and R. Vanhooren, “Practical random sampling of
potential defects for analog fault simulation,” in Test Conference (ITC), 2014 IEEE
International, 2014, pp. 1–10.
[14] B. Esen, A. Coyette, G. Gielen, W. Dobbelaere, and R. Vanhooren, “Effective DC fault
models and testing approach for open defects in analog circuits,” in 2016 IEEE
International Test Conference (ITC), 2016, pp. 1–9.
[15] Z. Liu, S. K. Chaganti, and D. Chen, “Improving Time-Efficiency of Fault-Coverage
Simulation for MOS Analog Circuit,” IEEE Trans. Circuits Syst. Regul. Pap., vol. PP,
no. 99, pp. 1–11, 2017.
[16] K. Ruohonen, Graph theory, Graafiteoria lecture notes, TUT. 2013.
[17] B. Kruseman et al., “Defect Oriented Testing for analog/mixed-signal devices,” in Test
Conference (ITC), 2011 IEEE International, 2011, pp. 1–10.
[18] “IEEE Standard for Access and Control of Instrumentation Embedded within a
Semiconductor Device,” IEEE Std 1687-2014, pp. 1–283, Dec. 2014.
124
CHAPTER 7. CONCLUSION
This research investigates two design and verification issues that impact the
reliability of high-performance analog circuits. One is the multi-state issue encountered
during the design stage and caused by the existence of positive feedback. and the other is the
set of fault coverage issues during the manufacturer process. To determine the presence or
absence of multi-states, a systematic procedure is proposed for identifying and breaking
positive feedback loops of a circuit and performing a break-loop homotopy method. To
improve fault coverage for analog circuits, a practical and efficient method for improving
fault coverage at reasonable cost and time is introduced.
Firstly, the design of a low temperature coefficient voltage reference generator is
proposed to target the problem of extracting the VGO from the temperature characteristic of
positively-biased PN junction voltage VBE. VGO is the silicon band gap voltage extrapolated at
zero Kevin and is a constant voltage independent of temperature, supply, and process over a
very wide temperature range. Analytical constraints that lead to strategies for creating an
output voltage proportional to VGO when certain mismatches and offsets are accurately
trimmed have been carefully investigated. The proposed method is implemented in the
GlobalFoundries 130nm process. Simulation results show that the design can achieve
temperature coefficients as low as 0.7ppm/°C over the range -40°C to 125°C over process
corners.
Second, a systematic method is proposed for automatically identifying positive
feedback loops (PFLs) vulnerable to multiple operating points. in analog/mixed-signal
circuits. The method first converts the netlist of a circuit into a directed dependency graph
(DDG) that captures critical relationships among branch currents and node voltages. It then
125
utilizes graph theory techniques to find all feedback loops from the DDG and, finally, a
criterion for determining the PFLs is developed. Since multiple states is caused by the PFLs,
this method could identify a circuit’s vulnerability to undesigned operating points through
only its structure without the computation required of DC solutions. The proposed approach
was implemented in a program and simulation results show that it could identify all the PFLs
very robustly.
Third, a method is proposed for breaking PFLs in a Multi-state vulnerable circuit. At
the breaking-points detemined, a break-loop homotopy sweep method can be applied to
verify the presence or absence of undesigned operating points. Questions of how and where
to break PFLs is challenging for many circuits, particularly as the circuit becomes large and
feedback structures become complex. To overcome this difficulty, graph theory techniques
are employed to partion a complex circuit graph into disjoint Strongly-Connected
Components (SCCs). Based on this concept, the PFL detection of and breakpoint locating
can be performed for every SCC. This limits the sweep dimension of the break-loop
homotopy sweep method to within one or two even for a large-scale circuit. Using Sub-
Bandgap reference and widlar-Banba examples, it is demonstrated that the proposed
approach can effectively identify all the SCCs and corresponding breakpoints.
Next, a systematic method for significantly improving time efficiency in estimating
the fault coverage for analog fault simulation is introduced. In the proposed method, a circuit
under test (CUT) is first partitioned into independent sub-circuits. The impacts of potential
faults directly entering a sub-circuit are then simulated and recorded using these sub-circuits,
a proess expected to be much more time-efficient than fault simulation using the entire much
larger circuit . Finally, the fault detectability at the given test-points is evaluated based on
126
fault impacts and sensitivity among different sub-circuits. As a first step toward quick
estimation of fault coverage, this chapter focuses on DC tests, and simulation results show
that the fault coverage measured by such tests can be estimated with sufficient accuracy, with
simulation reduced by 10X, or approximately the number of SCCs for the benchmark circuit.
For a much larger circuit, the number of SCCs is expected to be much larger and the time-
saving factor will be much larger.
Finally, A novel concurrent test-point selection and sampling method is introduced
for significantly improving fault coverage of analog circuits. The method has two major
parts. The first is to select a set of test-points using a recursive backward method such that
the knowledge of values of the selected test-points is sufficient to tell whether a fault has
occurred in the circuit. Since the selected test-points could be internal, concurrent sampling
with local digitization to observe the value of these test-points is proposed. The proposed
concurrent sampling method achieves multi-bit resolution and thus enables detection of both
catastrophic (hard) and parametric faults. As part of the concurrent sampling, the
measurement results are sent out as digital values. The proposed TPAC method can be used
for off-line manufacturer testing as well as for real-time fault detection.
127
APPENDIX A. PROGRAMS FOR IDENTIFYING AND BREADING FEEDBACK
LOOPS OF A CIRCUIT
1. Main.pl
#! /usr/bin/perl
use strict;
use warnings;
use lib './ITV/breakLoop/Strong_conn_comp/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
require './ITV/breakLoop/findPath.pl';
my $start_time=time();
my $start_time2=localtime();
my $debugFlag=1; #determine wether to print out information
if($debugFlag==1)
print "start at:$start_time2\n";
####open the net_from_cadence that generated from Cadence.
#open( MYFILE, "shimit.scs") || die "Can't open myfile: $!";
#open( MYFILE, "./ITV/selfbias_banba_with_cap.scs") || die "Can't open myfile: $!";
#open( MYFILE, "./ITV/myFile_hier_test") || die "Can't open myfile: $!";
#open( MYFILE, "./ITV/myFile") || die "Can't open myfile: $!";
system("perl ./ITV/breakLoop/flattenNetlist.pl >flattenNetlist.log");
open( MYFILE, "./flattenNetlist.txt") || die "Can't open myfile: $!";
my @netlist_from_cadence=<MYFILE>;
if($debugFlag==1)
print @netlist_from_cadence;
close(MYFILE);
####store the useful information in a hash
#my @netlist_usf=grep /(^\w+\d+\s.*\))/, @netlist_from_cadence;
#=================================================
# this is used to include the terminal line <==/^\(/
128
my @netlist_usf=grep /^\w+\d/ || /^\(/, @netlist_from_cadence;
#=================================================
#################################
#fowlloing code is to get the power
#supply node from the form
################################
my @myPowerSupply=grep /^MyV/, @netlist_from_cadence;
if($debugFlag==1)
print @myPowerSupply;
my $myVdd;
my $myVss;
my $path_begin='vdd!';
my $path_end='gnd!';
my %path_begin;
my %path_end;
$path_begin'vdd!'=1;
$path_end'gnd!'=1;
foreach (@myPowerSupply)
if(/^MyVdd\:\s\"(.*)\"/)
$myVdd=$1;
map($path_begin$_=1,split(/ /,$1));
elsif(/^MyVss\:\s\"(.*)\"/)
$myVss=$1;
map($path_end$_=1,split(/ /,$1));
if(defined $myVdd)
$path_begin=$myVdd;
#delete $path_begin'vdd!';
if(defined $myVss)
$path_end=$myVss;
#delete $path_end'gnd!';
############get the dependencies that we assigned for symbols
my @mySymbolDepden=grep /^MyDep/, @netlist_from_cadence;
if($debugFlag==1)
print @mySymbolDepden;
129
my %symbolDepen;
foreach (@mySymbolDepden)
if(/^MyDep\:\s\(\"(.*)\"\)/)
my @temp=split(/\" \"/,$1);
#push @SymboleDepden, $1;
my $depenName=$temp[0].$temp[1];
$symbolDepen$depenName=[@temp];
if($debugFlag==1)
print $depenName,"\n";
my %net_from_symbolDepen;
#print @SymboleDepden,"\n";
foreach (keys %symbolDepen)
if($debugFlag==1)
print $_,": ", @$symbolDepen$_,"\n";
for (my $i=0;$i<@$symbolDepen$_-1;$i++)
push @$net_from_symbolDepen@$symbolDepen$_[$i], $_;
if($debugFlag==1)
print "\n**net_from_symbolDepen**\n";
foreach (keys %net_from_symbolDepen)
if($debugFlag==1)
print "$_,=>@$net_from_symbolDepen$_\n";
#################################
#fowlloing code is to get the netlist
################################
if($debugFlag==1)
print "\n**processing the netlist**\n";
#print "netlist_usf:", @netlist_usf;
my %netlist_hash;
my %netlist_usf;
130
my %instance_prop;
my %instance_terminal;
#foreach $_ (@netlist_usf)
for (my $i=0;$i<@netlist_usf;$i++)
$_=$netlist_usf[$i];
if(/^(\w+\d+)\s+\(\"(.*)\"\)\s+(\w+)\s/)
$netlist_hash$1=[split(/\" \"/,$2)];
if($debugFlag==1)
print "$1 => @$netlist_hash$1 \n";
$instance_prop$1=$3;
#=========================================================
#########store the terminal infor.
my $instName=$1;
my $nextLine=$netlist_usf[$i+1];
if($nextLine=~/^\(\"(.*)\"\)/) #this considering ("D" "B" "G" "S")
$instance_terminal$instName=[split(/\" \"/,$1)];
if($nextLine=~/^\(\'(.*)\'\)/)#this considering ('D' 'B' 'G' 'S')
$instance_terminal$instName=[split(/\' \'/,$1)];
#=========================================================
elsif(/^(\w+\d+.*)\s+\(\"(.*)\"\)\s+(\w+)\s/) ##this considering we have hierachical
instances which are named like "I0.I1.N4"
$netlist_hash$1=[split(/\" \"/,$2)];
if($debugFlag==1)
print "Got it!!!$1 => @$netlist_hash$1 \n";
$instance_prop$1=$3;
#=========================================================
#########store the terminal infor.
my $instName=$1;
my $nextLine=$netlist_usf[$i+1];
if($nextLine=~/^\(\"(.*)\"\)/)#this considering ("D" "B" "G" "S
$instance_terminal$instName=[split(/\" \"/,$1)];
131
if($nextLine=~/^\(\'(.*)\'\)/)#this considering ('D' 'B' 'G' 'S')
$instance_terminal$instName=[split(/\' \'/,$1)];
#=========================================================
my %netlist_banba=%netlist_hash;
=pod
my %netlist_widlar=(
N3 => [qw/C C 0 0/],
N2 => [qw/A B 0 0/],
N0 => [qw/B B C 0/],
P1 => [qw/A A vdd! vdd!/],
P0 => [qw/B A vdd! vdd!/],
V0 => [qw/vdd! 0/]);
my %netlist_shimit=(
N1 => [qw/B D C 0/],
N0 => [qw/A net5 C 0/],
R3 => [qw/0 C/],
R2 => [qw/A D/],
R1 => [qw/vdd! B/],
R0 => [qw/vdd! A/],
V0 => [qw/net5 0/]);
=cut
my %netlist_widlar=(
N3 => [qw/C gnd! C gnd!/],
N2 => [qw/A gnd! B gnd!/],
N0 => [qw/B gnd! B C/],
P1 => [qw/A vdd! A vdd!/],
P0 => [qw/B vdd! A vdd!/],
V0 => [qw/vdd! gnd!/]);
my %netlist_shimit=(
N1 => [qw/B D C gnd!/],
N0 => [qw/A net5 C gnd!/],
R3 => [qw/gnd! C/],
R2 => [qw/A D/],
R1 => [qw/vdd! B/],
R0 => [qw/vdd! A/],
V0 => [qw/net5 gnd!/]);
#######################################
#find the channel of each instance
#diode connection transistor
#gate of non-diode connection tansistor
#######################################
132
my %netlist=%netlist_banba;
my %graph;
my %gate;
my %gate_net;
my %D;
my %S;
for my $instance (keys %netlist)
$_=$instance;
if($debugFlag==1)
print "$instance:";
my $prop=$instance_prop$instance;
if($debugFlag==1)
print "$prop";
my @terminal=@$instance_terminal$instance;
if($debugFlag==1)
print "(@terminal)";
if($prop=~/^pmos|^pfet|^nmos|^nfet/)
if($debugFlag==1)
print " is COMS!!";
elsif($prop=~/pnp|npn/)
if($debugFlag==1)
print " is BJT!!";
if($debugFlag==1)
print "\n";
#if(/P|N|M\d+/)
if($prop=~/^pmos|^pfet|^nmos|^nfet/) #means this is a coms transistor
#determine the channel of transistor
my $net=$netlist$instance;
#=================================================================
===========
133
my $D;
my $S;
my $B;
my $G;
for(my $i=0;$i<@terminal;$i++)
if($terminal[$i]=~/G/)$G=$net->[$i];
elsif($terminal[$i]=~/S/)$S=$net->[$i];
elsif($terminal[$i]=~/D/)$D=$net->[$i];
elsif($terminal[$i]=~/B/)$B=$net->[$i];
$S$instance=$S;
$D$instance=$D;
# print "D=>$D S=>$S\n";
$graph$instance=[$D,$S];
#if(
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if($D eq $S)
if($D eq $B)
if($debugFlag==1)
print "since D=S=B It's a varactor (variable capacitor)!!!!!!!!\n";
delete $graph$instance;
$instance_prop$_="varactor";
else
if($debugFlag==1)
print " It's a diode!!!!!!!!\n";
delete $graph$instance;
$instance_prop$_="diode";
$graph$_=[$D,$B];
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
elsif (($D ne $G) and ($G ne $S))#not diode connected
if(($D eq $S) and ($D eq $B))# vorator ###diode transistor or
if($debugFlag==1)
print " It's a varactor (variable capacitor)!!!!!!!!\n";
134
delete $graph$instance;
else
$gate$instance=$G;
$gate_net$G=[] if (not exists $gate_net$G);
$gate_net$G=[@$gate_net$G, $instance];
else
#search for diode connection and change the name
$_=$instance;
s/P/PD/;
s/N/ND/;
s/M/MD/;
s/T/TD/;
$graph$_=delete $graph$instance;
if($debugFlag==1)
print $instance, " is diode connection => $_\n";
=pod
$graph$instance=[$net->[0],$net->[3]]; #(0 1 2 3 )==>(D B G S)
#determine the gate of transistor
if (($net->[0] ne $net->[2]) and ($net->[2] ne $net->[3]))#not diode connected
if(($net->[0] eq $net->[3]) and ($net->[0] eq $net->[1]))# vorator ###diode
transistor or
print " It's a varactor (variable capacitor)!!!!!!!!\n";
delete $graph$instance;
else
$gate$instance=$net->[2];
$gate_net$net->[2]=[] if (not exists $gate_net$net->[2]);
$gate_net$net->[2]=[@$gate_net$net->[2], $instance];
else
135
#search for diode connection and change the name
$_=$instance;
s/P/PD/;
s/N/ND/;
s/M/MD/;
s/T/TD/;
$graph$_=delete $graph$instance;
print $instance, " is diode connection => $_\n";
=cut
#=================================================================
=============
elsif($prop=~/cap/) #means this is a capacitor
delete $graph$instance;
elsif(/^I\d+/)
if($debugFlag==1)
print "$_ is: $instance_prop$_\n";
if($instance_prop$_=~/^idc/)$graph$instance=$netlist$instance; #it's not an
independent current source
elsif($prop=~/pnp|npn/)
#determine the channel of BJT
my $net=$netlist$instance;
$graph$instance=[$net->[0],$net->[2]]; #(0 1 2)==>(C B E)
#determine the Base of BJT
if (($net->[0] ne $net->[1]) and ($net->[2] ne $net->[1]))#not diode connected
my $base_channel=$instance.'_BE';
$graph$base_channel=[$net->[1],$net->[2]];
$gate$instance=$net->[1];
$gate_net$net->[1]=[] if (not exists $gate_net$net->[1]);
$gate_net$net->[1]=[@$gate_net$net->[1], $instance];
else
#search for diode connection and change the name
136
$_=$instance;
s/Q/QD/;
$graph$_=delete $graph$instance;
if($debugFlag==1)
print $instance, " is diode connection $prop => $_\n";
else
$graph$instance=$netlist$instance;
###########################
my %channel=%graph;
if($debugFlag==1)
print "\n**Channel list**\n";
foreach $_ (keys %channel)
print $_, " => [qw/";
print $channel$_->[0],"\t";
print $channel$_->[1],"/]\n";
print "\n**Gate list**\n";
foreach $_ (keys %gate)
print "$_\_gate => '$gate$_'\n";
print "\n**Gate_net list**\n";
foreach $_ (keys %gate_net)
print "$_\_gate_net => '@$gate_net$_'\n";
#############################
##################################
#find the connections for each net
##################################
print "\n**The graph now is: **\n";
137
foreach my $instance (keys %graph)
print "$instance, @$graph$instance\n";
## if debugFlag
my %temp=%graph;
my $cont=0;
for my $instance (keys %temp)
my $net=$temp$instance;
if (exists $graph$net->[0])
$cont++;
# print "before $cont add net $net->[0] is: @$graph$net->[0]\n";
$graph$net->[0]=[@$graph$net->[0],$instance];
# print "after $cont add net $net->[0] is: @$graph$net->[0]\n";
else
$graph$net->[0]=[$instance];
if (exists $graph$net->[1])
# print "before $cont add net $net->[1] is: @$graph$net->[1]\n";
$graph$net->[1]=[@$graph$net->[1],$instance];
# print "after $cont add net $net->[1] is: @$graph$net->[1]\n";
else
$graph$net->[1]=[$instance];
##################################################
#the following code is to make the MOS/BJT channel as one direction
my $ins=$instance;
if($ins=~/(.*)_BE/)
$ins=$1;
$_=$ins; ## to make sure we can use $instance_prop$_;
s/PD/P/;
s/ND/N/;
138
s/MD/M/;
s/TD/T/;
my $prop=$instance_prop$_;
if($prop=~/pnp/)
if($debugFlag==1)
print "$net->[0]=>@$graph$net->[0] !!!!!!!!!!!!!\n";
my @ttt=grep (!/$ins/,@$graph$net->[0]);
if($debugFlag==1)
print "@ttt, got it!!!!!!!!!\n";
$graph$net->[0]=[@ttt];
#$graph$net->[0]=[grep (!/$ins/,@$graph$net->[0])];
elsif($prop=~/npn/)
if($debugFlag==1)
print "$net->[1]=>@$graph$net->[1] ????????????!\n";
my @ttt=grep (!/$ins/,@$graph$net->[1]);
if($debugFlag==1)
print "@ttt, got it??????????\n";
$graph$net->[1]=[@ttt];
#$graph$net->[1]=[grep (!/$ins/,@$graph$net->[1])];
####################################################
if($debugFlag==1)
print "\n**After add the net connction, the graph now is:**\n";
foreach my $instance (keys %graph)
print "$instance => [@$graph$instance]\n";
#the following code has problem since if we make channel directed, than we will have some
net connected to one channel
=pod
139
#######################################
#delete channel without current flowing
#######################################
print "\n**Short the channel without current flowing**\n";
%temp=%graph;
my @floatInstance;
foreach my $instance (keys %temp)
my $net=$temp$instance;
#if(@$net==1 && ($instance ne $path_begin) && ($instance ne $path_end))
if(@$net==1 && (not exists $path_begin$instance) && ($instance ne $path_end))
#means this net(not VDDVSS) is only connected to one channel @$net->[0];
#so no current flowing into this net as well as the connected channel
my $dele_channel=@$net[0];
# print "$instance is only connected to @$net,";
# print "\t so channel $dele_channel can be deleted\n";
#find another pin of the deleting channel (diff from $instance )
# if(!($dele_channel ~ @floatInstance))
if(!(grep$_ eq $dele_channel @floatInstance)) #if the $dele_channel is a
floating#instance ignore the following
my $join_net;
($join_net)=grep (!/$instance/,@$graph$dele_channel);
if (!(defined $join_net))
push @floatInstance, $dele_channel;
print "the channel: $dele_channel is floating! Since it only have one effective net
connection: $instance!";
else short_channel($instance,$dele_channel,$join_net);
# print "$instance => [@$graph$instance]\n";
print "\n**floating inst**:\n", @floatInstance,"\n";
print "\n**Now the graph is:**\n";
foreach my $instance (keys %graph)
print "$instance => [@$graph$instance]\n";
=cut
140
#########################################
#delete one channel and short this branch
#########################################
sub short_channel
my ($dele_net,$dele_channel,$keep_net)=@_;
#delete this channel from the join net connectioin
if($debugFlag==1)
print "\n$dele_net is only connected to $dele_channel,";
print "\t so channel $dele_channel can be deleted\n";
print "and $dele_net should be joined to --->$keep_net,\n";
new_netconne($dele_channel,$keep_net);
my $combNetName;
#if(($keep_net eq $path_end) or ($keep_net eq $path_begin) )
if(exists $path_begin$keep_net or ($keep_net eq $path_end))
if($debugFlag==1)
print "However power supply net name should not be changed!! Thus $keep_net is
unchanged\n";
$combNetName=$keep_net;
#net "gnd!" should not be recombined!!!
else
$combNetName=$keep_net.'_'.$dele_channel.'_'.$dele_net;
if($debugFlag==1)
print " \t this $keep_net is changed to $combNetName\n";
#####This following part is to change the net name $keep_net to $combNetName###
###########################################################################
##
##for the channel that connected to $keep_net change $keep_net to $combNetName
foreach my $ins(@$graph$keep_net)
my @new_netconne=grep (!/$keep_net/,@$graph$ins);#
#new_netconne is the new connections for net $keep_net after delete $keep_net
$graph$ins=[@new_netconne, $combNetName];
##change the key word $keep_net to $combNetname
$graph$combNetName=delete $graph$keep_net;
141
##for gate that connected to $keep_net change $keep_net to $combNetName
foreach my $ins (@$gate_net$keep_net)
$gate$ins=$combNetName;
###########################################################################
##
$keep_net=$combNetName;
delete $graph$dele_channel;
#print "@$gate_net$dele_net\n";
if (exists $gate_net$dele_net)
foreach my $change_gate(@$gate_net$dele_net)
#since deleting the net, the gate connected to it should be changed
if($debugFlag==1)
print "$change_gate\_G=>$dele_net originally\n";
$gate$change_gate=$keep_net;
if($debugFlag==1)
print "$change_gate\_G=>$keep_net now\n ";
delete $graph$dele_net;
#############################################
# find new connections for one net that
#comprise a channel after delete this channel
#############################################
sub new_netconne
my ($dele_channel,$keep_net)=@_;
# print "$keep_net=>[@$graph$keep_net] originally\n";
my @new_netconne=grep (!/$dele_channel/,@$graph$keep_net);#
#new_netconne is the new connections for net $keep_net after delete this channel
$graph$keep_net=[@new_netconne];
# print "$keep_net=>[@new_netconne] now\n";
142
#########################################
#delete one channel and open this branch
#########################################
sub open_channel
my ($dele_channel)=@_;
if($debugFlag==1)
print "\n channel $dele_channel is being deleted\n";
new_netconne($dele_channel,@$graph$dele_channel[0]);
new_netconne($dele_channel,@$graph$dele_channel[1]);
delete $graph$dele_channel;
print STDOUT "progress= 10\n";
##############################
#run the find_path function
#written in findPath.pl file
##############################
######################
#join the path to hash
######################
if($debugFlag==1)
print "\n**path list**\n";
my $i=0;
tie my %path, 'Tie::IxHash';
#my %path;
foreach my $path_begin(keys %path_begin)
my $routes = find_paths($path_begin, $path_end, \%graph);
#my $n=@$routes;
#print $n;
foreach my $pt (@$routes)
my $temp="path";
my $p=join("",($temp, $i++));
if($debugFlag==1)
print $p," => ";
143
print "@$pt\n";
$path$p=[@$pt];
# print $path$p->[2],"\t";
if($debugFlag==1)
print "\n**search self-determined path**\n";
########################################################
#for each path find the self-determined paths,
#find for each net the belonging to non-self-deter paths
########################################################
#print "\n**path list**\n";
#print "@$_\n" for @$routes;
my %net_path; #store for each net the paths it belongs to
my %check_gate;
my %MOS_Channel;#the real MOS Channel
my %self_deter_path; #stort the self-determined path
my %net__selfDeterPath;#store for each net the belonging to self-deter paths
my %path_bak=%path;
my %supplyVol;
foreach my $pt (keys %path)
#=================================================================
=============================
#find the power supply voltage source
#
my $potentialVDC=$path$pt->[1];
if(exists $instance_prop$potentialVDC)
if($instance_prop$potentialVDC=~/^vdc/ && ($path$pt->[2] eq $path_end))
if($debugFlag==1)
print "\n!!!Got the supply voltage source for $path$pt->[0] is: $potentialVDC
\n";
print "since:";
$supplyVol$path$pt->[0]=$potentialVDC;
144
#=================================================================
=============================
@_=@$path$pt;
if($debugFlag==1)
print "\n$pt => [qw/@_/]\n";
my $self_deter_flag=1;
my $i=0;
for (my $index=0;$index<@$path$pt;$index++)
#foreach my $net (@$path$pt)
my $net=@$path$pt[$index];
$_=$net;
#print "$_\n";
my $prop;
if(exists $instance_prop$net)# means this net is an instance 1st-if
$prop=$instance_prop$net;
# print "$prop";
# if($prop=~/^pmos|^pfet|^nmos|^nfet/)print " is COMS\n";
#if (/^P\d+/ or /^N\d+/ or /^M\d+/)
if($prop=~/^pmos|^pfet|^nmos|^nfet/) #means this is a coms transistor 2nd-if
$self_deter_flag=0;
if($debugFlag==1)
print "$net\_G should be checked\n";
#save the gate that need to be checked
$check_gate$pt=[] if (not exists $check_gate$pt);
$check_gate$pt=[@$check_gate$pt,$net];
######determine the real drain and source following the path
#if($net=~/^N/)
if($prop=~/^nmos|^nfet/)
$graph$net=[@$path$pt[$index-1],@$path$pt[$index+1]];
else
$graph$net=[@$path$pt[$index+1],@$path$pt[$index-1]];
$MOS_Channel$net=$graph$net;
# 2nd-if
145
if($prop=~/pnp|npn/) #means this is a BJT 2nd-if
$self_deter_flag=0;
if($debugFlag==1)
print "$net\_B should be checked\n";
#save the gate that need to be checked
$check_gate$pt=[] if (not exists $check_gate$pt);
$check_gate$pt=[@$check_gate$pt,$net];
######determine the real drain and source following the path
#if($net=~/^N/)
if($prop=~/npn/)
$graph$net=[@$path$pt[$index-1],@$path$pt[$index+1]];
else
$graph$net=[@$path$pt[$index+1],@$path$pt[$index-1]];
$MOS_Channel$net=$graph$net;
# 2nd-if
#1st-if
if($i%2==0 && $i>0) # 3nd-if
if ($net ne $path_end)
#find for each net the belonging to non-self-deter paths
$net_path$net=[] if (not exists $net_path$net);
$net_path$net=[@$net_path$net,$pt];
# 3nd-if
# print $i;
$i++;
## for
#one path may not have transistor, but it can bifurcate to another path which can contain tans
=pod
#for each path find the self-determined paths,
if ($self_deter_flag==1)
print "$pt is a self-determined path\n";
for (my $index=@$path$pt;$index>0;$index--)
146
short_channel(@$path$pt[$index-2],@$path$pt[$index-1],$path_end) if
($index%2==0);
$self_deter_path$pt=$path$pt;
delete $path$pt;
=cut
#foreach
if($debugFlag==1)
print "\nafter deleting the self-determined path:\n";
foreach (keys %path)
print "$_=>@$path$_\n";
#############################################################
print "\n**the real drain and source for each transistor**\n";
#############################################################
my %drain;
my %source;
foreach my $chan (keys %MOS_Channel)
my $D=@$MOS_Channel$chan[0];
my $S=@$MOS_Channel$chan[1];
push @$drain$D, $chan;
push@$source$S, $chan;
if($debugFlag==1)
print "$chan => [@$MOS_Channel$chan] \(D S\)\n";
if($debugFlag==1)
print "\n**drain list**\n";
foreach (keys %drain)
print "$_=>@$drain$_\n";
print "\n**source list**\n";
foreach (keys %source)
print "$_=>@$source$_\n";
147
print STDOUT "progress= 20\n";
########################################
#for determining voltage and dependencis
########################################
print "\n**find dependencies**\n";
# if debugFlag
my %depen;
my @d;
my %check_source;
foreach my $pt (keys %check_gate) #$pt-> each path that have transistors
if($debugFlag==1)
print "\nFor $pt: @$path$pt\n";
foreach my $ins (@$check_gate$pt) #ins-> each transistor of this path
if($debugFlag==1)
print "\n$ins\[G]=> $gate$ins, ";
my @check_Vgs; # gate voltage and source voltage can both be potential controlling
voltages
push @check_Vgs,$gate$ins; #gate is a potential controlling voltage
#if (($gate$ins eq $path_begin) or ($gate$ins eq $path_end)) # the gate is
connected to fixed voltage
if (exists $path_begin$gate$ins or ($gate$ins eq $path_end)) # the gate is connected
to fixed voltage
#if (@$channel$ins[1] ne ($path_begin and $path_end))# the source is not
connected to Vdd and Vss then is a potential control volt
if($debugFlag==1)
print "source of $ins is not connected to fixed voltage \n";
my $check_Vs=@$channel$ins[1];
push @check_Vgs,$check_Vs;#source is a potential controlling voltage
push @$check_source$check_Vs,$ins;
if($debugFlag==1)
print "Thus, we should check the source of $ins: $check_Vs\n";
148
#=================================================================
========================
my $mySource=@$MOS_Channel$ins[1];
if($debugFlag==1)
print "!!$ins\[S]=> $mySource\n";
if (!exists $path_begin$mySource && ($mySource ne $path_end))# the source is
not connected to Vdd and Vss then is a potential control volt
if($debugFlag==1)
print "source of $ins is not connected to fixed voltage \n";
my $check_Vs=$mySource;
push @check_Vgs,$check_Vs;#source is a potential controlling voltage
push @$check_source$check_Vs,$ins;
if($debugFlag==1)
print "Thus, we should check the source of $ins: $check_Vs\n";
#=================================================================
========================
foreach my $check_Vgs (@check_Vgs)
foreach my $net_p (@$net_path$check_Vgs) # net_p->each path that the gate
of this transistor gate is conncted to
if ($net_p ne $pt)
if($debugFlag==1)
print "and $check_Vgs is a net of $net_p\n";
# push @d,[$net_p, $check_Vgs],[$check_Vgs, $pt];##this may lead to
repeated dependencies
$depen$net_p.$check_Vgs=[$net_p, $check_Vgs];
$depen$check_Vgs.$pt=[$check_Vgs, $pt];
if($debugFlag==1)
print "depen:$net_p=>$check_Vgs, $check_Vgs=>$pt\n";
149
###########################consider the symbol dependencies
foreach my $check_Vgs (@check_Vgs)
foreach (keys %symbolDepen)
if($check_Vgs eq @$symbolDepen$_[1])
if($debugFlag==1)
print "and $check_Vgs is a net of symbol dependecies:
@$symbolDepen$_\n";#there is a depen between the symbol depen output to current
path
$depen$check_Vgs.$pt=[$check_Vgs, $pt];
foreach my $net_p (@$net_path@$symbolDepen$_[0]) #find a
path the generate the controlling voltage of the symboe depen
$depen$net_p.@$symbolDepen$_[0]=[$net_p,
@$symbolDepen$_[0]];
if($debugFlag==1)
print "also @$symbolDepen$_[0] is a net of $net_p\n";
=pod
print "\n**source**\n";
foreach (keys %check_source)
print "$_=>[@$check_source$_]\n";
=cut
my %net_from_depen;###list of the paths where the controlling voltages come from
my %path_depen;##list of the denpens that a path belongs to
my %path_from_depen;##list of the denpens that a path belongs to
###############
#after delete the repeated denpendecies
if($debugFlag==1)
print "\n**net from path**\n";
foreach my $net (keys %net_path)
150
print "$net: @$net_path$net\n";
my %net_path_bak=%net_path;
if($debugFlag==1)
print "\n**dependencies list**\n";
foreach my $item (keys %depen)
if($debugFlag==1)
print "$item: @$depen$item\n";
my $path1=@$depen$item[0];
my $net1=@$depen$item[1];
if($path1=~/^path/)
push @$net_from_depen$net1, $path1;
push @$path_depen$path1, $item;
#if
elsif($net1=~/^path/)
push @$path_depen$net1, $item;
push @$path_from_depen$net1, $item;
#elsif
if($debugFlag==1)
print "\n**list of the paths where the controlling voltages come from**\n";
foreach my $net (keys %net_from_depen)
if($debugFlag==1)
print"$net: @$net_from_depen$net^^^^^^^^^^^^^^^\n";
if(@$net_from_depen$net==2)
#============================================
my ($pt1,$pt2)=@$net_from_depen$net;
if(exists $path$pt1 && exists $path$pt2)
#============================================
combin_paths(@$net_from_depen$net,$net);
151
#if
foreach my $net (keys %net_path)
if($debugFlag==1)
print"$net: @$net_path$net~~~~~~~~~~~~~~\n";
if(@$net_path$net==2)
#============================================
my ($pt1,$pt2)=@$net_path$net;
if(exists $path$pt1 && exists $path$pt2)
#============================================
combin_paths(@$net_path$net,$net);
#if
if($debugFlag==1)
print "\n**path belongs to depens**\n";
foreach my $path (keys %path_depen)
print"$path: @$path_depen$path\n";
sub combin_paths
if($debugFlag==1)
print "!!!@_!!!\n";
my ($pt1,$pt2, $net)=@_;
my @pt1=@$path$pt1;
my @pt2=@$path$pt2;
if($debugFlag==1)
print "begin test\n";
print "$pt1 is: @pt1,\n $pt2 is: @pt2\n";
my %pt1;
map($pt1$_=1,@pt1); # create %pt1 with elements from @pt1
my @pt2Diff=grep(!defined($pt1$_),@pt2); # returns those elements of @pt2 that don't
# have a hash element in %pt1 therefore they
152
# do not exist in @pt1.
if($debugFlag==1)
print " the differen in $pt2 is: @pt2Diff\n";
if(!grep((/^P\d+/ or /^N\d+/ or /^M\d+/ or /^T\d+/ or (exists $net_from_depen$_) or
(exists $net_from_symbolDepen$_)), @pt2Diff) ) # there are no transistors and
controlling voltages in the common parts then this path can be combined
#print %net_from_symbolDepen,"\t @pt2Diff\n\n";
#if(!grep((not exists $net_from_symbolDepen$_), @pt2Diff))print "ok!!\n";
if($debugFlag==1)
print "$pt2 can be combined!!\n";
delete $path$pt2;
if($debugFlag==1)
print "@$path_depen$pt2 can be deleted !!\n";
grep(delete $depen$_,@$path_depen$pt2);
new_net_path($pt2, $net);
else# when $pt2 can not be combined, lets check $pt1
my %pt2;
map($pt2$_=1,@pt2);
my @pt1Diff=grep(!defined($pt2$_),@pt1);
if($debugFlag==1)
print " the differen in $pt1 is: @pt1Diff\n";
if(!grep((/^P\d+/ or /^N\d+/ or /^M\d+/ or /^T\d+/ or (exists $net_from_depen$_)
or (exists $net_from_symbolDepen$_)), @pt1Diff) )# there are no transistors and
controlling voltages in the common parts then this path can be combined
if($debugFlag==1)
print "$pt1 can be combined!!\n";
delete $path$pt1;
if($debugFlag==1)
print "@$path_depen$pt1 can be deleted !!\n";
grep(delete $depen$_,@$path_depen$pt1);
new_net_path($pt2, $net);
153
#############################################
# find new paths for one net it belongs to
#############################################
sub new_net_path
my ($dele_path,$net)=@_;
if($debugFlag==1)
print "$net=>[@$net_path$net] originally\n";
my @new_netconne=grep (!/$dele_path/,@$net_path$net);#
#new_netconne is the new connections for net $net after delete this channel
$net_path$net=[@new_netconne];
if($debugFlag==1)
print "$net=>[@new_netconne] now\n";
if($debugFlag==1)
print "\n**new dependencies after combining some paths**\n";
foreach my $item (keys %depen)
print "$item: @$depen$item\n";
############## add the symbol dependencies we assigned
foreach (keys %symbolDepen)
my $temp=[@$symbolDepen$_[0],@$symbolDepen$_[1]];
if($debugFlag==1)
print @$temp, "\n";
$depen$_=[@$symbolDepen$_[0],@$symbolDepen$_[1]];
###############################################
#build the relationshiop between the net number
###############################################
$i=0;
154
my %net_num;
undef %net_num;
my %num_net;
undef %num_net;
if($debugFlag==1)
print "\n**net<=>number transform list**\n";
=pod
foreach my $dep (@d)
print " @$dep \n";
if (not exists $net_num$dep->[1])
$net_num$dep->[1]=$i;
$num_net$i=$dep->[1];
$i++;
if (not exists $net_num$dep->[0])
$net_num$dep->[0]=$i;
$num_net$i=$dep->[0];
$i++;
=cut
foreach my $dep (keys %depen)
# print "@$depen$dep \n";
if (not exists $net_num@$depen$dep[1])
$net_num@$depen$dep[1]=$i;
$num_net$i=@$depen$dep[1];
$i++;
if (not exists $net_num@$depen$dep[0])
$net_num@$depen$dep[0]=$i;
$num_net$i=@$depen$dep[0];
$i++;
my $num_vertices=$i;
155
my $num_depen=keys %depen;
if($debugFlag==1)
print "num_vertices==>$num_vertices\n";
foreach $_(keys %net_num)
print $_,"\t",$net_num$_,"\n";
foreach $_(keys %num_net)
print $_,"\t",$num_net$_,"\n";
# if debugFlag
######################################
#print the dependencies to a text file.
######################################
open( MYDEPEN, ">./dependenciesToJava.txt") || die "Can't open myfile: $!";##'>' means
write only, it will clear and rewrite the file.
open( MYDEPEN1, ">./dependencies.txt") || die "Can't open myfile: $!";##'>' means write
only, it will clear and rewrite the file.
if($debugFlag==1)
print "\n**denpendencies list**\n";
=pod
print MYDEPEN $i=keys %depen,"\n";
foreach my $item (keys %depen)
print "$item => '@$depen$item'\n";
print MYDEPEN "$item => '@$depen$item'\n";
close(MYDEPEN);
=cut
=pod
print MYDEPEN $i=@d,"\n";
foreach my $item (@d)
print "@$item[0] => @$item[1]\n";
# print "$net_num@$item[0] => $net_num@$item[1]\n";
# print MYDEPEN "@$item[0],@$item[1]\n";
print MYDEPEN "$net_num@$item[0],$net_num@$item[1]\n";
156
close(MYDEPEN);
=cut
#=================================================================
=====================================
# Attention this number should be the total number of vertices, not the total number of
dependencies
print MYDEPEN $num_vertices,"\n";
print MYDEPEN $num_depen,"\n";
#=================================================================
=====================================
foreach my $item (keys %depen)
if($debugFlag==1)
print "@$depen$item[0] => @$depen$item[1]\n";
# print "$net_num@$depen$item[0] => $net_num@$depen$item[1]\n";
# print MYDEPEN "@$depen$item[0],@$depen$item[1]\n";
print MYDEPEN
"$net_num@$depen$item[0],$net_num@$depen$item[1]\n";
print MYDEPEN1 "@$depen$item[0] @$depen$item[1]\n";
close(MYDEPEN);
close(MYDEPEN1);
print STDOUT "progress= 30\n";
#################################
#call java code to find loops
#################################
if($debugFlag==1)
print "**\nThe loop found by java**\n";
#system("make");
#system("java ITV.breakLoop.de.graphs.TestCycles >java.log");
####open the loops file that generated from eclips.
open( MYLOOPS, "<loopsFromJava.txt") || die "Can't open myfile: $!";##'<' or omitting
means read only.
print STDOUT "progress= 50\n";
## the sign "+>"open with read and write mode
my @loops_num=<MYLOOPS>;
#print MYLOOPS "";#clear the data after read
157
close(MYLOOPS);
my @loops_net;
####transform the num to net
foreach (@loops_num)
my @temp;
chomp $_;
@temp=split(/ /,$_);
my @newloops;
foreach my $num (@temp)
push @newloops, $num_net$num;
push @loops_net,[@newloops];
# print "@temp \n";
my @pathNames;
if($debugFlag==1)
print "\n**path list**\n";
open( MYPATH, ">./pathList.txt") || die "Can't open myfile: $!";##'>' means write only, it
will clear and rewrite the file.
foreach (keys %path)
if($debugFlag==1)
print "$_=>@$path$_\n";
print MYPATH "$_=>@$path$_\n";
push @pathNames, $_;
close(MYPATH);
if($debugFlag==1)
print "\nself-determined path:\n";
foreach my $pt (keys %self_deter_path)
if($debugFlag==1)
print "$pt=>@$self_deter_path$pt\n";
158
for (my $i=0;$i<@$self_deter_path$pt;$i++)
if($i%2==0 && $i>0)
my $net=@$self_deter_path$pt[$i];
if ($net ne $path_end)
#find for each net the belonging to self-deter paths
=pod
$net__selfDeterPath$net=[] if (not exists $net__selfDeterPath$net);
$net__selfDeterPath$net=[@$net__selfDeterPath$net,$pt];
=cut
push @$net__selfDeterPath$net,$pt;
if($debugFlag==1)
print "\n**net from self-determined path**\n";
foreach (keys %net__selfDeterPath)
print "$_=>@$net__selfDeterPath$_\n";
open( MYLOOP, ">loopList.txt") || die "Can't open myfile: $!";##'>' means write only, it will
clear and rewrite the file.
foreach my $pt (keys %path)
print MYLOOP "$pt \t";
foreach (@$path$pt)
s/PD/P/;
s/ND/N/;
s/MD/M/;
s/TD/T/;
s/_BE//;
print MYLOOP "$_ ";
print MYLOOP "\n";
159
if($debugFlag==1)
print "\n**Loop list**\n";
my $k=0;
my %loopSign;
tie my %loopList, 'Tie::IxHash';
my %net_loop;
my %positLoopList;
my %negLoopList;
my %posLoop_net;
foreach my $loop (@loops_net)
my $iii=@$loop;
# print "$iii\n";
if(@$loop>2)
$k++;
my $loopNum='loop'.$k;
$loopList$loopNum=$loop;
if($debugFlag==1)
print "\n$loopNum: @$loop";
#############################################
#following code is to identify the common Nets
#of two paths
#############################################
sub findPathCommonNets
my ($pt1,$pt2)=@_;
my @pt1=@$path$pt1;
my @pt2=@$path$pt2;
my @common;
my @common2;
for (my $i=1; $i<@pt1-1;$i++)
for (my $j=1; $j<@pt2-1;$j++)
if($pt1[$i] eq $pt2[$j])
160
push @common,$pt1[$i];
if(@common)
if($common[0] eq $pt1[1])
pop @common;
elsif($common[-1] eq $pt1[-2])
@common= grep($_ ne $common[0], @common);
for (my $index=0; $index<@common;$index++)
if($index%2 ==1)
push @common2, $common[$index];
if(@common2)
if($debugFlag==1)
print "$pt1 & $pt2(common):@common2\n";
return \@common2;
#############################################
#following code is to remove some loop
#since some path in this loop has shared node
#############################################
if($debugFlag==1)
print "\n**path list**\n";
foreach (keys %path)
print "$_=>@$path$_\n";
tie my %pathComm, 'Tie::IxHash';
for (my $i=0; $i<@pathNames;$i++)
161
my $pt1=$pathNames[$i];
for (my $j=$i+1; $j<@pathNames;$j++)
my $pt2=$pathNames[$j];
my $common=findPathCommonNets($pt1,$pt2);
if(@$common)
$pathComm$pt1.$pt2=$common;
$pathComm$pt2.$pt1=$common;
if($debugFlag==1)
print "\n**path commom nets list**\n";
foreach (keys %pathComm)
print "$_=>@$pathComm$_\n";
tie my %loopList_temp, 'Tie::IxHash';
%loopList_temp=%loopList;
foreach my $loopNum (keys %loopList_temp)
my $loop=$loopList_temp$loopNum;
if($debugFlag==1)
print "\n$loopNum: @$loop\n";
my @temp=@$loop;
#$loopList_temp$loopNum=[@temp];
push @temp,@$loop[0];#make the last item equal to the loop begin
my $sign=0;
my @pathInLoop;
my @netInLoop;
for (my $index=0; $index<@$loop;$index++)
if(@$loop[$index]=~/^path/)
my $I=@$loop[$index];#start from current
if($debugFlag==1)
print "$I\t @$path$I\n";##print the path that need to be highlighted
push @pathInLoop,@$loop[$index];
162
else
push @netInLoop,@$loop[$index];
if($debugFlag==1)
print "\npathInLoop: @pathInLoop\nnetInLoop: @netInLoop\n";
for (my $i=0; $i<@pathInLoop;$i++)
my $pt1=$pathInLoop[$i];
for (my $j=$i+1; $j<@pathInLoop;$j++)
my $pt2=$pathInLoop[$j];
if(exists $pathComm$pt1.$pt2)
#print "$pt1 $pt2:@$pathComm$pt1.$pt2\n";
my @common=@$pathComm$pt1.$pt2;
my %common;
map($common$_=1,@common); # create %pt1 with elements from @pt1
my @temp=grep(defined($common$_),@netInLoop); # returns those
elements of @pt2 that don't
if(@temp)
if($debugFlag==1)
print "The CV @temp is in $pt1.$pt2: @common\t thus this loop should be
delete!!\n";
delete $loopList$loopNum;
#############################################
#following code is to determine loop sign
#############################################
sub expandLoopBetweenTwoCV
my ($pt,$inst,$CV)=@_;
#print "$pt:@$path$pt\n";
163
my @k;
my @expand;
for (my $i=0; $i<@$path$pt;$i++)
my $temp=@$path$pt[$i];
if($temp eq $inst || $temp eq $CV)
push @k, $i;
for (my $i=$k[0]; $i<=$k[1];$i++)
push @expand, @$path$pt[$i];
my @expand1;
if($expand[0] ne $inst) #make sure always starts at the input $inst
while(@expand)
my $temp=pop @expand;
push @expand1, $temp;
else
@expand1=@expand;
my @expand2;
for (my $i=0; $i<@expand1;$i++) ### only keep the net
if($i%2==1)push @expand2,$expand1[$i];
return @expand2;
########
#expand loop
tie my %loopListExpand, 'Tie::IxHash';
$k=0;
foreach my $loopNum (keys %loopList)
my $loop=$loopList_temp$loopNum;
if($debugFlag==1)
print "\n$loopNum: @$loop\n";
my @temp=@$loop;
push @temp,@$loop[0];#make the last item equal to the loop begin
my @extendLoop;
for (my $index=0; $index<@$loop;$index++)
164
push @extendLoop,@$loop[$index];
if(@$loop[$index]=~/^path/)
my $I=@$loop[$index];#start from current
foreach my $MOS (@$check_gate$I)#MOS-> each transistor of this path
my $CV=@$loop[$index-1];
if($CV eq $gate$MOS || $CV eq $MOS_Channel$MOS[1])
#print "$CV -> $MOS ->$temp[$index+1]\n";
my @expand=expandLoopBetweenTwoCV($I, $MOS,$temp[$index+1]);
#print "$temp[$index-1], $temp[$index], $temp[$index+1]\t";
#print "is expaned to: $temp[$index-1] $temp[$index] @expand\n";
#print "input: $I, $MOS,$temp[$index+1]\n";
#print "output: @expand\n";
push @extendLoop,@expand;
pop @extendLoop;
last;
if($debugFlag==1)
print "extendLoop: @extendLoop\n";
my %seen;
my $flag=1;
foreach (@extendLoop)
if(!$seen$_)
$seen$_=1;
else
if($debugFlag==1)
print "$_ is repeated in this loop, so it is not a loop\n";
$flag=0;
last;
if($flag)
$k++;
165
my $Num='loop'.$k;
$loopListExpand$Num =\@extendLoop;
if($debugFlag==1)
print "\n**Expanded loop list**\n";
foreach (keys %loopListExpand)
print "$_=>@$loopListExpand$_\n";
$k=0;
my %seenLoop;
tie my %loopListOnlyNet, 'Tie::IxHash';
foreach my $loopNum (keys %loopListExpand)
my $loop=$loopListExpand$loopNum;
my @loopOnlyNet;
my $loopOnlyNetStr;
for (my $index=0; $index<@$loop;$index++)
if(@$loop[$index]=~/^path/)
else
push @loopOnlyNet,@$loop[$index];
if(defined $loopOnlyNetStr)
$loopOnlyNetStr=$loopOnlyNetStr.' '.@$loop[$index];
else
$loopOnlyNetStr=@$loop[$index];
if($debugFlag==1)
print "@loopOnlyNet\t$loopOnlyNetStr\n";
if(!$seenLoop$loopOnlyNetStr)
$seenLoop$loopOnlyNetStr=1;
$k++;
166
my $Num='loop'.$k;
#my @temp=split(/ /,$loopOnlyNetStr);
#print "$_=> @temp\n";
$loopListOnlyNet$Num=$loop;
else
if($debugFlag==1)
print "$_ is repeated loop\n";
if($debugFlag==1)
print "\n**Only Net loop list**\n";
foreach (keys %loopListOnlyNet)
print "$_=>@$loopListOnlyNet$_\n";
print STDOUT "progress= 60\n";
#########
#loop sign
print "\n**determine loop sign**\n";
#if $debugFlag
%loopList=%loopListOnlyNet;
foreach my $loopNum (keys %loopList)
my $loop=$loopList$loopNum;
if($debugFlag==1)
print "\n$loopNum: @$loop\n";
my @temp=@$loop;
#$loopList$loopNum=[@temp];
push @temp,@$loop[0];#make the last item equal to the loop begin
my $sign=0;
for (my $index=0; $index<@$loop;$index++)
if(@$loop[$index]=~/^path/)
my $I=@$loop[$index];#start from current
# print "$I\t @$path$I\n";##print the path that need to be highlighted
167
foreach my $MOS (@$check_gate$I)#MOS-> each transistor of this path
my $prop=$instance_prop$MOS;
if($prop=~/^pmos|^pfet/)
# print "$I=>$MOS,\n$gate$MOS\t
MOS_Channel$MOS[1]:$MOS_Channel$MOS[1]\n";
if(@$loop[$index-1] eq $gate$MOS)#V_GP->I
$sign+=1 ;
if($debugFlag==1)
print " @$loop[$index-1]=>$I is negtive \n";
if($temp[$index+1] eq $MOS_Channel$MOS[1])#I->V_SP
$sign+=1;
if($debugFlag==1)
print "test $MOS\_S=> $MOS_Channel$MOS[1]\n";
print " $I=>$temp[$index+1] is negtive \n";
#if
else ##NMOS
# print "$I=>$MOS,\n MOS_Channel$MOS:
@$MOS_Channel$MOS\t gate$MOS: $gate$MOS\n";
if(@$loop[$index-1] eq $MOS_Channel$MOS[1]) #V_SN->I
$sign+=1 ;
if($debugFlag==1)
print " @$loop[$index-1]=>$I is negtive \n";
if((@$loop[$index-1] eq $gate$MOS) or (@$loop[$index-1] eq
$MOS_Channel$MOS[1])) #I->V_DN
if(($temp[$index+1] eq $MOS_Channel$MOS[0]) or
($MOS_Channel$MOS[1] eq $path_end)) ## for I->VD_N the VD_N can be a points
more close to 'Vdd' then the drain of current transistor
168
$sign+=1;
if($debugFlag==1)
print " $I=>$temp[$index+1] is negtive \n";
#else
#foreach
if(!defined $temp[$index+2])$temp[$index+2]=@$loop[1];
my $depenName=$temp[$index+1].$temp[$index+2];
if(exists $symbolDepen$depenName)
if($debugFlag==1)
print "find a symbol dependency\n";
if($symbolDepen$depenName[2]=='1')
if($debugFlag==1)
print " $temp[$index+1]=>$temp[$index+2] is negtive \n";
$sign+=1;
else
#find for each net the belonging to loop
push @$net_loop@$loop[$index],$loopNum;
if ($sign%2==0 && $sign>0)
if($debugFlag==1)
print " positive loop\n";
$loopSign$loopNum='positive';
else
if($debugFlag==1)
print " negtive loop\n";
$loopSign$loopNum='negative';
169
print MYLOOP "$loopNum\t$loopSign$loopNum\t";
print MYLOOP "@$loop\n";
#=================================================================
===
#Out put the extended loop to "loopList.txt"
=pod
foreach (keys %loopListExpand)
print MYLOOP "$_=>@$loopListExpand$_\n";
=cut
#=================================================================
===
if($debugFlag==1)
print "\n**net from positive loop**\n";
foreach my $net (keys %net_loop)
foreach my $loop (@$net_loop$net)
if($loopSign$loop eq'negative')
# print "$net=>[@$net_loop$net] originally\n";
my @new_netconne=grep (!/$loop/,@$net_loop$net);#
$net_loop$net=[@new_netconne];
#print "$net=>[@new_netconne] now\n";
#elseprint "$net=> [@$net_loop$net]\n";
if($debugFlag==1)
print "$net=> [@$net_loop$net]\n";
#=================================================================
===
#=================================================================
===
if($debugFlag==1)
print "\n**Controlling inst for all nets in positive loops**\n";
open( CLTRINST, ">./controlInstList.txt") || die "Can't open myfile: $!";
170
foreach my $net (keys %net_loop)
if(@$net_loop$net)# only consider the nets in positive feedback loop which are
potential breakpoints
#find the controling devices for each potential break point
if(exists $gate_net$net) #this can be wrong if we have cascode diode transistor as
in wildlar banba
my @potentialCtrlInst=@$gate_net$net;
my @finalCtrlInst;
my @controlPath;
foreach my $item (keys %depen)
if($item=~/^$net/)
if($debugFlag==1)
print " $item: @$depen$item\n";
push @controlPath,$$depen$item[1];
if($debugFlag==1)
print "controlPath: @controlPath\n";
my $ff;
foreach my $ins(@potentialCtrlInst)#want to check whether this potential control
instance is in the controling path
$ff=0;
foreach my $pt (@controlPath)
if($debugFlag==1)
print "@$path$pt\n";
foreach(@$path$pt)
#print "potentialControlIns: $ins\t pathItem: $_...\n";
if($_ eq $ins)
$ff=1;
if($debugFlag==1)
print "\t$ins exists in $pt!!!\n";
171
last;
if($ff==1)push @finalCtrlInst, $ins;
#print "$net: @$gate_net$net\n";
#print CLTRINST "$net @$gate_net$net\n";
if($debugFlag==1)
print "$net: @finalCtrlInst\n";
print CLTRINST "$net @finalCtrlInst\n";
close( CLTRINST );
#=================================================================
===
#=================================================================
===
foreach my $loop (keys %loopList)
if($loopSign$loop eq 'positive')
$positLoopList$loop=$loopList$loop;
else
$negLoopList$loop=$loopList$loop;
=pod
print "\n**find positive loop dependencies**\n";
my @pathInPositiLoop;
foreach my $loop (keys %positLoopList)
for (my $index=0; $index<@$positLoopList$loop;$index++)
if(@$positLoopList$loop[$index]=~/^path/)
172
push @pathInPositiLoop, @$positLoopList$loop[$index];
#print @$positLoopList$loop[$index],"\n";
my %contrLoop;
my %contrLoop_detail;
foreach my $loop (keys %positLoopList)
my @contrlLoop;
my %contrlLoopDepenDetail;
my @contrlLoopDepenDetail;
#push @contrlLoop,$loop;
print "$loop: @$positLoopList$loop\n";
for (my $index=0; $index<@$positLoopList$loop;$index++)
if(@$positLoopList$loop[$index]=~/^path/)
my $pt=@$positLoopList$loop[$index];
print " For $pt:\n";
foreach my $ins (@$check_gate$pt) #ins-> each transistor of this path
print "\tThe gate of $ins is $gate$ins\n";
my @loopDepenDetail;
push @loopDepenDetail,$loop,$gate$ins;
my ($contrlLoop,
$loopdepen)=check_gate($gate$ins,$loop,\@loopDepenDetail);
#print "the control loop is $contrlLoop\n";
#print "Detailed loop depen: @$loopdepen\n\n";
if(!(grep($_ eq $contrlLoop) @contrlLoop))
if (!$contrlLoop eq "")
push @contrlLoop, $contrlLoop;
my @temp;
while(@$loopdepen)
push @temp, (pop @$loopdepen);
push @contrlLoopDepenDetail,\@temp;
173
print "The final control loop of $loop is @contrlLoop\n";
print "\n";
$contrLoop$loop=[@contrlLoop];
$contrLoop_detail$loop=[@contrlLoopDepenDetail];
print "\n**Group the positive Loop**\n";
my %net_loop_temp=%net_loop;
my %positLoopList_temp=%positLoopList;
my %GroupLoop;
my %GroupLoop_flat;
$i=0;
while(%positLoopList_temp)
$i++;
print "$i\n";
my $maxLoopnum=0;
my $breakPoint=undef;
while (my ($key, $loop)=each(%net_loop_temp))
if(@$loop>$maxLoopnum)
print "Got a better net: since $key=>[@$loop] >$maxLoopnum\n";
$maxLoopnum=@$loop;
$breakPoint=$key;
print "breakPoint=>$breakPoint for: @$net_loop_temp$breakPoint\n";
$GroupLoop$breakPoint=\@$net_loop_temp$breakPoint;
#delete $net_loop_temp$breakPoint;
grep(delete $positLoopList_temp$_,@$net_loop_temp$breakPoint); #delete the
loop after group it
my %new_net_loop_temp;
print "Now the left positive loop is:\n";
foreach my $loop (keys %positLoopList_temp)
my @temp=@$positLoopList_temp$loop;
print "$loop=> @temp\n";
if(@temp>2)
for (my $index=0; $index<@temp;$index++)
if(!($temp[$index]=~/^path/))
#find for each net the belonging to loop
push @$new_net_loop_temp$temp[$index],$loop;
174
%net_loop_temp=%new_net_loop_temp;
print "Now the new net_loop_temp is;\n";
foreach (keys %net_loop_temp)
print "$_=>[@$net_loop_temp$_]\n";
print "\n**Positive Loop list**\n";
while (my ($key, $value)=each(%positLoopList))
print "$key=> @$value\n";
print "\n**After group them**\n";
foreach my $breakpoint (keys %GroupLoop)
print "$breakpoint=>[@$GroupLoop$breakpoint]\n";
foreach (@$GroupLoop$breakpoint)
push @$GroupLoop_flat$breakpoint,@$positLoopList$_;
# print "@$GroupLoop_flat$breakpoint\n";
print "\n**loop dependencies**\n";
foreach (keys %contrLoop)
my $jj=@$contrLoop$_;
print "For $_: $jj\n";
for (my $k=0; $k<@$contrLoop$_;$k++)
my $L;
$L=@$contrLoop$_[$k];
#print "loop depen$k: $L => $_\n";
my $i=$k+1;
print "loop depen$i: @@$contrLoop_detail$_[$k]\n";
175
##check whether a gate will cause loop dependencies
sub check_gate
my ($gt,$loop, $loopDepenDetail)=@_;
my @loopDepenDetail=@$loopDepenDetail; #store the detaied information of where a
loop dependency come from
if($gt eq $path_end)
print "\t$gt is fixed bias\n";
push @loopDepenDetail,$path_end;
return ("", \@loopDepenDetail);#$loop;
elsif(exists $net_loop$gt and (grep$_ eq $loop @$net_loop$gt)) #if the $gate is a
net of the loop itself then no loop dependencies caused by this gate
print "\t$gt is a net of the loop itself \n";
push @loopDepenDetail,$loop;
return ("", \@loopDepenDetail);#$loop;
else
if(exists $net_from_depen$gt)###########top level dependency
my ($contrPath)=@$net_from_depen$gt;
print "$gt is from $contrPath,\n";
push @loopDepenDetail,$contrPath;
if(grep$_ eq $contrPath @$positLoopList$loop)# if the $contrPath of this gate
is a path of the loop itself then no loop dependencies caused by this gate
print " the $contrPath is a path of the loop itself\n";
push @loopDepenDetail,$loop;
return ("", \@loopDepenDetail);#$loop;
else
foreach my $L (keys %positLoopList)
if(grep$_ eq $contrPath @$positLoopList$L)# if the $contrPath is a
path of another Loop
print "the $contrPath is a path of another loop: $L\n";
pop @loopDepenDetail;
push @loopDepenDetail,$L;
print "now the return loopdepen is @loopDepenDetail\n";
return ($L,\@loopDepenDetail);
#print "now the return loopdepen is @loopDepenDetail\n";
# if
176
#foreach
print "continuing finding...\n";
print "the $contrPath is from @$path_from_depen$contrPath\n";
foreach my $contrVolt (@$path_from_depen$contrPath)
print "the $contrPath is controled by $depen$contrVolt[0]\n";
push @loopDepenDetail,$depen$contrVolt[0];
#print "10now the return loopdepen is @loopDepenDetail\n";
#print " we are checking: $depen$contrVolt[0],$loop\n";
my ($contrLoop,
$loopDepen)=check_gate($depen$contrVolt[0],$loop,\@loopDepenDetail);
if ($contrLoop ne $loop)
# @loopDepenDetail=@$loopDepen;
#print "11now the return loopdepen is @$loopDepen\n";
return ($contrLoop,$loopDepen);
#foreach
#else
#if
elsif(exists $net_from_symbolDepen$gt) ##########symbol dependency
print "$gt is from the symbol dependency @$net_from_symbolDepen$gt\n";
foreach my $dep (@$net_from_symbolDepen$gt)
print "@$symbolDepen$dep\t";
my ($contrVolt)=grep(!/$gt/, @$symbolDepen$dep);
print "the $gt is controled by: $contrVolt\n";
push @loopDepenDetail,$contrVolt;
my ($contrLoop, $loopDepen)=check_gate($contrVolt,$loop,\@loopDepenDetail);
if ($contrLoop ne $loop)
# @loopDepenDetail=@$loopDepen;
#print "11now the return loopdepen is @$loopDepen\n";
return ($contrLoop,$loopDepen);
#if
#foreach
#elsif
# else
=cut
#####caculate execution time
my $finish_time=time();
177
my $finish_time2=localtime();
if($debugFlag==1)
print "finish at:$finish_time2\n";
my $timeused=$finish_time-$start_time;
print "Used time: $timeused\n";
print @mySymbolDepden;
print "\n**positive loop list**\n";
foreach my $loop (keys %positLoopList)
print "$loop: @$positLoopList$loop\n";
print "\n**negative loop list**\n";
# if($debugFlag==1)
open( NEGLOOP, ">./negtiveLoops.txt") || die "Can't open myfile: $!";##'>' means write
only, it will clear and rewrite the file.
foreach my $loop (keys %negLoopList)
if($debugFlag==1)
print "$loop=> @$negLoopList$loop\n";
print NEGLOOP "@$negLoopList$loop ";
close(NEGLOOP);
open( PATHLIST, ">./pathList.txt") || die "Can't open myfile: $!";##'>' means write only, it
will clear and rewrite the file.
foreach my $net (keys %net_path_bak)
print PATHLIST "$net: @$net_path_bak$net\n";
foreach (keys %path_bak)
print PATHLIST "$_=>@$path_bak$_\n";
close(PATHLIST);
#=============================
178
open( SUPPLY, ">./supplyVoltage.txt") || die "Can't open myfile: $!";##'>' means write only,
it will clear and rewrite the file.
foreach my $net (keys %supplyVol)
print SUPPLY "$net $supplyVol$net\n";
close( SUPPLY );
#=============================
print STDOUT "progress= 70\n";
system("perl ./ITV/breakLoop/searchBreakPoints.pl -d $debugFlag");
print STDOUT "FINISHED\n";
2. autoGenerateNetlist.il
;;;load("./ITV/breakLoop/autoModifyNetlist/autoGenerateNetlist.il")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;if this is set to be '1' then the partial netlist for the breaked loop will be generated, otherwise
the whole netlist will begengerated
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
genePartialNetlist=0;
CV=geGetEditCellView()
println(CV)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;set default value
defaltVDD=hiGetCurrentForm()->Vdd->value
defaltVSS=hiGetCurrentForm()->Vss->value
defaltBreakPoint=hiGetCurrentForm()->BreakPoint->value
defaltSCC=hiGetCurrentForm()->strongCompList->value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
let((myPort pathItemId loopItem pathItem myInstTerm)
myPort = outfile(simplifyFilename("./myPartNetlist.scs"))
fprintf(myPort "//Library name: %L \n" CV~>libName)
fprintf(myPort "//Cell name: %L \n" CV~>cellName)
fprintf(myPort "//View name: %L \n" CV~>cellViewType)
fprintf(myPort "MyVdd: %L \n" defaltVDD)
fprintf(myPort "MyVss: %L \n" defaltVSS)
);let
myNetOfPath=makeTable("myNetOfPath" nil);
179
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;show the path table;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
println(";;;path list;;;;")
let((pathName)
foreach(pathName pathTable
println(
list(pathName pathTable[pathName])
);println
;selectPath(pathTable[pathName])
);foreach
);let
;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;show the loop table;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;
println(";;;loop list;;;;")
foreach(loopName loopTable
println(
list(loopName loopTable[loopName])
);println
);foreach
;==================================================================
==============================
DDGTable=makeTable("DDGTable" nil) ;store the dimension for each SCC
let( (inport nextLine dependencies DepenName)
inport=infile("./dependencies.txt")
when(inport
while(gets(nextLine inport)
println(nextLine)
dependencies=parseString(nextLine)
DepenName =car(dependencies)
DDGTable[DepenName]=append1(DDGTable[DepenName] cadr(dependencies))
);while
close(inport)
);when
);let
printf("\n**DDG Table**\n")
foreach(DepenName DDGTable
printf("%s=>%L\n" DepenName DDGTable[DepenName])
)
;==================================================================
==============================
aa=nil
breakedLoopFromBreakPoint=nil
180
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;find the gate of tansistor (controlling transistor that need to connect to sweep votalge
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
let((selWire breakNet instConnToSelNet instNum currentBreakPoint potentialCltrInst)
;;these following code always treat the selected net as breaking point
;selWire=geGetSelSet()
;instConnToSelNet=car(selWire~>net~>instTerms~>inst~>name)
;instConnToSelNet=car(selWire~>net~>instTerms~>inst)
;;the following consider the value from the break point form as breaking point
temp0=parseString(defaltBreakPoint, "");;;from the form we get the breakpoints
breakNets=car(parseString(car(temp0),""))
breakNets=parseString(breakNets," ")
printf("The breakpoints figured out from the form are: %L \n" breakNets)
;println(breakNets)
cltrInst=makeTable("cltrInst" nil)
foreach(currentBreakPoint breakNets;;; several break points foreach
;;;;the following is trying to figure out the breaked loop from the given breaking points
foreach(loopName loopTable
println(loopTable[loopName]);println
foreach(loopItem loopTable[loopName]
if(loopItem==currentBreakPoint then
breakedLoopFromBreakPoint=append1(breakedLoopFromBreakPoint
loopName)
);if
);foreach
);foreach
instNum=makeTable("instNum" nil)
breakNet=dbFindNetByName(CV currentBreakPoint)
instConnToSelNet=breakNet~>instTerms~>inst
;=========================
;=========================
aa=instConnToSelNet
println(
list(" !!!instConnToSelNet" instConnToSelNet~>name)
)
println(instConnToSelNet~>??
)
foreach(inst instConnToSelNet
block=nil
BPS=inst~>name
if(inst~>prop==nil then block=inst; a self-created block is found
; following is to figure out the connection between level to level-1
printf("%s(PIN): %L\n" block~>name block~>instTerms~>name)
181
printf("%s(Conn): %L\n" block~>name block~>instTerms~>net~>name)
foreach(myTerms block~>instTerms
if(myTerms~>net~>name==currentBreakPoint then
nextLevelBreakPoint=myTerms~>name
printf("Current BPS: %s=>" currentBreakPoint)
BPS=strcat(BPS "." nextLevelBreakPoint)
printf("Next BPS: %s\n" BPS)
);if
);foreach
nextLevelCV=dbGetAnyInstSwitchMaster(block "schematic")
breakNetNextLevel=dbFindNetByName(nextLevelCV nextLevelBreakPoint)
println(breakNetNextLevel~>instTerms~>inst~>name)
)
);foreach
;=========================
;=========================
foreach(inst instConnToSelNet
if(instNum[inst]==nil then
instNum[inst]=1
else
instNum[inst]=instNum[inst]+1
);if
);foreach
potentialCltrInst=nil
potentialCltrInstByName=nil
;println(instNum~>?)
foreach(inst instNum~>?
if(instNum[inst]==1 then ;;the instance that have two terminal connected to the selected
net is diode connection
potentialCltrInst=append1(potentialCltrInst inst)
potentialCltrInstByName=append1(potentialCltrInstByName inst~>name)
);if
);foreach
printf("potentialCltrInst is: %L \n" potentialCltrInst~>name)
;==================================================================
==============================
;make this change becase for cascode transistor, it's not necessarily diode transistors
printf("\n**The breakedLoop are:**\n\n" )
foreach(loopName breakedLoopFromBreakPoint
println(
list(loopName loopTable[loopName])
182
);println
);foreach
println(
list(currentBreakPoint DDGTable[currentBreakPoint])
);println
foreach(DDGpath DDGTable[currentBreakPoint];foreach DDGTable
println(
list(DDGpath pathTable[DDGpath])
);println
foreach(inst potentialCltrInstByName
printf("??potentialCltrInst: %s\n" inst)
if(member(inst pathTable[DDGpath]) then
printf("??find one control inst: %s\n" inst )
cltrInst[inst]=currentBreakPoint
);if
;=========================
;=========================
;pathItem=pathTable[DDGpath]
foreach(pathItem pathTable[DDGpath]
printf("~~~~~~~~~~~~~~~~~~%s" pathItem)
pathItemList=parseString(pathItem ".")
println(pathItemList)
println(car(last(pathItemList)))
if(inst==car(last(pathItemList)) then
printf("??find one control inst: %s\n" inst )
)
)
;=========================
;=========================
);foreach
);foreach DDGTable
/*
foreach(inst potentialCltrInst
;println(inst~>name)
;println(inst~>instTerms~>name)
;println(inst~>instTerms~>net~>name)
;println(car(selWire~>net)~>name)
foreach(instTerm inst~>instTerms
if(instTerm~>name=="G" && instTerm~>net==breakNet then
printf("found it: %s gate connection should be changed" inst~>name)
cltrInst[inst~>name]=instTerm~>net~>name
;print(inst~>instTerms~>net)
);if
);foreach
183
printf("\n")
);foreach
*/
;==================================================================
==============================
);;; several break points foreach
);let
printf("\n**The breakedLoop due to %L are:** \n%L \n" breakNets
breakedLoopFromBreakPoint)
printf("\n**Controling Devices & Voltages List**\n")
foreach(ins cltrInst
print(ins)
println(cltrInst[ins])
);foreach
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;generate netlist automatically
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
simulator( 'spectre )
;==================================================================
=============================================================
;don't need this. since this file is called by identifyBPS.il
;in that file CV is arealdy defined
;and this few sentence will actually generate a new window after close it, the activate
window will be nil and cause problem
;so if we click "Netlist" button multiple times, i.e. call this file multiple times in
identifyBPS.il
;CV=geGetEditCellView()
;schCheck(CV)
;==================================================================
=============================================================
design(
CV~>libName
CV~>cellName
CV~>cellViewType
)
address=createNetlist(
?recreateAll t
?display t
)
hiCloseWindow(hiGetCurrentWindow())
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;output the generated netlist and tansistor to a file
184
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
myPort = outfile("./input.scs")
fprintf(myPort address)
foreach(ins cltrInst
fprintf(myPort "\n%L" ins)
fprintf(myPort " %L" cltrInst[ins])
);foreach
;fprintf(myPort " %L\n" loopTable[breakedLoop])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;print a loop to a file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
foreach(breakedLoop breakedLoopFromBreakPoint;foreach for several broken Loops
println("breakedLoop now")
println(breakedLoop)
fprintf(myPort "\n%s" car(parseString(breakedLoop)))
if(cadr(parseString(breakedLoop)) then
fprintf(myPort " %s " cadr(parseString(breakedLoop)))
)
;fprintf(myPort "\n%L " breakedLoop)
;print a path to a file
/*
procedure(printPathTFile(pathName)
let((pathItemId pathItem)
foreach(pathItem pathTable[pathName]
pathItemId=dbFindAnyInstByName(CV pathItem)
if( pathItemId then;;or if(pathItem~>objType=="inst"
fprintf(myPort " %L" pathItemId~>name)
);let
);procedure
*/
pathNet=makeTable("pathNet" nil)
foreach(loopItem cdr(loopTable[breakedLoop])
if( rexMatchp("path" loopItem) then
foreach(pathItem pathTable[loopItem]
;fprintf(myPort " %L\t" pathItem)
pathItemId=dbFindAnyInstByName(CV pathItem)
if( pathItemId then;;or if(pathItem~>objType=="inst"
fprintf(myPort " %L" pathItemId~>name)
else
pathNet[pathItem]=loopItem
);if
);foreach
);if
185
);foreach
);foreach for several broken Loops
fprintf(myPort "\nMyVdd: %L \n" loopListForm->Vdd->value)
fprintf(myPort "MyVss: %L \n" loopListForm->Vss->value)
println("path Net now")
foreach(pathNetItem pathNet
println(pathNetItem)
println(pathNet[pathNetItem])
);foreach
println("end pathnet")
;====================================
;====================================
fprintf(myPort "MyBPS:")
foreach(BPS breakNets
fprintf(myPort " %s" BPS)
)
fprintf(myPort "\n")
;====================================
;====================================
close(myPort)
;view("/home/yli/501labs/autoModifyNetlist/input.scs")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;communication with Netlist modifying program (written in perl)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
println("modifying simulator input file...")
let((result)
if(genePartialNetlist==1 then
cmd="perl ./ITV/breakLoop/autoModifyNetlist/modifyPartialNetlist.pl"
else
;cmd="perl ./ITV/autoModifyNetlist/modifyNetlist.pl"
cmd=strcat("perl ./ITV/breakLoop/autoModifyNetlist/modifyNetlist.pl " defaltSCC)
println(cmd)
);if
ChildId=ipcBeginProcess(cmd "" "" "" "" "autoGeneNetlist.log")
ipcWait(ChildId)
if(!ipcIsActiveProcess(ChildId) then x=1
; view("modifyNetlist.log")
; result=ipcReadProcess(ChildId)
186
; println(result)
);;if
);let
ipcKillProcess(ChildId)
println(" ...successful.")
view(address)
view("./input1.scs")
;view("autoGeneNetlist.log")
2. modifyNetlist.pl
#! /usr/bin/perl
use strict;
use warnings;
use lib './ITV/breakLoop/Strong_conn_comp/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
my $input1 = $ARGV[0];
if ($input1 eq "")
print "\n***Usage:Generate netlist file for certain SCC***\n";
print "***Need an input1 to stand for SCC name***\n";
print "***E.g. ==> perl modifyNetlist.pl SCC1 <===\n\n";
exit(1);
else
print STDOUT "$input1\n";
#===============================
#####################################
#obtain the suppy voltage source for each vdd
#####################################
open( SUPPLY, "./supplyVoltage.txt") || die "Can't open myfile: $!";
my @supplyVol=<SUPPLY>;
close(SUPPLY);
print @supplyVol;
my %SUPPLY;
my %supplyVol;
my $numSupplyVol=0;
foreach (@supplyVol)
my @temp=split(/\s+/,$_);
$supplyVol$temp[1]=$temp[0];
187
$numSupplyVol++;
print "\n**supply Voltage source list $numSupplyVol!!!**\n";
foreach (keys %supplyVol)
print "$_ $supplyVol$_\n";
my $supplyCont=0;
my %breakpointReplacement;
#===================================
#####################################
#obtain the instance for each SCC
#####################################
open( SCCInst, "./SCCInst.txt") || die "Can't open myfile: $!";
my @SCCInst=<SCCInst>;
close(SCCInst);
my %SCCInst;
foreach (@SCCInst)
if(/^(SCC\d+)\s+(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCInst$1=\@temp;
print "\n**SCC instance list**\n";
foreach (keys %SCCInst)
print "$_ @$SCCInst$_\n";
print "current SCC is: $input1 @$SCCInst$input1\n\n";
#####################################
#obtain the original netlist, controlling devices and controlling voltage
#####################################
open( MYFILE, "./input.scs") || die "Can't open myfile: $!";
my @address_input=<MYFILE>;
#print @address_input,"\n";
close(MYFILE);
open( MYINPUT, "$address_input[0]") || die "Can't open myfile: $!";
my @input_scs=<MYINPUT>;
188
print @input_scs;
close(MYINPUT);
my %ctrlInst;
my %ctrlVolt_Inst;
my $ctrlVolt;
my @ctrlVolt;
my @BPS;
foreach $_ (@address_input)
if(/^\"(.*)\"\s\"(.*)\"/)
print $1,"!!!\t",$2,"\n";
my $A=$1;
my $B=$2;
#============================================================
=============
#this code is trying to deal with net name like "Vi-" "Vi+"
if(($B=~/(.*)(\-)/) or ($B=~/(.*)(\+)/))
$B=$1.'\\\\'.$2;# $B will be Vi\\- since in matching rule the first '\' is to tell the
second '\' is a charactor in the original string
#============================================================
=============
$ctrlInst$A=$B;#$A is contolling device and $B is controlling voltage
$ctrlVolt_Inst$B=[] if (not exists $ctrlVolt_Inst$B);
$ctrlVolt_Inst$B=[@$ctrlVolt_Inst$B, $A];
push @ctrlVolt, $B;
$ctrlVolt=$B;
#=================================================================
========
#=================================================================
========
elsif(/^MyBPS:\s(.*)/)
print "$1\n";
my @temp=split(/ /,$1);
foreach my $net (@temp)
if(($net=~/(.*)(\-)/) or ($net=~/(.*)(\+)/))
$net=$1.'\\\\'.$2;# $B will be Vi\\- since in matching rule the first '\' is to tell
the second '\' is a charactor in the original string
189
push @BPS, $net;
$ctrlVolt=$BPS[0];
#=================================================================
========
#=================================================================
========
print "BPS: @BPS\nThe first controVolt: $ctrlVolt\n";
print "\n**ctrlVolt_Inst list**\n";
foreach $_ (keys %ctrlVolt_Inst)
print "$_ => @$ctrlVolt_Inst$_\n";
#=================================================================
========
#=================================================================
========
#=================================================================
========
open( PATHLIST, "./pathList.txt") || die "Can't open myfile: $!";##'>' means write only, it
will clear and rewrite the file.
my @pathList=<PATHLIST>;
my %BPSPowerSuply;
foreach (@pathList)
if(/^path\d+=>(.*)/)
print $1,"\n";
my @temp=split(/\s+/,$1);
foreach my $sup (@BPS)
if(/$sup/)
print " the breakpint $sup is in path $_ therefore one of its vdd is:
$temp[0]\n";
if(not exists
$BPSPowerSuply$sup)$BPSPowerSuply$sup=[$temp[0]];
else$BPSPowerSuply$sup=[@$BPSPowerSuply$sup, $temp[0]];
190
print "\n**BPS Power Suply list**\n";
foreach (keys %BPSPowerSuply)
print "$_ @$BPSPowerSuply$_\n";
#=================================================================
========
print "\n**Controlling inst for all nets in positive loops**\n";
open( CTRLINST, "./controlInstList.txt") || die "Can't open myfile: $!";
my @ctrlInstForAllNets=<CTRLINST>;
close(CTRLINST);
my %ctrlInstForAllNets;
foreach $_ (@ctrlInstForAllNets)
my @temp=split(/\s+/,$_);
# print "@temp\t";
my $net=$temp[0];
my @inst=grep !/$net/, @temp;
if(($net=~/(.*)(\-)/) or ($net=~/(.*)(\+)/))
$net=$1.'\\\\'.$2;# $B will be Vi\\- since in matching rule the first '\' is to tell the
second '\' is a charactor in the original string
print "$net => @inst\n";
$ctrlInstForAllNets$net=\@inst;
my %ctrlVolt_Inst1;
foreach (@BPS)
$ctrlVolt_Inst1$_=$ctrlInstForAllNets$_
print "\n**ctrlVolt_Inst1 list**\n";
my @hier_ctrlVolt=split(/\./,$ctrlVolt); #I1.B => I1 B
my $numHier=@hier_ctrlVolt;
my %ctrledBlock;
my %ctrlingBlock;
foreach $_ (keys %ctrlVolt_Inst1)
print "$_ => @$ctrlVolt_Inst1$_\n";
my @temp1=split(/\./,$_ ); #I1.B => I1 B
191
my $inNum=@temp1;
if($inNum>1) $ctrlingBlock$_=$temp1[$inNum-2];
foreach my $ins(@$ctrlVolt_Inst1$_)
my @temp2=split(/\./,$ins);
my $outNum=@temp2;
if($outNum>1 && ($outNum > $inNum)) #if $outNum > $inNum means that the
controling instance is insider a block of the CV level
$ctrledBlock$_=[] if (not exists $ctrledBlock$_);
$ctrledBlock$_=[@$ctrledBlock$_, $temp2[$outNum-2]];# for control
device like I1.P7 the block I1 also has terminal shoulbe be changed to Vin
if($ctrlingBlock$_)print "ctrlingBlock: $ctrlingBlock$_\n";
if($ctrledBlock$_)print " ctrlingBlock: @$ctrledBlock$_\n";
@ctrlVolt=@BPS;
%ctrlVolt_Inst=%ctrlVolt_Inst1;
=ppod
if($numHier==1)
print "wowowowo\n";
foreach $_ (keys %ctrlVolt_Inst1)
print "!!$_ => @$ctrlVolt_Inst1$_\n";
foreach my $ins(@$ctrlVolt_Inst1$_)
my @temp=split(/\./,$ins);
print "$ins!!! @temp\n";
=cut
#######################################################
#following codes is to find the subcircuit of a netlist
########################################################
print "\n**find the subcircuit of a netlist**\n";
my %subckt_termi;
my %subckt_netlist;
my @subNetlist;
my $subckt_name;
my $flag=0;
my @topLevel;
192
my @netlist=@input_scs;
for (my $i=0; $i<@netlist;$i++)
#print "$netlist[$i]";
my $currentLine=$netlist[$i];
chop $currentLine;
$_=$netlist[$i];
if(/^subckt\s(.*)/)
my @temp=split(/\s+/,$1);
$subckt_name=$temp[0];
my @terms=grep !/$subckt_name/, @temp;
#print "$subckt_name\t@terms\n";
$subckt_termi$subckt_name=\@terms;
@subNetlist=();
$flag=1;
push @subNetlist, $_;
elsif($flag)
push @subNetlist, $_;
if(/^ends/)
#pop @subNetlist;
$subckt_netlist$subckt_name=[@subNetlist];
$flag=0;
if(!/^ends/ and $flag==0)
push @topLevel,$currentLine;
print "\n**Top level**\n";
for (my $i=0; $i<@topLevel;$i++)
print "$topLevel[$i]\n";
print "\n**subckt netlist**\n";
foreach (keys %subckt_termi)
# print "$_ (@$subckt_termi$_)\n";
print "@$subckt_netlist$_\n";
193
#=================================================================
========
#=================================================================
========
#####################################
#generate a new netlist to be the same as we're breaking and inserting a voltage
#source at the break-points
#the relsulting netlist **.scs can be used as input file for break-loop homotopy
#method
#####################################
my @newInputScs;
my $BPSindex=1;
my $Vx="ITV2014vx".$BPSindex;
my $Vin="ITV2014Vin".$BPSindex;
my $Vout="ITV2014Vout".$BPSindex;
#==============================================
$breakpointReplacement$ctrlVolt=[$Vin, $Vout, $Vx];
#==============================================
my @instNotInSCC;
my $para_flag=0;
print "\n**For breakPoint: $ctrlVolt**\n";
;#foreach my $netLine (@input_scs)
for (my $index=0;$index<@input_scs;$index++)
my $netLine=$input_scs[$index];
my $currentOutputLine=$netLine;
$_=$netLine;
if($para_flag==1)
push @newInputScs, $netLine;
#add extra parameters
if(/^parameters/) # if3
chomp $currentOutputLine;# remove any newline character from the end of a string
my @temp1=split(/\s+/,$currentOutputLine);
foreach $_ (@temp1)
194
if(/^Vx(\d+)/) ##the circuit may have some DC voltage named as "Vx**"
$BPSindex=$1+1;
if($BPSindex>0)
$Vx='ITV2014vx'.$BPSindex;#create a new DC voltage
$Vin="ITV2014Vin".$BPSindex;#create a new net name as controlling voltage
$currentOutputLine=$currentOutputLine.' '."$Vx\n";
#==============================================
$breakpointReplacement$ctrlVolt=[$Vin, $Vout];
#==============================================
#==============================================================
#
elsif(/^(V\d+)\s/)##the lines that may contain the power supply voltage source
if(exists $supplyVol$1)
my $volName=$1;
print "############The instance $1 is used to generate vdd:
$supplyVol$volName\n";
my $flag=0;
foreach my $BP (keys %BPSPowerSuply)
if(grep /$supplyVol$volName/, @$BPSPowerSuply$BP)
print "############The $supplyVol$volName in used for
breakpoint: $BP, thus need to changed!\n";
$flag=1;
last;
if($flag==1)
pop @newInputScs;
my $volVal;
if(/dc=(.*)\stype/)
$volVal=$1;
print "The DC value of this vdd is: $volVal????\n";
$supplyCont++;
push @newInputScs,"$volName ($supplyVol$volName 0) vsource
dc=ITV2014vdx$supplyCont type=dc\n";
$SUPPLY$supplyVol$volName="ITV2014vdx".$supplyCont."
$volName dc=$volVal";
195
#==============================================================
elsif(/^\/\/\s+Library/ or /^\/\/\s+Cell/ or /^\/\/\s+View/) #we want to copy the first three line
push @newInputScs, $netLine;
elsif(/^simulatorOptions/) # we want to insert a line for sweeping voltage source before this
line
pop @newInputScs;
#print "$Vx ($Vin 0) vsource dc=$Vx type=dc\n";
if($numHier==1)
push @newInputScs,"$Vx ($Vin 0) vsource dc=$Vx type=dc\n";
$para_flag=0;
elsif(/^(\w+\d+)\s/) ##the lines that contain the instance netlist
my $currentIns=$1;
if(grep $_ eq $1 @$SCCInst$input1) ###if1
print "$1 is an instance in current SCC!!!!!! \n";
#=================================================================
==============
# end if1
else
if(!/^(V\d+)\s/ && !/^(I\d+)\s/)
print "Line$index $1 is not an instance in current SCC!!!!!! \n";
push @instNotInSCC, $1;
#end if1 else
#=================================================================
==============
$para_flag=1; #this is to make sure the original netlist lines is before the added line
my $temp=pop @newInputScs;
#print "previous line is ", $temp,"\n";
my $Vout1=$Vout.' '; # Ensure that we replace the word $Vout as a whole (avoid
such case: 'Vo'ut-> 'Vout'ut
$temp=~s/$ctrlVolt\s/$Vout1/g;
$Vout1=$Vout.')';
$temp=~s/$ctrlVolt\)/$Vout1/g;
#print "after change previous line is ", $temp,"\n";
196
push @newInputScs, $temp;
#print "current line is ", $netLine, "\n";
$Vout1=$Vout.' ';
$netLine=~s/$ctrlVolt\s/$Vout1/g;
$Vout1=$Vout.')';
$netLine=~s/$ctrlVolt\)/$Vout1/g;
#print "after change current line is ", $netLine,"\n";
if($temp ne $netLine)
push @newInputScs, $netLine;
foreach my $ins (@$ctrlVolt_Inst$ctrlVolt)
if($currentIns eq $ins) #means find the controlling device line
print "$currentIns is corlling;;;\n";
print "before change:\n$netLine";
$netLine=~s/$Vout/$Vin/g; #replace the controlling voltage with Vin
print "after change:\n$netLine\n";
pop @newInputScs;
push @newInputScs,$netLine;
#end if
#end foreach
#============================================this consider the
controlling blocks
foreach my $ins (@$ctrledBlock$ctrlVolt)
if($currentIns eq $ins) #means find the controlling device line
print "$currentIns is corlling;;;\n";
print "before change:\n$netLine";
$netLine=~s/$Vout/$Vin/g; #replace the controlling voltage with Vin
print "after change:\n$netLine\n";
pop @newInputScs;
push @newInputScs,$netLine;
#end if
#end foreach
#===========================================
#=================================================================
==============
#this part has been moved to before, because even for instances not belongs to
#current SCC we still want to print it out in the first run (so that we have access
#to an modified netlist including all instances with the break-pints modified)
=pod
# end if1
else
if(!/^(V\d+)\s/ && !/^(I\d+)\s/)
197
print "Line$index $1 is not an instance in current SCC!!!!!! \n";
push @instNotInSCC, $1;
#end if1 else
=cut
#=================================================================
==============
#end if3
#end foreach
=pod
##############################################################
#if an instance is not included in the SCC then there will be a extra continued line wchich we
don't want
#following codes is to delete that line
#my $previousLineInSCC=1;
if($previousLineInSCC ==0) ##if2
#pop @newInputScs;
$previousLineInSCC =1;
#end if2
=cut
#=================================================================
=========
#deal with breakpoint insider a subckt
print "\n**Trying to deal with breakpoint in subckt**\n";
#print "$ctrlVolt=>@$ctrlInstForAllNets$ctrlVolt \t@hier_ctrlVolt, $numHier\n";
if($numHier>=2)#means this circuit has hierachial
print "We need to create a new block for $hier_ctrlVolt[$numHier-2]\n";
my $ctrlVolt_Blk=$hier_ctrlVolt[$numHier-1];
print "Control Voltage:$ctrlVolt => $ctrlVolt_Blk \n";
my @ctrlVolt_Inst_Blk;
foreach(@$ctrlInstForAllNets$ctrlVolt)
my @temp=split(/\./,$_);
push @ctrlVolt_Inst_Blk,$temp[-1];
print "Control instances: @$ctrlInstForAllNets$ctrlVolt => @ctrlVolt_Inst_Blk\n";
for (my $i=0;$i<@newInputScs; $i++)
$_=$newInputScs[$i];
if(/$hier_ctrlVolt[$numHier-2](\s\(.*\)\s)(.*)/) #find the block in the last level
198
print "$_\n";
#print "$1\t$2\n";
my $blkName=$2;
my $newName=$blkName.'_Break';
$newInputScs[$i]=~s/$blkName/$newName/;#change the block master name
print "=> $newInputScs[$i]\n";
#print "@$subckt_netlist$blkName\n";
$subckt_netlist$newName=$subckt_netlist$blkName; # create a new block
#modify it based on contol voltage and device
print "\n**For breakPoint: $ctrlVolt**\n";
=pod
$BPSindex=$BPSindex+1;
my $Vx="ITV2014vx".$BPSindex;#create a new DC voltage
my $Vin="ITV2014Vin".$BPSindex;#create a new net name as controlling voltage
my $Vout="ITV2014Vout".$BPSindex;
=cut
#==============================================
$breakpointReplacement$ctrlVolt=[$Vin, $Vout, $Vx];
#==============================================
my @subcktOld=@$subckt_netlist$blkName;
my @subcktNew;
for (my $index=0;$index<@subcktOld;$index++)
$_=$subcktOld[$index];
push @subcktNew,$_;
if(/(\w+\d+)\s/)
my $currentIns=$1;
my $temp=pop @subcktNew;
#print "current line is\n\t ",$temp, "\n";
my $Vout1=$Vout.' ';
$temp=~s/$ctrlVolt_Blk\s/$Vout1/g;
$Vout1=$Vout.')';
$temp=~s/$ctrlVolt_Blk\)/$Vout1/g;
#print "after change current line is \n\t", $temp,"\n";
push @subcktNew,$temp;
foreach my $ins (@ctrlVolt_Inst_Blk)
if($currentIns eq $ins) #means find the controlling device line
print "$currentIns is corlling;;;\n";
$temp=pop @subcktNew;
print "before change:\n$temp";
199
$temp=~s/$Vout/$Vin/g; #replace the controlling voltage with
Vin
print "after change:\n$temp\n";
push @subcktNew,$temp;
#end if
#end foreach
# end if
# end for
my $temp1=pop @subcktNew;
push @subcktNew,"$Vx ($Vin 0) vsource dc=$Vx type=dc\n";
push @subcktNew,$temp1;
$subcktNew[0]=~s/$blkName/$newName/;#change the block master name
$subcktNew[-1]=~s/$blkName/$newName/;#change the block master name
print "modified subckt:\n@subcktNew\n";
$subckt_netlist$newName=\@subcktNew; # create a new block
#=================================================================
=========
print "\n**After first breakPoint, modified Netlist:(without deleting instances in other
SCC)**\n";
print @newInputScs;
#=====================
foreach(keys %subckt_netlist)
#print "$_\n@$subckt_netlist$_\n";
my @newLine=grep /$_/,@newInputScs;
push @newInputScs,@$subckt_netlist$_;
print "\n**After modify the breakPoint in block , modified Netlist:(without deleting instances
in other SCC)**\n";
print @newInputScs;
#=====================
print "\n**Trying to delete the instance not in current SCC**\n";
my @newInputScs2=@newInputScs;
for (my $index=0;$index<@newInputScs2;$index++)
my $currentLine= $newInputScs2[$index];
$_=$currentLine;
if(/^(\w+\d+)\s/)
200
print $currentLine;
if(grep $_ eq $1 @instNotInSCC)
@newInputScs= grep $_ ne $currentLine @newInputScs;
my $nextLine=$newInputScs2[$index+1];
@newInputScs= grep $_ ne $nextLine @newInputScs;
print "\n**After first breakPoint, modified Netlist:(deleting instances in other SCC)**\n";
print @newInputScs;
##########################################################
###The following code is to deal with multiple breakPoints
##########################################################
#=================================================================
===============
#if we want to exclude the instances of other SCC use my @newInputScs1=@newInputScs;
(but it right now has problems for SCC that need input from other SCC)
#my @newInputScs1=@newInputScs;
my @newInputScs1=@newInputScs2;
#=================================================================
===============
if(keys %ctrlVolt_Inst>1)
print "\nThere are more than one break points: \n";
print keys %ctrlVolt_Inst,"\n";
my @otherPoints=grep (!/$ctrlVolt/,keys %ctrlVolt_Inst);
print @otherPoints,"\n";
#print $BPSindex;
foreach my $ctrlVolt (@otherPoints)
@newInputScs=@newInputScs1; #since each iteration we will add a new line the end
@newInputScs1=();
print "\n**For breakPoint: $ctrlVolt**\n";
$BPSindex=$BPSindex+1;
my $Vx="ITV2014vx".$BPSindex;#create a new DC voltage
my $Vin="ITV2014Vin".$BPSindex;#create a new net name as controlling voltage
my $Vout="ITV2014Vout".$BPSindex;
#==============================================
$breakpointReplacement$ctrlVolt=[$Vin, $Vout, $Vx];
#==============================================
for (my $index=0;$index<@newInputScs;$index++)
$_=$newInputScs[$index];
push @newInputScs1,$_;
201
if(/^(\w+\d+)\s/)
my $currentIns=$1;
my $temp=pop @newInputScs1;
#print "current line is\n\t ",$temp, "\n";
my $Vout1=$Vout.' ';
$temp=~s/$ctrlVolt\s/$Vout1/g;
$Vout1=$Vout.')';
$temp=~s/$ctrlVolt\)/$Vout1/g;
#print "after change current line is \n\t", $temp,"\n";
push @newInputScs1,$temp;
foreach my $ins (@$ctrlVolt_Inst$ctrlVolt)
if($currentIns eq $ins) #means find the controlling device line
print "$currentIns is corlling;;;\n";
$temp=pop @newInputScs1;
print "before change:\n$temp";
$temp=~s/$Vout/$Vin/g; #replace the controlling voltage with Vin
print "after change:\n$temp\n";
push @newInputScs1,$temp;
#end if
#end foreach
# end if
# end for
push @newInputScs1,"$Vx ($Vin 0) vsource dc=$Vx type=dc\n";
# end foreach
#end if
print "\n**Final modified Netlist**\n";
print @newInputScs1;
open( MODIFYINPUT, ">./input1.scs") || die "Can't open myfile: $!";##'>' means write only,
it will clear and rewrite the file.
print MODIFYINPUT @newInputScs1;
close(MODIFYINPUT);
#=================================================================
=====
open( MODIFIEDITEM, ">./modifiedItems.txt") || die "Can't open myfile: $!";##'>' means
write only, it will clear and rewrite the file.
print MODIFIEDITEM "POWER_SUPPLY $numSupplyVol\n";
foreach (keys %SUPPLY)
print MODIFIEDITEM "$_ $SUPPLY$_\n";
my $numBreakpoint=keys %ctrlVolt_Inst;
202
print MODIFIEDITEM "BREAK_POINTS $numBreakpoint\n";
foreach (keys %breakpointReplacement)
print MODIFIEDITEM "$_ @$breakpointReplacement$_
@$BPSPowerSuply$_\n";
close(MODIFIEDITEM);
#=================================================================
=====
3. findStrongConnComp.pl
#! /usr/bin/perl
#use FindBin;
#use lib "$FindBin::Bin/../Graph-0.96";
use strict;
use warnings;
use lib './ITV/breakLoop/Strong_conn_comp/Graph-0.96/lib';
use Graph::Directed;
my $g = Graph::Directed->new();
my $g1 = Graph::Directed->new();
my $g2 = Graph::Directed->new();
my $g3 = Graph::Directed->new();
my $g4 = Graph::Directed->new();
my $depenGraph = Graph::Directed->new();
open( MYFILE, "./dependencies.txt") || die "Can't open myfile: $!";
my @dependencies=<MYFILE>;
close(MYFILE);
#print @dependencies;
foreach (@dependencies)
my @temp=split(/\s/,$_);
$depenGraph->add_edges(@temp);
print "depenGraph is:\n $depenGraph\n";
open( MYFILE, "./negtiveLoops.txt") || die "Can't open myfile: $!";
my @negLoops=<MYFILE>;
@negLoops=split(/\s/,$negLoops[0]);
#print "Nodes in negative Loops: \n@negLoops\n";
close(MYFILE);
=pod
############################
####simplify the graph######
############################
203
my @depenGraph_vertices=$depenGraph->vertices;
foreach (@depenGraph_vertices)
my $inDegree=$depenGraph->in_degree($_);
my $outDegree=$depenGraph->out_degree($_);
if($inDegree==0 or $outDegree==0)
print "$_ in_degree=$inDegree out_degree=$outDegree\n";
$depenGraph=$depenGraph->delete_vertex($_);
print "simplified depenGraph is:\n $depenGraph\n";
=cut
# Each pair is a pair of vertices qw|a b| indicating
# a directed edge from a to b
# graph: lineitem <-> invioce <-> claim <-> insurer
$g1->add_edges( qw| A B B C
C D D A|);
$g2->add_edges( qw| A B B C
C D D A
B E E F F G G H H I I F|);
$g3->add_edges( qw|A B B C
C D D A
B E E F
F G G H
H I I F
I E E C|);
$g4->add_edges( qw| v1 v5 v1 v3
v1 v2 v2 v4
v3 v2 v3 v5
v4 v3 v4 v6 v6 v5|);
$g=$depenGraph;
#$g=$g2;
my @strongConnComp=$g->strongly_connected_components;
print "\nThe graph is: $g\n";
print "\n**Strongly connected components list**\n";
print "Before simplify:\n";
foreach (my $k=0; $k< @strongConnComp; $k++)
204
my $comp=$strongConnComp[$k];
print "Comp$k => @$comp\n";
#############################################################
####simplify the graph by deleting the one-element components
#############################################################
@strongConnComp=grep (@$_>1,@strongConnComp);
print "\nAfter simplify:\n";
foreach (my $k=0; $k< @strongConnComp; $k++)
my $comp=$strongConnComp[$k];
print "Comp$k => @$comp\n";
=pod
print "In_degree is: ";
print $g->in_degree('A'),"\n";
print "has_a_cycle is: ";
print $g->has_a_cycle,"\n";
print "find_a_cycle is: ";
print $g->find_a_cycle,"\n";
=cut
my @edges=$g->edges;
print "\n**Edges List***\n";
my $i=0;
foreach (@edges)
print "@$_\n";
my @vertices=$g->vertices;
my %breakPoint;
my $temp_g = Graph::Directed->new();
$temp_g->add_edges($g->edges);
my @ii=$temp_g->edges;
foreach (my $k=0; $k< @strongConnComp; $k++)
my $comp=$strongConnComp[$k];
########## obtain the subgraph for each strongcomponent##
my $temp_g = Graph::Directed->new();
print "\nFor Comp$k: @$comp\n";
foreach my $edge (@edges)
205
if((grep($_ eq @$edge[0]) @$comp) and (grep($_ eq @$edge[1])
@$comp))
#print "@$edge\n";
$temp_g->add_edges(@$edge);
print "subgraph:$temp_g\n";
###############################################
#identify break point for each component
###############################################
my @vertices=$temp_g->vertices;
my $breakOnlyNegLoop;
$breakOnlyNegLoop=0;
if($breakOnlyNegLoop==1)
print "\n###Nodes before deleting the nodes of negative loop:\n @vertices\n";
print "Nodes in negative Loops: \n@negLoops\n";
###### The following part is trying to get rid of the negative loop nodes
###### it enable us to break only positive loops
##*****************************************************
my %negLoops;
map($negLoops$_=1,@negLoops); # create %negLoops with elements from
@negLoops
my @verticesDiff=grep(!defined($negLoops$_),@vertices); # returns those elements of
@vertices that don't
# have a hash element in %negLoops therefore they
# do not exist in @negLoops.
print " \n###Remaining nodes after deleting the nodes of negative loop:\n @verticesDiff\n";
@vertices=@verticesDiff;
##*******************************************************
my @currentBreakingPoint;
if(@vertices>0)
########## Try to find one arc as breaking point##
print "Try to find one arc as breaking point...\n";
foreach (@vertices)
my $c=$temp_g->copy_graph;
#print " Before deleting, the copy graph is $c\n";
$c=$c->delete_vertex($_);
206
# print " After deleting $_, the copy graph is $c\n";
if(/^path/)
elsif (!$c->has_a_cycle)
push @currentBreakingPoint, $_;
last;
#foreach
############ Try to find two arcs as breaking points##
if(@currentBreakingPoint>0)
print"Get a break point: @currentBreakingPoint\n";
else
print "Try to find two arcs as breaking points...\n";
foreach (my $i=0; $i < @vertices; $i++)
foreach (my $j=$i+1; $j < @vertices; $j++)
my $c=$temp_g->copy_graph;
# print " Before deleting, the copy graph is $c\n";
$c=$c->delete_vertices($vertices[$i],$vertices[$j]);
# print " After deleting $vertices[$i] and $vertices[$j], the copy graph is $c\n";
if($vertices[$i]=~/^path/ or $vertices[$j]=~/^path/)
elsif ($c->is_acyclic)
push @currentBreakingPoint, $vertices[$i];
push @currentBreakingPoint, $vertices[$j];
last;
#foreach
if (@currentBreakingPoint>0)##after finding two breaking point, stop the foreach
print"Get two break point: @currentBreakingPoint\n";
last;
#foreach
# if
if(@currentBreakingPoint==0)print " **warnning** breaking points is larger than 2
for this components!\n";
else$breakPoint$k=\@currentBreakingPoint;
#if
207
print "\n**BreakPoints List**\n";
foreach (keys %breakPoint)
print "For Comp$_:@$strongConnComp[$_]\n @$breakPoint$_ \n";
4. findPath.pl
#! /usr/bin/perl
use constant LAST => -1;
use constant PATH => 0;
use constant SEEN => 1;
use strict;
use warnings;
sub find_paths
my ($beg, $end, $graph) = @_;# $graph is the ref of %graph
my @solution;
my @work;
for (@$graph->$beg) # $graph->$beg is the ref of key "$beg"
# push @solution, [$beg, $end] if $_ eq $end;
if ($_ eq $end)
push @solution, [$beg, $end];
next;
push @work, [[$beg, $_], $beg => undef, $_ => undef];
#the hash with undef is to check whether the node hasbeen visited
while (@work)
my $item = pop @work;
my ($path, $seen) = @$item[PATH, SEEN];
for my $node (@$graph->$path->[LAST])
next if exists $seen->$node;
my @new_path = (@$path, $node);
if ($node eq $end)
push @solution, \@new_path;
next;
my %new_seen = (%$seen, $node => undef);
push @work, [\@new_path, \%new_seen];
return \@solution;
208
1;
5. flattenNetlist.pl
#! /usr/bin/perl
use strict;
use warnings;
use lib './ITV/breakLoop/Strong_conn_comp/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
my $start_time=time();
my $start_time2=localtime();
print "start at:$start_time2\n";
####open the net_from_cadence that generated from Cadence.
open( MYFILE, "./myFile_hier") || die "Can't open myfile: $!";
my @netlist=<MYFILE>;
print @netlist;
close(MYFILE);
=pod
my @temp=@netlist_from_cadence;
while(@temp)
my $item=pop @temp;
print "$item";
=cut
my %subckt_termi;
my %subckt_netlist;
my @subNetlist;
my $subckt_name;
my $flag=0;
my @topLevel;
for (my $i=0; $i<@netlist;$i++)
#print "$netlist[$i]";
my $currentLine=$netlist[$i];
chop $currentLine;
$_=$netlist[$i];
if(/^subckt\s(.*)\s\(\"(.*)\"\)/)
209
#print "!!!$_";
#print "$1\t$2\n";
$subckt_termi$1=[split(/\" \"/,$2)];
#print "$1 => @$subckt_termi$1 \n\n";
$subckt_name=$1;
@subNetlist=();
$flag=1;
elsif($flag)
push @subNetlist, $_;
if(/^ends\ssubckt/)
pop @subNetlist;
$subckt_netlist$subckt_name=[@subNetlist];
$flag=0;
if(!/^ends\ssubckt/ and $flag==0)
push @topLevel,$currentLine;
print "\n**Top level**\n";
for (my $i=0; $i<@topLevel;$i++)
print "$topLevel[$i]\n";
print "\n**subckt netlist**\n";
foreach (keys %subckt_termi)
print "$_ (@$subckt_termi$_)\n";
print "@$subckt_netlist$_\n";
#############################################
# flatten a Block
#############################################
sub printBlock
my ($blockName,$master,$term,$termConn)=@_;
210
print "===$blockName \. $master \. (@$term) => @$termConn===\n";
my %term;
my %termConn;
map($term$_=1,@$term);
for (my $i=0; $i<@$term;$i++)
$termConn@$term[$i]=@$termConn[$i];
# print "@$subckt_netlist$master\n";
my %netlist_hash;
my %instance_prop;
my $instance_name;
my @newNets;
my @flatNetlist;
my $currentMaster;
foreach $_ (@$subckt_netlist$master) ##foreach line in the master
my $currentLine=$_;
chop $currentLine;
if(/^(\w+\d+)\s+\(\"(.*)\"\)\s+(\w+)\s/)
$netlist_hash$1=[split(/\" \"/,$2)]; # get all the nets in this instance
# print "$1 => @$netlist_hash$1 $3\n";
$instance_name=$blockName.'.'.$1;
$instance_prop$1=$3;
$currentMaster=$3;
@newNets=();
for (my $j=0; $j<@$netlist_hash$1;$j++) ##foreach net in this instance
my $oriNetInSubckt=@$netlist_hash$1[$j];
#print "$oriNetInSubckt\t$term$oriNetInSubckt\n\n!!";
#print keys %term,"!!\n";
if(exists $term$oriNetInSubckt)
#print "$oriNetInSubckt is a pin, should connect to upper level node:
$termConn$oriNetInSubckt\n";
push @newNets,$termConn$oriNetInSubckt;
@$netlist_hash$1[$j]=$termConn$oriNetInSubckt;
##end if
else
push @newNets,$blockName.'.'.$oriNetInSubckt;
211
@$netlist_hash$1[$j]=$blockName.'.'.$oriNetInSubckt;
##end foreach
#print "!!!!!!!$instance_name=>@newNets\n";
my $temp=join("\" \"", @newNets);
$currentLine=$instance_name." (\"".$temp."\") ".$instance_prop$1;
push @flatNetlist,$currentLine;
if(exists $subckt_netlist $currentMaster)
#print "\nget it!!! $currentMaster\n";
pop @flatNetlist;
my $preLevelNetlist;
$preLevelNetlist=printBlock($instance_name,$3,$subckt_termi$3,$netlist_hash$
1);
push @flatNetlist, @$preLevelNetlist;
##end if
##end if
elsif(!exists $subckt_netlist $currentMaster)
push @flatNetlist,$currentLine;
##end foreach
for (my $i=0; $i<@flatNetlist;$i++)
print"$flatNetlist[$i]\n";
return \@flatNetlist;
my @term=("VSS", "A", "B") ;
my @termConn=("gnd!", "A", "B");
#printBlock("I0","Block",\@term,\@termConn);
print "\n**fatten netlist**\n";
open( FLATNETLIST, ">./flattenNetlist.txt") || die "Can't open myfile: $!";##'>' means write
only, it will clear and rewrite the file.
my @topLevelFlatten=@topLevel;
for (my $i=0; $i<@topLevel;$i++)
$_=$topLevel[$i];
#print "!!!!!!!$_\n\n";
#if(/^(\w+\d+)\s+\(\"(.*)\"\)\s+(\w+)\s/)
212
if(/^(\w+\d+)\s+\(\"(.*)\"\)\s+(\w+)/)
my $master=$3;
#print "master: $master\n";
if(exists $subckt_netlist$master)
my $blockName=$1;
my $termConn=[split(/\" \"/,$2)];
my $nextLine=$topLevel[$i+1];
$nextLine=~s/\(\"//g;
$nextLine=~s/\"\)//g;
my $term=[split(/\" \"/,$nextLine)];
for (my $i=0; $i<@$term;$i++) # this is to make sure each element in
@$term) will not have space
@$term[$i]=~s/\s+//g;
print "===$blockName \. $master \. (@$term) => @$termConn===\n";
my $newBlock=printBlock($blockName,$master,$term,$termConn);
@topLevelFlatten = grep $_ and ($_ ne $topLevel[$i]) and ($_ ne $topLevel[$i+1])
@topLevelFlatten;
push @topLevelFlatten,@$newBlock;
elseprint "$topLevel[$i]\n";
elseprint "$topLevel[$i]\n";
print "\n**fatten netlist**\n";
for (my $i=0; $i<@topLevelFlatten;$i++)
print "$topLevelFlatten[$i]\n";
print FLATNETLIST "$topLevelFlatten[$i]\n";
close(FLATNETLIST);
6. identifySCC.il
;;;load("./ITV/identifySCC.il")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;identify the SCC list for current;;;;;;;;;;
;;;;;schematic and try display the loops for each SCC ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
213
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;read data from a file and store them into a table
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CV=geGetEditCellView()
tableName = sprintf( nil "%s %s %s"
CV~>libName CV~>cellName CV~>viewName )
loopTable=makeTable(tableName nil)
loopTableNameList=nil
pathTable=makeTable(tableName nil)
let( (inport nextLine loopList loopName pathName)
inport=infile("./loopList.txt")
when( inport
while(gets(nextLine inport)
println(nextLine)
loopList=parseString(nextLine)
if( rexMatchp("loop" car(loopList)) then
loopName=car(loopList)
loopTable[loopName]=append(loopTable[loopName] cdr(loopList))
loopTableNameList=append1(loopTableNameList loopName)
else rexMatchp("path" car(loopList))
pathName=car(loopList)
pathTable[pathName]=append(pathTable[pathName] cdr(loopList))
);if
);while
close(inport)
);when
);let
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;procedure for highlight loops;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;select nets
procedure( selectNet(NetId)
let((NetFigs fig)
NetFigs=NetId~>figs
foreach( fig NetFigs
geSelectFig(fig)
);foreach
);let
);procedure
;;select instance
procedure( selectInst(instId)
214
geSelectFig(instId)
);procedure
;;highlight Nets
;lpp=list("y0" "drawing")
procedure(highLightNet(hlSetId netId)
let((fig)
;hlSetId=geCreateHilightSet(CV lppNet)
hlSetId->enable = nil
foreach(fig netId~>figs geAddHilightFig(hlSetId fig))
hlSetId->enable = t
);let
);proc
;;highlight Instance
procedure(highLightInst(hlSetId instId)
;hlSetId=geCreateHilightSet(CV lppInst)
hlSetId->enable = nil
geAddHilightFig(hlSetId instId)
hlSetId->enable = t
);proc
;;select path
procedure(selectPath(path)
let((NetId InstId item hierachi_item)
MyVdd=loopListForm->Vdd->value
MyVss=loopListForm->Vss->value
Temp1=parseString(MyVdd " ")
Temp2=parseString(MyVss " ")
PowerNet=append(Temp1 Temp2)
foreach(item path
if(!member(item PowerNet) then
hierachi_item=parseString(item ".")
item=car(hierachi_item)
NetId=dbFindNetByName(CV item);gets DataID for Net as to get the and select figs
attached.
InstId=dbFindAnyInstByName(CV item);gets DataID for Inst as to get the and select figs
attached.
if( NetId then selectNet(NetId)
else selectInst(InstId)
);if
);if
);foreach
);let
215
);procedure
;find the transistor that cause net-to-path dependencies and select
procedure(findTransCauseDepen(netName pathName flash)
let((itemId itemTermNet hlSetId)
;println("Now find depen")
;printf("begin net is %s and target path is %s\n" netName pathName)
foreach(pathItem pathTable[pathName]
itemId=dbFindAnyInstByName(CV pathItem)
if( itemId then;;or if(pathItem~>objType=="inst"
;printf("the for Terminal of instance %s is connected to:" itemId~>name)
;println(itemId~>instTerms~>net~>name)
foreach(itemTermNet itemId~>instTerms~>net~>name
if(itemTermNet==netName then
;println(itemId~>name)
;println(itemTermNet)
;printf("dependency from %s to %s of %s is highlighted!\n" netName
itemId~>name pathName)
lppInst=list("y2" "drawing")
;;;flash
; hlSetIdFlash=geCreateHilightSet(CV lppInst)
; highLightNet(hlSetIdFlash NetId)
; hiUpdate()
; hiSleep(1)
; geDeleteHilightSet(hlSetIdFlash)
; hiUpdate()
; hiSleep(1)
hlSetId=geCreateHilightSet(CV lppInst)
highLightInst(hlSetId itemId)
hiUpdate()
;;flash
if(flash=="YES" then
selectInst(itemId)
hiUpdate()
hiSleep(1)
geDeselectFig(itemId)
hiUpdate()
hiSleep(1)
);if
selectInst(itemId)
);if
);foreach
);if
);foreach
216
);let
);proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;highlight components( in sequence and flash);;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
procedure(highLightLoopInSequence(loopName lpp flash)
let((lastItem Term NetId InstId parseTerm Temp hlSetId)
geDeselectAllFig(CV)
geDeleteAllHilightSet(CV)
lastItem=car(last(loopTable[loopName]))
lastItem1=nil;;;mainly to deal with some net name formed from combining the gate
resistors
foreach(Term cdr(loopTable[loopName])
;println(Term)
if( rexMatchp("path" Term) then
findTransCauseDepen(lastItem Term flash)
if(lastItem1 then
findTransCauseDepen(lastItem1 Term flash)
);if
else
Temp=parseString(Term "_")
;println(Temp)
foreach(parseTerm Temp
NetId=dbFindNetByName(CV parseTerm );gets DataID for Net as to get and select
the figs attached
InstId=dbFindAnyInstByName(CV parseTerm );gets DataID for Instance as to get
and select the figs attached
hlSetIdFlash=geCreateHilightSet(CV lpp)
hlSetId=geCreateHilightSet(CV lpp)
if(NetId then
;println(NetId~>name)
;;;flash
if(flash=="YES" then
highLightNet(hlSetIdFlash NetId)
hiUpdate()
hiSleep(1)
geDeleteHilightSet(hlSetIdFlash)
hiUpdate()
hiSleep(1)
);if
highLightNet(hlSetId NetId)
hiUpdate()
else
217
;println(InstId~>name)
;;;flash
if(flash=="YES" then
highLightInst(hlSetIdFlash InstId)
hiUpdate()
hiSleep(1)
geDeleteHilightSet(hlSetIdFlash)
hiUpdate()
hiSleep(1)
);if
highLightInst(hlSetId InstId)
hiUpdate()
);if
);foreach
lastItem=car(Temp);; the first and the last net parsed from the combined name may
both possibly be the controlling voltage
lastItem1=car(last(cdr(Temp)))
);if
);foreach
);let
);procedure
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;show the path table;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
println(";;;path list;;;;")
foreach(pathName pathTable
println(
list(pathName pathTable[pathName])
);println
;selectPath(pathTable[pathName])
);foreach
;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;show the loop table;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;
println(";;;loop list;;;;")
foreach(loopName loopTable
println(
list(loopName loopTable[loopName])
);println
);foreach
218
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;show the interface of loop highlighting;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
procedure( TrShowListBox( aList )
hiShowListBox(
?name gensym( 'TrExampleListBox )
?choices aList
?callback 'TrExampleListBoxCB
?title "Loop List"
?multipleSelect t
?applyButton t
)
) ; procedure
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;differentiate negative and positive loops ;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
positiveLoop=nil
negativeLoop=nil
loopListName=nil
let((loopSign posLoopNum negLoopNum combName loopTable_temp combName1)
posLoopNum=0
negLoopNum=0
loopTable_temp=loopTable
loopTable=makeTable(tableName nil);;since I want to change the table keyword so I store
the original table in a temperary and create a new table
foreach(loopName loopTableNameList
;foreach(loopName loopTable_temp
loopSign=car(loopTable_temp[loopName])
if(loopSign=="positive" then
posLoopNum=posLoopNum+1
combName=strcat("Positive loop" pcExprToString(posLoopNum))
;combName=strcat("Positive" loopName)
loopTable[combName]=loopTable_temp[loopName]
positiveLoop=append1(positiveLoop combName)
;print("new table Item:")
println(combName)
println(loopTable_temp[loopName])
else
negLoopNum=negLoopNum+1
combName=strcat("Negative loop" pcExprToString(negLoopNum))
;combName=strcat("Negative" loopName)
loopTable[combName]=loopTable_temp[loopName]
negativeLoop=append1(negativeLoop combName)
;print("new table Item:")
219
println(combName)
println(loopTable_temp[loopName])
);if
);foreach
);let
println(positiveLoop)
println(negativeLoop)
loopListName=append(positiveLoop negativeLoop)
;=================================================================
;=================================================================
;=================================================================
;=================================================================
;=================================================================
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;procedure for auto-searching the break-points;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
strongCompnents_list=nil
procedure(autoIdentifySCC()
breakPointsTable=makeTable("breakPointsTable" nil);
breakOnlyPFLTable=makeTable("breakOnlyPFLTable" nil);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;get the SCC table;;;;;
SCCTable=makeTable(tableName nil)
let( (inport nextLine SCCList SCCName)
inport=infile("SCCList.txt")
when( inport
while(gets(nextLine inport)
SCCList=parseString(nextLine)
if( rexMatchp("SCC" car(SCCList)) then
SCCName=car(SCCList)
SCCTable[SCCName]=append(SCCTable[SCCName] cdr(SCCList))
);if
);while
close(inport)
);when
);let
220
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;show the SCC table;;;;;
printf("\n**SCC List**\n")
foreach(SCCName SCCTable
println(
list(SCCName SCCTable[SCCName])
);println
;selectSCC(SCCTable[SCCName])
);foreach
printf("\n**get the instance of each SCC**\n")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;get the instance of each SCC;;;;;
let((myPort SCCName SCCitem pathItem)
myPort = outfile("./SCCInst.txt")
foreach(SCCName SCCTable ;;foreach1
fprintf(myPort "%s" SCCName)
foreach(SCCitem SCCTable[SCCName] ;;foreach2
if(rexMatchp("path" SCCitem) then ;;if1
;println(list(SCCitem pathTable[SCCitem]))
foreach(pathItem pathTable[SCCitem] ;;foreach3
if(dbFindAnyInstByName(CV pathItem) then ;;if2
fprintf(myPort " %s" pathItem)
);;if2
);foreach3
);;;if1
);foreach2
fprintf(myPort "\n")
);foreach1
close(myPort)
);let
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;get the loopInSCC table;;;;;
loopInSCC=makeTable(tableName nil)
let( (inport nextLine SCCList SCCName posLoopNum negLoopNum)
inport=infile("loopOfSCC.txt")
when( inport
posLoopNum=0
negLoopNum=0
while(gets(nextLine inport)
SCCList=parseString(nextLine)
221
;;fowwing code create a table to change the loop name correspond to that in
the createNetlist.il
;;and keep the infor of the SCC it belongs to
if(rexMatchp("positive" car(SCCList)) then
posLoopNum=posLoopNum+1
combName=strcat("Positive loop" pcExprToString(posLoopNum))
loopInSCC[combName]=cadr(SCCList)
else
negLoopNum=negLoopNum+1
combName=strcat("Negative loop" pcExprToString(negLoopNum))
loopInSCC[combName]=cadr(SCCList)
);if
);while
close(inport)
);when
);let
printf("\n**loopInSCC List**\n")
SCC_loop=makeTable(tableName nil)
foreach(SCCName loopInSCC
println(
list(SCCName loopInSCC[SCCName])
);println
SCC_loop[loopInSCC[SCCName]]=append1(SCC_loop[loopInSCC[SCCName]]
SCCName)
);foreach
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;show the loopOfSCC table;;;;;
printf("\n**SCC_loop**\n")
foreach(SCCName SCC_loop
println(
list(SCCName SCC_loop[SCCName])
);println
SCC_loop[SCCName]=sort(SCC_loop[SCCName] 'alphalessp)
println(
list(SCCName SCC_loop[SCCName])
);println
);foreach
printf("\n**Get the breakpoints table**\n")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;get the breakpoints table;;;;;
222
FILEDATA = infile("BreakPoints.txt")
while(gets(str, FILEDATA)
str=substring(str 1 strlen(str)-1)
LocLine= parseString(str ";")
printf("Now we have %L\n" LocLine)
strongCompnents_list=append1(strongCompnents_list car(LocLine))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;put the break-points into table
foreach(item cdr(LocLine)
last_Char=substring(item strlen(item) strlen(item))
first_Char=substring(item 1 1)
while(last_Char==" "
item=substring(item 1 strlen(item)-1)
last_Char=substring(item strlen(item) strlen(item))
);while
while(first_Char==" "
item=substring(item 2 strlen(item))
first_Char=substring(item 1 1)
);while
;;;;;;;Break-points for only PFLs
if(last_Char=="." then
printf("Got a break-point for breaking only PFL: %s\n" item)
item=substring(item 1 strlen(item)-1)
breakOnlyPFLTable[car(LocLine)]=append1(breakOnlyPFLTable[car(LocLine)],item)
;;;;;;;Break-points for both N/PFLs
else
breakPointsTable[car(LocLine)]=append1(breakPointsTable[car(LocLine)],item)
);if..else..
)
;breakPointsTable[nth(0 LocLine)]=nth(1 LocLine)
);while finish reading data
close(FILEDATA)
printf("\n**BreakOnlyPFLTable List**\n")
foreach( temp breakOnlyPFLTable
printf(" %s %L \n" temp breakOnlyPFLTable[temp])
)
printf("\n**BreakPointsTable List**\n")
foreach( temp breakPointsTable
printf(" %s %L \n" temp breakPointsTable[temp])
);foreach
223
); procedure autoIdentifySCC()
autoIdentifySCC()
;;procedure for selecting SCC
procedure(selectSCC(SCC)
geDeselectAll() ;;deselect previous SCC
geDeselectAllFig(CV)
geDeleteAllHilightSet(CV)
let((item)
foreach(item SCC
println(item)
if( rexMatchp("path" item) then
selectPath(pathTable[item])
);if
);foreach
);let
);procedure
;selectSCC(SCCTable["SCC0"])
loopListForm->strongCompList->choices=strongCompnents_list
7. identifyBPS.il
;;;load("./ITV/identifyBPS.il")
procedure(selectBreakPoint()
let((CV selWire lpp hlSetId)
;;;if the user does not select a node show a warinng dialog
selWire=geGetSelSet()
if(selWire==nil then
hiHighlightField( hiGetCurrentForm() 'BreakPoint 'error )
selectNetWarning()
;hiRaiseWindow(hiGetCurrentWindow())
else
;;;;highlight the selected net
CV=geGetEditCellView()
lpp=list("y0" "drawing")
hlSetId=geCreateHilightSet(CV lpp)
highLightNet(hlSetId car(selWire~>net))
;;;gemerate amd alter the netlist
hiHighlightField( hiGetCurrentForm() 'BreakPoint 'background )
224
hiGetCurrentForm()->BreakPoint->value=car(selWire~>net~>name)
;geDeselectAllFig(geGetEditCellView())
;load("./ITV/autoModifyNetlist/autoGenerateNetlist.il")
);if
);let
);procedure
breakPointsTable=makeTable("breakPointsTable" nil);
breakOnlyPFLTable=makeTable("breakOnlyPFLTable" nil);
FILEDATA = infile("BreakPoints.txt")
while(gets(str, FILEDATA)
str=substring(str 1 strlen(str)-1)
LocLine= parseString(str ";")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;put the break-points into table
foreach(item cdr(LocLine)
last_Char=substring(item strlen(item) strlen(item))
first_Char=substring(item 1 1)
while(last_Char==" "
item=substring(item 1 strlen(item)-1)
last_Char=substring(item strlen(item) strlen(item))
);while
while(first_Char==" "
item=substring(item 2 strlen(item))
first_Char=substring(item 1 1)
);while
;;;;;;;Break-points for only PFLs
if(last_Char=="." then
printf("Got a break-point for breaking only PFL: %s\n" item)
item=substring(item 1 strlen(item)-1)
breakOnlyPFLTable[car(LocLine)]=append1(breakOnlyPFLTable[car(LocLine)],item)
;;;;;;;Break-points for both N/PFLs
else
breakPointsTable[car(LocLine)]=append1(breakPointsTable[car(LocLine)],item)
);if..else..
)
;breakPointsTable[nth(0 LocLine)]=nth(1 LocLine)
);while finish reading data
close(FILEDATA)
printf("\n**BreakOnlyPFLTable List**\n")
225
foreach( temp breakOnlyPFLTable
printf(" %s %L \n" temp breakOnlyPFLTable[temp])
)
printf("\n**BreakPointsTable List**\n")
foreach( temp breakPointsTable
printf(" %s %L \n" temp breakPointsTable[temp])
);foreach
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;procedure for auto-displaying the break-points;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Breakpoints_list_copy=nil
BreakPFLpoints_list_copy=nil
procedure(autoDispBreakPoint()
println("for test")
println(loopListForm~>strongCompList~>value)
if(loopListForm~>strongCompList~>value==" " then
hiDisplayAppDBox(
?name gensym( 'trExampleDialogBox )
?dboxBanner "Warning"
?dboxText "Please Select a SCC!"
?dialogType hicWarningDialog
?dialogStyle 'modal
?location list(600 300)
);hiDisplayAppDBox
else
println("for test1")
println(loopListForm~>BreakOnlyPFLButton~>value)
;;;;;;;;;;;;display breaking-points for only PFLs;;;;
if(loopListForm~>BreakOnlyPFLButton~>value=="YES" then
println("for test2")
println(loopListForm~>strongCompList~>value)
println(breakOnlyPFLTable[loopListForm~>strongCompList~>value])
println("for test2")
if(breakOnlyPFLTable[loopListForm~>strongCompList~>value] then
if(BreakPFLpoints_list_copy==nil then
BreakPFLpoints_list_copy=breakOnlyPFLTable[loopListForm~>strongCompList~>value])
hiGetCurrentForm()->BreakPoint->value =strcat(""
car(BreakPFLpoints_list_copy) "")
BreakPFLpoints_list_copy=cdr(BreakPFLpoints_list_copy)
else
226
hiGetCurrentForm()->BreakPoint->value =""
hiDisplayAppDBox(
?name gensym( 'trExampleDialogBox )
?dboxBanner "Warning"
?dboxText "Can't Break only PFLs!!"
?dialogType hicWarningDialog
?dialogStyle 'modal
?location list(600 300)
);hiDisplayAppDBox
);if
;;;;;;;;;;;;display breaking-points for both N/PFLs;;;;
else
if(breakPointsTable[loopListForm~>strongCompList~>value] then
if(Breakpoints_list_copy==nil then
Breakpoints_list_copy=breakPointsTable[loopListForm~>strongCompList~>value])
hiGetCurrentForm()->BreakPoint->value =strcat(""
car(Breakpoints_list_copy) "")
Breakpoints_list_copy=cdr(Breakpoints_list_copy)
else
hiGetCurrentForm()->BreakPoint->value =""
hiDisplayAppDBox(
?name gensym( 'trExampleDialogBox )
?dboxBanner "Warning"
?dboxText "No BPS for both N/PFLs!!"
?dialogType hicWarningDialog
?dialogStyle 'modal
?location list(600 300)
);hiDisplayAppDBox
);if
);if
);if
); procedure
procedure(breakLoop()
;;;if the user does not select a node show a warinng dialog
println("the breakpoint is...")
println(hiGetCurrentForm()->BreakPoint->value)
if(hiGetCurrentForm()->BreakPoint->value=="" then
hiHighlightField( hiGetCurrentForm() 'BreakPoint 'error )
selectNetWarning()
else if(hiGetCurrentForm()->BreakPoint->value=="|BPS|>2" then
hiHighlightField( hiGetCurrentForm() 'BreakPoint 'error )
BPSGreaterThanTwoWarning()
else
227
hiHighlightField( hiGetCurrentForm() 'BreakPoint 'background)
load("./ITV/breakLoop/autoModifyNetlist/autoGenerateNetlist.il")
);else if
);if
);procedure
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;To check whether the vdd/vss fields
;have been specified with a selected net
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
procedure( checkBreakingPoint( myForm )
println(myForm->BreakPoint->value)
if(myForm->BreakPoint->value =="" then
println("You have to specify BreakPoint")
nil
else
println("You have specified BreakPoint")
t
) ;if
) ; procedure
procedure(formCheck(myForm)
println("now it is checking...")
println(checkBreakingPoint( myForm ))
if( checkBreakingPoint( myForm ) then
hiSetCallbackStatus( myForm t); the form will disappear after you set this status
hiHighlightField( myForm 'BreakPoint 'highlight )
else
hiHighlightField( myForm 'BreakPoint 'highlight )
hiSetCallbackStatus( myForm nil ); the form won't disappear after you set this status
) ; if
);procedure
8. searchBreakPoints.pl
#! /usr/bin/perl
#use FindBin;
#use lib "$FindBin::Bin/../Graph-0.96";
use strict;
use warnings;
use lib './ITV/breakLoop/Strong_conn_comp/Graph-0.96/lib';
use Graph::Directed;
use lib './ITV/breakLoop/Strong_conn_comp/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
my $input1=$ARGV[0];
228
my $input2=$ARGV[1];
if ($input1 eq "")
print "\n* usage:*\n";
print "-d choose if you like to show the debug output 1(YES) or 0(NO)\n";
print "Example: Perl ./searchBreakPoints.pl -d 1\n\n";
exit(1);
my $debugFlag=0; #determine wether to print out information
if( ($input1=~/-d$/)&& ($input2=~/0$/ or $input2=~/1$/ ))
$debugFlag=$input2; #determine wether to print out information
else
print "error parameter!\n";
exit(0);
my $g = Graph::Directed->new();
my $g1 = Graph::Directed->new();
my $g2 = Graph::Directed->new();
my $g3 = Graph::Directed->new();
my $g4 = Graph::Directed->new();
my $depenGraph = Graph::Directed->new();
open( MYFILE, "./dependencies.txt") || die "Can't open myfile: $!";
my @dependencies=<MYFILE>;
close(MYFILE);
#print @dependencies;
foreach (@dependencies)
my @temp=split(/\s/,$_);
$depenGraph->add_edges(@temp);
if($debugFlag==1)
print "depenGraph is:\n $depenGraph\n";
open( MYFILE, "./negtiveLoops.txt") || die "Can't open myfile: $!";
my @negLoops=<MYFILE>;
@negLoops=split(/\s/,$negLoops[0]);
#print "Nodes in negative Loops: \n@negLoops\n";
close(MYFILE);
229
#============================================
if($debugFlag==1)
print "\n**use to remove BreakPoints that are not gate**\n";
open( CTRLINST, "./controlInstList.txt") || die "Can't open myfile: $!";
my @ctrlInstForAllNets=<CTRLINST>;
close(CTRLINST);
my @potentialBreakpoints;
my %potentialBreakpoints;
foreach $_ (@ctrlInstForAllNets)
my @temp=split(/\s+/,$_);
push @potentialBreakpoints,$temp[0];
$potentialBreakpoints$temp[0]=1;
if($debugFlag==1)
print "!!!!!!!!!!!!All possible breakpoint: @potentialBreakpoints\n";
#============================================
=pod
############################
####simplify the graph######
############################
my @depenGraph_vertices=$depenGraph->vertices;
foreach (@depenGraph_vertices)
my $inDegree=$depenGraph->in_degree($_);
my $outDegree=$depenGraph->out_degree($_);
if($inDegree==0 or $outDegree==0)
print "$_ in_degree=$inDegree out_degree=$outDegree\n";
$depenGraph=$depenGraph->delete_vertex($_);
print "simplified depenGraph is:\n $depenGraph\n";
=cut
# Each pair is a pair of vertices qw|a b| indicating
# a directed edge from a to b
# graph: lineitem <-> invioce <-> claim <-> insurer
230
$g1->add_edges( qw| A B B C
C D D A|);
$g2->add_edges( qw| A B B C
C D D A
B E E F F G G H H I I F|);
$g3->add_edges( qw|A B B C
C D D A
B E E F
F G G H
H I I F
I E E C|);
$g4->add_edges( qw| v1 v5 v1 v3
v1 v2 v2 v4
v3 v2 v3 v5
v4 v3 v4 v6 v6 v5|);
$g=$depenGraph;
#$g=$g3;
my @strongConnComp=$g->strongly_connected_components;
if($debugFlag==1)
print "\nThe graph is: $g\n";
print "\n**Strongly connected components list**\n";
print "Before simplify:\n";
foreach (my $k=0; $k< @strongConnComp; $k++)
my $comp=$strongConnComp[$k];
print "Comp$k => @$comp\n";
#if($debugFlag==1)
#############################################################
####simplify the graph by deleting the one-element components
#############################################################
@strongConnComp=grep (@$_>1,@strongConnComp);
if($debugFlag==1)
print "\nAfter simplify:\n";
foreach (my $k=0; $k< @strongConnComp; $k++)
my $comp=$strongConnComp[$k];
print "Comp$k => @$comp\n";
231
#if($debugFlag==1)
=pod
print "In_degree is: ";
print $g->in_degree('A'),"\n";
print "has_a_cycle is: ";
print $g->has_a_cycle,"\n";
print "find_a_cycle is: ";
print $g->find_a_cycle,"\n";
=cut
my @edges=$g->edges;
my $i=0;
if($debugFlag==1)
print "\n**Edges List***\n";
foreach (@edges)
print "@$_\n";
#if($debugFlag==1)
my @vertices=$g->vertices;
my %breakPoint;
my $temp_g = Graph::Directed->new();
$temp_g->add_edges($g->edges);
my @ii=$temp_g->edges;
=pod
foreach (my $k=0; $k< @strongConnComp; $k++)
my $comp=$strongConnComp[$k];
########## obtain the subgraph for each strongcomponent##
my $temp_g = Graph::Directed->new();
print "\nFor Comp$k: @$comp\n";
foreach my $edge (@edges)
if((grep($_ eq @$edge[0]) @$comp) and (grep($_ eq @$edge[1])
@$comp))
#print "@$edge\n";
$temp_g->add_edges(@$edge);
print "subgraph:$temp_g\n";
###############################################
#identify break point for each component
###############################################
232
my @vertices=$temp_g->vertices;
my $breakOnlyNegLoop;
$breakOnlyNegLoop=0;
if($breakOnlyNegLoop==1)
print "\n###Nodes before deleting the nodes of negative loop:\n @vertices\n";
print "Nodes in negative Loops: \n@negLoops\n";
###### The following part is trying to get rid of the negative loop nodes
###### it enable us to break only positive loops
##*****************************************************
my %negLoops;
map($negLoops$_=1,@negLoops); # create %negLoops with elements from
@negLoops
my @verticesDiff=grep(!defined($negLoops$_),@vertices); # returns those elements of
@vertices that don't
# have a hash element in %negLoops therefore they
# do not exist in @negLoops.
print " \n###Remaining nodes after deleting the nodes of negative loop:\n @verticesDiff\n";
#@vertices=@verticesDiff;
##*******************************************************
my @currentBreakingPoint;
if(@vertices>0)
########## Try to find one arc as breaking point##
print "Try to find one arc as breaking point...\n";
foreach (@vertices)
my $c=$temp_g->copy_graph;
#print " Before deleting, the copy graph is $c\n";
$c=$c->delete_vertex($_);
# print " After deleting $_, the copy graph is $c\n";
if(/^path/)
elsif (!$c->has_a_cycle)
push @currentBreakingPoint,$_;
push @currentBreakingPoint,';';
#last;
#foreach
233
############ Try to find two arcs as breaking points##
if(@currentBreakingPoint>0)
print"All possible 1BP: @currentBreakingPoint\n";
else
print "Try to find two arcs as breaking points...\n";
foreach (my $i=0; $i < @vertices; $i++)
foreach (my $j=$i+1; $j < @vertices; $j++)
my $c=$temp_g->copy_graph;
# print " Before deleting, the copy graph is $c\n";
$c=$c->delete_vertices($vertices[$i],$vertices[$j]);
# print " After deleting $vertices[$i] and $vertices[$j], the copy graph is $c\n";
if($vertices[$i]=~/^path/ or $vertices[$j]=~/^path/)
elsif ($c->is_acyclic)
push @currentBreakingPoint, $vertices[$i];
push @currentBreakingPoint, $vertices[$j];
push @currentBreakingPoint, ';';
# last;
#foreach
if (@currentBreakingPoint>0)##after finding two breaking point, stop the foreach
print"All possible 2BP: @currentBreakingPoint\n";
last;
#foreach
# if
if(@currentBreakingPoint==0)print " **warnning** breaking points is larger than 2
for this components!\n";
else$breakPoint$k=\@currentBreakingPoint;
#if
print "\n**BreakPoints List**\n";
open( BREAK, ">./ITV/BreakPoints.txt") || die "Can't open myfile: $!";##'>' means write
only, it will clear and rewrite the file.
for (my $index=0; $index<keys %breakPoint; $index++)
$_=$index;
print "For Component$_: @$strongConnComp[$_]\n @$breakPoint$_ \n";
234
print BREAK "Component$_ @$breakPoint$_ \n";
close(BREAK);
=cut
open( MYFILE, "./loopList.txt") || die "Can't open myfile: $!";
my @loopList=<MYFILE>;
close(MYFILE);
@loopList=grep /^loop\d+/ @loopList;
if($debugFlag==1)
print @loopList;
my %loopOfComp;
my %loopList;
my %PFL;my %NFL;
my @NetInPFL;my @NetInNFL;
my %loopInSCC;
tie %loopInSCC, 'Tie::IxHash'; # make hash keys in order
foreach my $myloop (@loopList)
$_=$myloop;
if(/^(loop\d+)\s+(\w+)\s+(.*)/)
my $myloopName=$1.$2;
my $loop=$3;
my @temp=split(/\s/,$loop);
if($debugFlag==1)
print "\n$myloopName: $loop\n";
$loopList$myloopName=\@temp;
my @temp_wo_path=grep !/^path/ @temp; # only keep the net information of the
loop to simplify the calculation
if($2 eq "positive")
$PFL$myloopName=\@temp_wo_path;
push @NetInPFL,@temp_wo_path;
else
$NFL$myloopName=\@temp_wo_path;
push @NetInNFL,@temp_wo_path;
my $flag=0;
235
foreach my $loopItem (@temp)
if($debugFlag==1)
print "@strongConnComp?????????????\n";
foreach (my $j=0; $j< @strongConnComp; $j++)
my $comp=$strongConnComp[$j];
if($debugFlag==1)
print "got it $j++++++++++ @$comp\n";
print "Comp$j=> @$comp\n";
#if(grep /$loopItem/ @$comp) ## might be problematic!!!!!!! since B is
belong to [A1 path1 B1]
if(grep $_ eq $loopItem @$comp)
if($debugFlag==1)
print "since $loopItem is in Comp$j [@$comp]\n";
print "$myloopName is belong to: Comp$j\n";
$flag=1;
my $compName="SCC".$j;
$loopInSCC$myloopName="SCC".$j;
if($debugFlag==1)
print "$compName!!!!!!!!!!!!!!!!!!\n";
$loopOfComp$compName=[] if (not exists
$loopOfComp$compName);
$loopOfComp$compName=[@$loopOfComp$compName,
$myloopName];
#$loopOfComp$j=[] if (not exists $loopOfComp$j);
#$loopOfComp$j=[@$loopOfComp$j, $myloopName];
last;
#if
#foreach
last if($flag==1);
#foreach
#if
#foreach
if($debugFlag==1)
236
print "\n**loop List**\n";
foreach my $loopName (keys %loopList)
print "$loopName: @$loopList$loopName\n";
print "\n**PFL List**\n";
foreach my $loopName (keys %PFL)
print "$loopName: @$PFL$loopName\n";
#print "Nets in PFLs: @NetInPFL\n";
print "\n**NFL List**\n";
foreach my $loopName (keys %NFL)
print "$loopName: @$NFL$loopName\n";
#print "Nets in NFLs: @NetInNFL\n";
print "\n**loopOFComp List**\n";
foreach my $compName (keys %loopOfComp)
print "$compName: @$loopOfComp$compName\n";
#if($debugFlag==1)
my %loopOfComp_bak=%loopOfComp;
#############################
##Get the nets of the graph
############################
my @Nets=@NetInPFL;
push @Nets,@NetInNFL;
#print "Nets of the graph=>@Nets\n";
###remove the deplicate element in @Nets
my %seen;
$seen$_++ for @Nets;
@Nets=grep !/^path/ keys %seen;
if($debugFlag==1)
print "\n**Nets of the graph (Unique)**\nwhole=>@Nets\n";
#############################
##Get the nets of each SCC
############################
my %Nets_SCC;
my %PFL_SCC;
my %NFL_SCC;
foreach (my $k=0; $k< @strongConnComp; $k++)
237
my $comp=$strongConnComp[$k];
my @Nets=@$comp;
my %seen;
$seen$_++ for @Nets;
@Nets=grep !/^path/ keys %seen;
$Nets_SCC$k=\@Nets;
if($debugFlag==1)
print "Comp$k=>@$Nets_SCC$k\n";
my $compName="SCC".$k;
foreach (@$loopOfComp$compName)
if(/positive/)
$PFL_SCC$k=[] if (not exists $PFL_SCC$k);
$PFL_SCC$k=[@$PFL_SCC$k, $_];
else
$NFL_SCC$k=[] if (not exists $NFL_SCC$k);
$NFL_SCC$k=[@$NFL_SCC$k, $_];
if($debugFlag==1)
print "\n**PFL_SCC**\n";
if(%PFL_SCC) ##this should be added or the fowllowing print command will report error
when %PFL_SCC is empty
foreach my $compName (keys %PFL_SCC)
print "Comp$compName: @$PFL_SCC$compName\n";
print "\n**NFL_SCC**\n";
if (%NFL_SCC)##this should be added or the fowllowing print command will report error
when %NFL_SCC is empty
foreach my $compName (keys %NFL_SCC)
print "Comp$compName: @$NFL_SCC$compName\n";
#if($debugFlag==1)
####################################
238
##find FVS by brute force
####################################
tie my %SCCDimension, 'Tie::IxHash';
foreach (my $k=0; $k< @strongConnComp; $k++)
######local N/PFL for current SCC
my %PFL_local;
my %NFL_local;
foreach my $loopName (@$PFL_SCC$k)
$PFL_local$loopName=$PFL$loopName;
foreach my $loopName (@$NFL_SCC$k)
$NFL_local$loopName=$NFL$loopName;
my $comp=$strongConnComp[$k];
=pod
########## obtain the subgraph for each strongcomponent##
my $temp_g = Graph::Directed->new();
print "\nFor Comp$k: @$comp\n";
foreach my $edge (@edges)
if((grep($_ eq @$edge[0]) @$comp) and (grep($_ eq @$edge[1])
@$comp))
#print "@$edge\n";
$temp_g->add_edges(@$edge);
# print "subgraph:$temp_g\n";
=cut
print STDOUT "progress= 80\n";
###############################################
#identify break point for each component
###############################################
my @currentBreakingPoint;
my $Dim;
if(@Nets>0)
########## Try to find one arc as breaking point##
if($debugFlag==1)
print "Try to find one arc as breaking point...\n";
foreach (@Nets) # brute force and search each net in the graph
239
if(/^path/)
else
if(check_net_in_hash($_,\%PFL_local)) # if this net is contained in every
PFL_local then it's a break-point
if($debugFlag==1)
print "$_ => break-point";
print "\nfor test!!!\n";
print check_net_in_NFLs($_,\%NFL_local);
print check_net_in_hash($_,\%PFL_local);
print "\nfor test!!!\n";
if(!check_net_in_NFLs($_,\%NFL_local))# if this net is not contained in
any NFL then it break only PFL_local
if($debugFlag==1)
print " for only PFLs\n";
if( exists $potentialBreakpoints$_)
push @currentBreakingPoint,$_.'.;';# '.' means find a points that only
break PFLs and terminate the for loop
# ';' is used to seperate two BPS
#last;
else
if($debugFlag==1)
print " for both N/PFLs\n";
if( exists $potentialBreakpoints$_)
push @currentBreakingPoint,$_.';'; #';' is used to seperate two BPS
#if
#if
#if
#foreach
############ Try to find two arcs as breaking points##
if(@currentBreakingPoint>0)
if($debugFlag==1)
print"All possible 1BP: @currentBreakingPoint\n";
240
$Dim=1;
else
if($debugFlag==1)
print "*Nope!!!*\nTry to find two arcs as breaking points...\n";
foreach (my $i=0; $i < @Nets; $i++)
foreach (my $j=$i+1; $j < @Nets; $j++)
if(check_two_nets_in_hash($Nets[$i],$Nets[$j],\%PFL_local))
if($debugFlag==1)
print "$Nets[$i] $Nets[$j] => is break-points";
if(check_net_in_NFLs($Nets[$i],\%NFL_local) or
check_net_in_NFLs($Nets[$j],\%NFL_local))
if( exists $potentialBreakpoints$Nets[$i] && exists
$potentialBreakpoints$Nets[$j])
push @currentBreakingPoint, $Nets[$i];
push @currentBreakingPoint, $Nets[$j].';'; #';' is used to seperate two
BPS
if($debugFlag==1)
print " for both N/PFLs\n";
else
if( exists $potentialBreakpoints$Nets[$i] && exists
$potentialBreakpoints$Nets[$j])
push @currentBreakingPoint, $Nets[$i];
push @currentBreakingPoint, $Nets[$j].'.;'; #';' is used to seperate two
BPS
last;
if($debugFlag==1)
print " for only PFLs\n";
241
#foreach
#foreach
if (@currentBreakingPoint>0)
if($debugFlag==1)
print"All possible 2BP: @currentBreakingPoint\n";
$Dim=2;
# if
if(@currentBreakingPoint==0)
if($debugFlag==1)
print STDOUT " **warnning** breaking points is larger than 2 for this
components!\n";
push @currentBreakingPoint, "|BPS|>2".';';
push @currentBreakingPoint, "|BPS|>2".'.;';
$breakPoint$k=\@currentBreakingPoint;
else
$breakPoint$k=\@currentBreakingPoint;
$SCCDimension$k=$Dim;
#if
sub check_net_in_loop
my ($net,$loopName)=@_;
if(grep($_ eq $net) @$loopList$loopName)return 1;
elsereturn 0;
sub check_net_in_hash
242
my ($net,$hash)=@_;
my $flag=1;
foreach my $loopName (keys %$hash)
if(!check_net_in_loop($net,$loopName))$flag=0;last; # if this net is not contained
in some loops return 0 else return 1
return $flag;
sub check_net_in_NFLs
my ($net,$hash)=@_;
my $flag=0;
foreach my $loopName (keys %$hash)
if(check_net_in_loop($net,$loopName))$flag=1;last; # if this net is contained in
some loops return 1 else return 0
return $flag;
sub check_two_nets_in_hash
my ($netA,$netB,$hash)=@_;
my $flag=1;
my %temp=%$hash;
foreach my $loopName (keys %$hash)
if(check_net_in_loop($netA,$loopName))
delete $temp$loopName;
elsif(check_net_in_loop($netB,$loopName))
delete $temp$loopName;
#print keys %temp;
if(keys %temp)$flag=0;
return $flag;
if($debugFlag==1)
print "\n**BreakPoints List**\n";
243
open( BREAK, ">./BreakPoints.txt") || die "Can't open myfile: $!";##'>' means write only, it
will clear and rewrite the file.
for (my $index=0; $index<keys %breakPoint; $index++)
$_=$index;
if($debugFlag==1)
print "For SCC$_: @$strongConnComp[$_]\n=>@$breakPoint$_ \n";
print BREAK "SCC$_;@$breakPoint$_\n";
close(BREAK);
open( DIMENSION, ">./SCCDimension.txt") || die "Can't open myfile: $!";##'>' means write
only, it will clear and rewrite the file.
foreach (keys %SCCDimension)
print DIMENSION "SCC$_ $SCCDimension$_\n";
close(DIMENSION);
open( SCC, ">./SCCList.txt") || die "Can't open myfile: $!";##'>' means write only, it will
clear and rewrite the file.
for (my $index=0; $index<keys %breakPoint; $index++)
$_=$index;
print SCC "SCC$_ @$strongConnComp[$_]\n";
close(SCC);
open( loopOfComp, ">./loopOfSCC.txt") || die "Can't open myfile: $!";##'>' means write
only, it will clear and rewrite the file.
=pod
foreach my $compName (keys %loopOfComp_bak)
print loopOfComp "$compName @$loopOfComp_bak$compName\n";
=cut
foreach my $myloopName (keys %loopInSCC)
print loopOfComp "$myloopName $loopInSCC$myloopName\n";
close(loopOfComp);
244
APPENDIX B. PROGRAMS FOR IMPROVING TIME EFFICIENCY OF FAULT-
COVERAGE SIMULATION
1. creat_subSG.pl
#! /usr/bin/perl
use strict;
use warnings;
use lib './FPG16/FPG/package/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
use lib './FPG16/FPG/package/Graph-0.96/lib';
use Graph::Directed;
#=====================How to
use================================================================
==============
#
# 1. At the directory where foder "FPG16" is located, open a terminal;
# 2. Run the command "perl ./FPG16/FPG/create_subSG.pl"
#
# input file list:
# "./FPG_logfile/sg.txt"
# "./FPG_logfile/sg_#.txt"
# "./FPG_logfile/SCC_nodes.txt"
# "./FPG_logfile/SCC_instances.txt"
#
#
# output file list:
# "./FPG_logfile/.txt" contains the fault propagation graph
# "./FPG_logfile/.txt" contains the sensitivity graph
# "./FPG_logfile/SCC_subSG/sg_#_$k.txt"
# "./FPG_logfile/SCC_subSG/sg_$k.txt"
# "./FPG_logfile/SCC_subSG/sg_adj_$k.txt"
#=================================================================
============================================
##################################################################
#### retrieve the instances and nodes for each SCC**\n";
##################################################################
open( MYFILE, "./FPG_logfile/SCC_inst.txt") || die "Can't open SCC_inst.txt: $!";
my @SCC_instances=<MYFILE>;
print "\n**Instance list for each SCC**\n";
print @SCC_instances;
245
close(MYFILE);
tie my %SCC_instances, 'Tie::IxHash';
tie my %SCC_nodes, 'Tie::IxHash';
for (my $k=0; $k<@SCC_instances; $k++)
my $currentLine=$SCC_instances[$k];
chomp $currentLine;
my @temp=split(/\=\>/, $currentLine);
my $SCC_Name=$temp[0];
if(@temp>1)
$SCC_instances$SCC_Name=$temp[1];
else
$SCC_instances$SCC_Name="";
foreach my $k (keys %SCC_instances)
print "$k => $SCC_instances$k\n";
open( MYFILE, "./FPG_logfile/SCC_nodes.txt") || die "Can't open SCC_nodes.txt: $!";
my @SCC_nodes=<MYFILE>;
print "\n**Nodes list for each SCC**\n";
print @SCC_nodes;
close(MYFILE);
for (my $k=0; $k<@SCC_nodes; $k++)
my $currentLine=$SCC_nodes[$k];
chomp $currentLine;
my @temp=split(/\=\>/, $currentLine);
my $SCC_Name=$temp[0];
if(@temp>1)
$SCC_nodes$SCC_Name=$temp[1];
else
$SCC_nodes$SCC_Name="";
246
foreach my $k (keys %SCC_nodes)
print "$k => $SCC_nodes$k\n";
##################################################################
#retrive the sensitivity graph
##################################################################
open( MYFILE, "./FPG_logfile/sg.txt") || die "Can't open sg.txt: $!";
my @SG=<MYFILE>;
close(MYFILE);
=pod
print "\n**sg**\n";
print @SG;
=cut
open( MYFILE, "./FPG_logfile/sg_#.txt") || die "Can't open sg_#.txt: $!";
my @SG_num=<MYFILE>;
close(MYFILE);
=pod
print "\n**sg_#**\n";
print @SG_num;
=cut
##################################################################
#for each instance in the SCC,
#obtain the related edge in SG
##################################################################
print "**instances**\n";
tie my %SCC_subSG, 'Tie::IxHash';
foreach my $k (keys %SCC_instances)
print "$k => $SCC_instances$k\n";
my @inst=split(/\s+/,$SCC_instances$k);
#print "@inst\n";
my @SG_used=@SG;
foreach my $item (@inst)
if($item=~/^T(.*)$/)
247
#print "transistor: T$1\n";
my $j=$1;
foreach my $Line (@SG)
#chomp $Line;
if ($Line=~/\sI$j\s/)
#print "$Line!!!\n";
$SCC_subSG$k=[] if (not exists $SCC_subSG$k);
#$SCC_subSG$k=[@$SCC_subSG$k, $Line];
$SCC_subSG$k=[@$SCC_subSG$k, $Line] if
(!(grep$_ eq $Line @$SCC_subSG$k)); #avoid repeating
@SG_used=grep !/$Line/ @SG_used;
elsif($item=~/^R(.*)$/)
#print "Resistor: R$1\n";
my $j=$1;
foreach my $Line (@SG)
#chomp $Line;
if ($Line=~/\sIR$j\s/)
#print "$Line!!!\n";
$SCC_subSG$k=[] if (not exists $SCC_subSG$k);
#$SCC_subSG$k=[@$SCC_subSG$k, $Line];
$SCC_subSG$k=[@$SCC_subSG$k, $Line] if
(!(grep$_ eq $Line @$SCC_subSG$k)); #avoid repeating
@SG_used=grep !/$Line/ @SG_used;
print "$k => $SCC_nodes$k\n";
my @nodes=split(/\s+/,$SCC_nodes$k);
#print "@nodes!!!!\n";
=pod
foreach my $item (@nodes)
248
foreach my $Line (@SG_used)
#chomp $Line;
if ($Line=~/\sI(\S+)\s/)
my $temp_node=$1;
if ($temp_node eq $item)
#print "$Line!!!\n";
$SCC_subSG$k=[] if (not exists $SCC_subSG$k);
#$SCC_subSG$k=[@$SCC_subSG$k, $Line];
$SCC_subSG$k=[@$SCC_subSG$k, $Line] if
(!(grep$_ eq $Line @$SCC_subSG$k)); #avoid repeating
=cut
foreach my $Line (@SG_used)
#chomp $Line;
if ($Line=~/\sI(\S+)\s/)
my $temp_node=$1;
if((grep$_ eq $temp_node @nodes))
#print "$Line!!!\n";
$SCC_subSG$k=[] if (not exists $SCC_subSG$k);
#$SCC_subSG$k=[@$SCC_subSG$k, $Line];
$SCC_subSG$k=[@$SCC_subSG$k, $Line] if
(!(grep$_ eq $Line @$SCC_subSG$k)); #avoid repeating
#my $tt1=@SG;
#my $tt2=@SG_used;
#print "$tt1,$tt2!!!!!!!!!!!!!!!!!!!!!!!!\n";
=pod
249
##################################################################
#for each node in the SCC,
#obtain the related edge in SG
##################################################################
print "**nodes**\n";
foreach my $k (keys %SCC_nodes)
print "$k => $SCC_nodes$k\n";
my @nodes=split(/\s+/,$SCC_nodes$k);
#print "@nodes!!!!\n";
my @inst=split(/\s+/,$SCC_instances$k);
foreach my $item (@nodes)
foreach my $Line (@SG)
#chomp $Line;
if ($Line=~/\s(I$item)\s/)
#print "$Line!!!\n";
$SCC_subSG$k=[] if (not exists $SCC_subSG$k);
#$SCC_subSG$k=[@$SCC_subSG$k, $Line];
$SCC_subSG$k=[@$SCC_subSG$k, $Line] if
(!(grep$_ eq $Line @$SCC_subSG$k)); #avoid repeating
if ($Line=~/\s$item\s/)
print "!!!!$item-->$Line\n";
if ($Line=~/\sI(\S+)\s/)
my $temp_node=$1;
my $temp_inst='T'.$temp_node;
"#############################$item==>$temp_node=>$Line\n";
if((grep$_ eq $temp_node @nodes))
print "\t$Line is in this
SCC********************";
if((grep$_ eq $temp_inst @inst))
print "\t$Line **is in this
SCC********************";
250
$SCC_subSG$k=[] if (not exists $SCC_subSG$k);
#$SCC_subSG$k=[@$SCC_subSG$k, $Line];
$SCC_subSG$k=[@$SCC_subSG$k, $Line] if
(!(grep$_ eq $Line @$SCC_subSG$k)); #avoid repeating
=cut
print "\n**subSG for each SCC**\n";
if (! -d './FPG_logfile/SCC_subSG')
system('mkdir -p ./FPG_logfile/SCC_subSG')
else
system('rm -r ./FPG_logfile/SCC_subSG/*');
foreach my $k (keys %SCC_subSG)
print "$k\t => $SCC_instances$k\n";
print "\t => $SCC_nodes$k\n";
print "@$SCC_subSG$k\n";
#system("mkdir SCC_subSG");
open( MYFILE, ">./FPG_logfile/SCC_subSG/sg_#_$k.txt") || die "Can't open
sg_#_$k.txt: $!";
open( MYFILE1, ">./FPG_logfile/SCC_subSG/sg_$k.txt") || die "Can't open
sg_$k.txt: $!";
my $count=0;
my @node;
my %SG_w;
foreach my $edge (@$SCC_subSG$k)
my @temp=split(/\s+/, $edge);
print MYFILE1 " \t$temp[1]\t$temp[2]\t$temp[3]\n";
#print "@temp\n";
my $num=$temp[0];
my @temp1=split(/\s+/, $SG_num[$num-1]);
#print "@temp1\n";
$count++;
print MYFILE $count;
print MYFILE " \t$temp1[1]\t$temp1[2]\t$temp1[3]\n";
251
push @node,$temp[1] if (!(grep$_ eq $temp[1] @node));
push @node,$temp[2] if (!(grep$_ eq $temp[1] @node));
$SG_w$temp[1].$temp[2]=$temp[3];
#print "\t@node\n";
=pod
open( MYFILE2, ">./FPG_logfile/SCC_subSG/sg_adj_$k.txt") || die "Can't open
sg_adj_$k.txt: $!";
for (my $i=0;$i<@node;$i++)
print "\t\t$node[$i]";
print MYFILE2 "\t\t$node[$i]";
print "\n";
for (my $i=0;$i<@node;$i++)
print "$node[$i]";
print MYFILE2 "$node[$i]";
for (my $j=0;$j<@node;$j++)
if(exists $SG_w$node[$i].$node[$j])
print "\t\t$SG_w$node[$i].$node[$j]";
print MYFILE2 "\t\t$SG_w$node[$i].$node[$j]";
else
print "\t\t0";
print MYFILE2 "\t\t0";
print "\n";
print MYFILE2 "\n";
close(MYFILE2);
=cut
print "\n";
close(MYFILE);
close(MYFILE1);
2. createFPG.pl
#! /usr/bin/perl
use strict;
252
use warnings;
use lib './FPG16/FPG/package/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
use lib './FPG16/FPG/package/Graph-0.96/lib';
use Graph::Directed;
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#This need to take care
my @input_pin;
push @input_pin, "vin";
push @input_pin, "vip";
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#=====================How to
use================================================================
==============
#
# 1. At the directory where foder "FPG16" is located, open a terminal;
# 2. Run the command "perl ./FPG16/FPG/createFPG.pl"
#
# input file list:
# "./FPG16/FPG/flattenNetlist.pl" Reqired script @dir ./FPG16/FPG/
#
# "./FPG16/FPG/findSCC.pl" Reqired script @dir ./FPG16/FPG/ to find SCC for
fpg.txt
# "./FPG_logfile/op.auto" Reqired file @dir ./FPG16/FPG/ which contains the
DC operating points of gm, gmb, gds, R
# output file list:
# "./FPG_logfile/fpg.txt" contains the fault propagation graph
# "./FPG_logfile/sg.txt" contains the sensitivity graph
# "./FPG_logfile/sg_#.txt" contains the sensitivity graph in number
# "./FPG_logfile/nodes.txt" contains the node list of the sensitivity graph
# "./FPG_logfile/nodes2num.txt" contains the node list of the sensitivity graph in
numbers
# "./FPG_logfile/nodes_impedance.txt" contains the node impedances
my $start_time=time();
my $start_time2=localtime();
##################################################################
#determine wether to print out information
my $debugFlag=1;
253
if($debugFlag==1)
print "start at:$start_time2\n";
=pod
$cellName="widlar";
$fileName=$cellName."_hier.netlist";
=cut
##################################################################
####flatten the netlist generated from cadence [optional]
##################################################################
system("perl ./FPG16/FPG/flattenNetlist.pl -d 1 >./FPG_logfile/flattenNetlist.log");
##################################################################
#### retrieve the netlist
##################################################################
open( MYFILE, "./FPG_logfile/flattenNetlist.txt") || die "Can't open flattenNetlist.txt: $!";
my @netlist_from_cadence=<MYFILE>;
if($debugFlag==1)
print @netlist_from_cadence;
close(MYFILE);
####store the useful information in a hash
#=================================================
# this is used to include the terminal line <==/^\(/
my @netlist_usf=grep /^\w+\d/ || /^\(/, @netlist_from_cadence;
#=================================================
##################################################################
#fowlloing code is to get the cell name
##################################################################
my @cellName=grep /\/\/Cell/, @netlist_from_cadence;
print "@cellName\n";
my $cellName;
foreach (@cellName)
if (/\"(.*)\"/)
$cellName=$1;
print "cell name==>$cellName\n";
##################################################################
#fowlloing code is to get the power
#supply node from the form
##################################################################
my @myPowerSupply=grep /^MyV/, @netlist_from_cadence;
if($debugFlag==1)
254
print @myPowerSupply;
my $myVdd;
my $myVss;
my $path_begin='vdd!'; #set default value
my $path_end='gnd!'; #set default value
my %path_begin;
my %path_end;
$path_begin'vdd!'=1; #set default value
$path_end'gnd!'=1; #set default value
foreach (@myPowerSupply)
if(/^MyVdd\:\s\"(.*)\"/)
$myVdd=$1;
map($path_begin$_=1,split(/ /,$1));
elsif(/^MyVss\:\s\"(.*)\"/)
$myVss=$1;
map($path_end$_=1,split(/ /,$1));
if(defined $myVdd)
$path_begin=$myVdd;
#delete $path_begin'vdd!';
if(defined $myVss)
$path_end=$myVss;
#delete $path_end'gnd!';
print "$path_begin, $path_end,!!!!!!!!!!!!!!!!!!!!!!\n";
##################################################################
#fowlloing code is to get the netlist
#################################################################
if($debugFlag==1)
print "\n**processing the netlist**\n";
#print "netlist_usf:", @netlist_usf;
tie my %instance_hash, 'Tie::IxHash';
tie my %netlist_usf, 'Tie::IxHash';
tie my %instance_prop, 'Tie::IxHash';# model name of a device, like 'nfet', 'res', 'cap'
255
tie my %instance_terminal, 'Tie::IxHash';# teminal name of a device, like 'D', 'S', 'B'
tie my %FPG_depen, 'Tie::IxHash';
tie my %FPG_depen1, 'Tie::IxHash';
my $FPG_Count;
$FPG_Count=0;
for (my $i=0;$i<@netlist_usf;$i++)
$_=$netlist_usf[$i];
if(/^(\w+\d+)\s+\(\"(.*)\"\)\s+(\w+)\s/)
$instance_hash$1=[split(/\" \"/,$2)];
if($debugFlag==1)
print "$1 => @$instance_hash$1 \n";
$instance_prop$1=$3;
#=========================================================
#########store the terminal infor.
my $instName=$1;
my $nextLine=$netlist_usf[$i+1];
if($nextLine=~/^\(\"(.*)\"\)/) #this considering ("D" "B" "G" "S")
$instance_terminal$instName=[split(/\" \"/,$1)];
if($nextLine=~/^\(\'(.*)\'\)/)#this considering ('D' 'B' 'G' 'S')
$instance_terminal$instName=[split(/\' \'/,$1)];
#=========================================================
elsif(/^(\w+\d+.*)\s+\(\"(.*)\"\)\s+(\w+)\s/) ##this considering we have hierachical
instances which are named like "I0.I1.N4"
$instance_hash$1=[split(/\" \"/,$2)];
if($debugFlag==1)
print "Got it!!!$1 => @$instance_hash$1 \n";
$instance_prop$1=$3;
#=========================================================
#########store the terminal infor.
my $instName=$1;
my $nextLine=$netlist_usf[$i+1];
if($nextLine=~/^\(\"(.*)\"\)/)#this considering ("D" "B" "G" "S
256
$instance_terminal$instName=[split(/\" \"/,$1)];
if($nextLine=~/^\(\'(.*)\'\)/)#this considering ('D' 'B' 'G' 'S')
$instance_terminal$instName=[split(/\' \'/,$1)];
#=========================================================
###########################################################################
###
#find the channel of each instance
#diode connection transistor
#gate of non-diode connection tansistor
###########################################################################
###
tie my %graph, 'Tie::IxHash';
my %gate;
my %gate_net;
my %D;
my %S;
tie my %DirectedDepen, 'Tie::IxHash';
for my $instance (keys %instance_hash)
$_=$instance;
if($debugFlag==1)
print "$instance:";
my $prop=$instance_prop$instance;
if($debugFlag==1)
print "$prop";
my @terminal=@$instance_terminal$instance;
if($debugFlag==1)
print "(@terminal)";
if($prop=~/^pmos|^pfet|^nmos|^nfet/)
if($debugFlag==1)
257
print " is COMS!!";
elsif($prop=~/pnp|npn/)
if($debugFlag==1)
print " is BJT!!";
if($debugFlag==1)
print "\n";
#if(/P|N|M\d+/)
if($prop=~/^pmos|^pfet|^nmos|^nfet/) #means this is a coms transistor
#determine the channel of transistor
my $net=$instance_hash$instance;
#=================================================================
===========
my $D;
my $S;
my $B;
my $G;
for(my $i=0;$i<@terminal;$i++)
if($terminal[$i]=~/G/)$G=$net->[$i];
elsif($terminal[$i]=~/S/)$S=$net->[$i];
elsif($terminal[$i]=~/D/)$D=$net->[$i];
elsif($terminal[$i]=~/B/)$B=$net->[$i];
$S$instance=$S;
$D$instance=$D;
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
$gate$instance=$G;
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
# print "D=>$D S=>$S\n";
$graph$instance=[$D,$S];
#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFF
my $I='I_'.$instance;
if(not exists $FPG_depen1$G.$I)
258
$FPG_depen1$G.$I=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[$G, $I];
if(not exists $path_begin$D and ($D ne $path_end))
if(not exists $FPG_depen1$I.$D)
$FPG_depen1$I.$D=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[$I, $D];
if(not exists $FPG_depen1$D.$I)
$FPG_depen1$D.$I=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[$D, $I];
if(not exists $path_begin$S and ($S ne $path_end))
if(not exists $FPG_depen1$S.$I)
$FPG_depen1$S.$I=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[$S, $I];
if(not exists $FPG_depen1$I.$S)
$FPG_depen1$I.$S=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[$I, $S];
#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFF
#if(
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if($D eq $S)
if($D eq $B)
259
if($debugFlag==1)
print "since D=S=B It's a varactor (variable capacitor)!!!!!!!!\n";
delete $graph$instance;
$instance_prop$_="varactor";
else
if($debugFlag==1)
print " It's a diode!!!!!!!!\n";
delete $graph$instance;
$instance_prop$_="diode";
$graph$_=[$D,$B];
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
elsif (($D ne $G) and ($G ne $S))#not diode connected
if(($D eq $S) and ($D eq $B))# vorator ###diode transistor or
if($debugFlag==1)
print " It's a varactor (variable capacitor)!!!!!!!!\n";
delete $graph$instance;
else
$gate$instance=$G;
$gate_net$G=[] if (not exists $gate_net$G);
$gate_net$G=[@$gate_net$G, $instance];
else
#search for diode connection and change the name
$_=$instance;
s/P/PD/;
s/N/ND/;
s/M/MD/;
s/T/TD/;
$graph$_=delete $graph$instance;
if($debugFlag==1)
260
print $instance, " is diode connection => $_\n";
#=================================================================
=============
elsif($prop=~/res/) #means this is a resistor
my $net=$instance_hash$instance;
#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFF
my $I='I_'.$instance;
if(not exists $path_begin@$net[0] and (@$net[0] ne $path_end))
if(not exists $FPG_depen1$I.@$net[0])
$FPG_depen1$I.@$net[0]=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[$I, @$net[0]];
if(not exists $FPG_depen1@$net[0].$I)
$FPG_depen1@$net[0].$I=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[@$net[0], $I];
if(not exists $path_begin@$net[1] and (@$net[1] ne $path_end))
if(not exists $FPG_depen1@$net[1].$I)
$FPG_depen1@$net[1].$I=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[@$net[1], $I];
if(not exists $FPG_depen1$I.@$net[1])
$FPG_depen1$I.@$net[1]=1;
$FPG_Count=$FPG_Count+1;
$FPG_depen'DD'.$FPG_Count=[$I, @$net[1]];
261
#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFF
elsif($prop=~/cap/) #means this is a capacitor
delete $graph$instance;
elsif(/^I\d+/)
if($debugFlag==1)
print "$_ is: $instance_prop$_\n";
if($instance_prop$_=~/^idc/)$graph$instance=$instance_hash$instance;
#it's not an independent current source
elsif($prop=~/pnp|npn/)
#determine the channel of BJT
my $net=$instance_hash$instance;
$graph$instance=[$net->[0],$net->[2]]; #(0 1 2)==>(C B E)
#determine the Base of BJT
if (($net->[0] ne $net->[1]) and ($net->[2] ne $net->[1]))#not diode connected
my $base_channel=$instance.'_BE';
$graph$base_channel=[$net->[1],$net->[2]];
$gate$instance=$net->[1];
$gate_net$net->[1]=[] if (not exists $gate_net$net->[1]);
$gate_net$net->[1]=[@$gate_net$net->[1], $instance];
else
#search for diode connection and change the name
$_=$instance;
s/Q/QD/;
$graph$_=delete $graph$instance;
if($debugFlag==1)
print $instance, " is diode connection $prop => $_\n";
262
else
$graph$instance=$instance_hash$instance;
#FFFFFFFFFFFFFFFFFFFFFFFFFFFFF
open( MYDEPEN1, ">./FPG_logfile/fpg.txt") || die "Can't open fpg.txt: $!";##'>' means write
only, it will clear and rewrite the file.
if($debugFlag==1)
print "\n**FPG_depen list**\n";
foreach my $item (keys %FPG_depen)
print "$item: @$FPG_depen$item[0] => @$FPG_depen$item[1]\n";
print MYDEPEN1 "@$FPG_depen$item[0] @$FPG_depen$item[1]\n";
close(MYDEPEN1);
#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
#############################################################
# find SCC
system("perl ./FPG16/FPG/findSCC.pl -d $debugFlag");
#############################################################
#############################################################
#### read gm gds from a file
#############################################################
#open( MYFILE, "./$cellName.op") || die "Can't open $cellName.op: $!";
open( MYFILE, "./FPG_logfile/op.auto") || die "Can't open op.auto: $!";
my @op= ('Tie::Array');
@op=<MYFILE>;
close(MYFILE);
#print @op;
#############################################################
#### otain op
#############################################################
tie my %op, 'Tie::IxHash';
263
foreach (@op)
my @IN=split(/\s+/,$_);
$op$IN[0]=$IN[1];
print "\n**Now creating sensitivity graph:**\n";
print "**OP is:**\n";
foreach my $depen (keys %op)
print "$depen=>$op$depen\n";
print "\n\n**step 1**\n";
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
#1. Extract all the “nets” as voltage nodes;
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
my @Net_vec;
my %net_instance;
foreach my $inst (keys %instance_hash)
=pod
print "$inst=>@$instance_hash$inst\n";
my $prop=$instance_prop$inst;
if($debugFlag==1)
print "$prop";
my @terminal=@$instance_terminal$inst;
if($debugFlag==1)
print "(@terminal)";
if($prop=~/^pmos|^pfet|^nmos|^nfet/)
print " is COMS!!";
=cut
foreach my $net(@$instance_hash$inst)
# print "$net\n";
if(($net ne $path_begin) && ($net ne $path_end) && ($net ne 'gnd!') &&
!(grep$_ eq $net @Net_vec)) #(exclude VDD VSS)
if(!grep(/^$net$/, @input_pin))
264
push @Net_vec, $net;
if(($net ne $path_begin) && ($net ne $path_end) && ($net ne 'gnd!') ) #(exclude
VDD VSS)
$net_instance$net=[] if (not exists $net_instance$net);
$net_instance$net=[@$net_instance$net, $inst] if (!(grep$_ eq $inst
@$net_instance$net)); #avoid repeating
print "\n**Nets of the circuit, (exclude VDD VSS)**\n";
print "=>@Net_vec\n";
print "\n**Incident device of a net **\n";
for my $_(keys %net_instance)
print "$_==> @$net_instance$_\n";
print "\n\n**step 2**\n";
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
#2. Each voltage node has current node (inject current) to generate it with a gain of Z
(except input voltage nodes, e.g. VA, VB, Vbias);
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
my $sensGraph = Graph::Directed->new();
tie my %SFG, 'Tie::IxHash';
tie my %SFG_w, 'Tie::IxHash';
my %node_impedance;
foreach my $net (@Net_vec)
my @edges=['I'.$net, $net];
$sensGraph->add_edges(@edges);
my $name='I'.$net.'->'.$net;
$SFG$name=['I'.$net, $net];
$SFG_w$name=1;
#####find impedance
265
my $z=0;
my $nonsource_flag=0; #mean it is not an node that only connect to idea voltage
source
print "\n**For net $net: ";
print "incident instance==>@$net_instance$net**\n";
foreach my $inst(@$net_instance$net)
my $prop=$instance_prop$inst;
my $i;
if($inst=~/^\w(\d+)/)
$i=$1;
if($prop=~/^pmos|^pfet|^nmos|^nfet/)
print "=>$inst\[COMS\]: ";
print "G:$gate$inst\t";
print "D:$D$inst\t";
print "S:$S$inst\n";
if ($net eq $D$inst)
print "gds_$inst = $op'gds_'.$inst is added\n";
$nonsource_flag=1;
$z=$z+$op'gds_'.$inst;
if ($net eq $gate$inst)
print "gm_$inst = $op'gm_'.$inst is added\n";
$z=$z+$op'gm_'.$inst;
elsif ($net eq $S$inst)
print "gds_$inst = $op'gds_'.$inst and gm_$inst = $op'gm_'.$inst
are added\n";
$nonsource_flag=1;
$z=$z+$op'gds_'.$inst+$op'gm_'.$inst;
266
if($prop=~/^res/)
print "=>$inst\[RES\]: ";
print "1/$inst=$op$inst is added\n";
$nonsource_flag=1;
$z=$z+$op$inst;
if($prop=~/^vdc/ or $prop=~/^vdc/)
print "=>$inst\[vdc/idc\]: ";
print "$inst is a source\n";
if($nonsource_flag)
$SFG_w$name=1/$z;
print "z_$net: $name==>$SFG_w$name!!!\n";
$node_impedance$net=1/$z;
print "\n\n**step 3**\n";
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
#3 For each MOS, include a branch: Vgate Idrain with gain of –gm
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
foreach my $inst (keys %graph)
if (exists $instance_hash$inst)
print "$inst=>@$instance_hash$inst\n";
my $prop;
if (exists $instance_prop$inst)
$prop=$instance_prop$inst ;
if($prop=~/^pmos|^pfet|^nmos|^nfet/)
print "=>$inst\[COMS\]: !!!!!!!!!!!!!!";
print "G:$gate$inst\t";
267
print "D:$D$inst\t";
print "S:$S$inst\n";
if(($D$inst ne $path_begin) and ($D$inst ne $path_end) )
my $i;
if($inst=~/^\w(\d+)/)
$i=$1;
# add edge: Vgate-->Idrain
my @edges=[$gate$inst,'I'.$D$inst];
$sensGraph->add_edges(@edges);
my $name=$gate$inst.'->I'.$D$inst;
print "$name==>";
$SFG$name=[$gate$inst,'I'.$D$inst];
$SFG_w$name=0-$op'gm_'.$inst;;
print "$SFG_w$name\n";
print "\n\n**step 4**\n";
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
# 4. For MOS whose sources are not vdd/gnd,
# includes a branch: Vgate Isource with gain of gm
# includes a branch: Vsource Idrain with gain of gm+gmb+gds
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
print "$path_begin!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
foreach my $inst (keys %graph)
print "$inst############################\n";
if (exists $instance_hash$inst)
print "$inst=>@$instance_hash$inst\n";
my $prop;
if (exists $instance_prop$inst)
268
$prop=$instance_prop$inst ;
print "@@@@@@@@@@@@@@@@@@@\n";
if($prop=~/^pmos|^pfet|^nmos|^nfet/)
print "=>$inst\[COMS\]: ";
print "G:$gate$inst\t";
print "D:$D$inst\t";
print "S:$S$inst\n";
if(($S$inst ne $path_begin) and ($S$inst ne $path_end) )
my $i;
if($inst=~/^\w(\d+)/)
$i=$1;
# add edge: Vgate-->Isource
my @edges=[$gate$inst,'I'.$S$inst];
$sensGraph->add_edges(@edges);
my $name=$gate$inst.'->I'.$S$inst;
print "$name==>";
$SFG$name=[$gate$inst,'I'.$S$inst];
$SFG_w$name=$op'gm_'.$inst;
print "$SFG_w$name\n";
# add edge: Vsource-->Idrain
if(($D$inst ne $path_begin) and ($D$inst ne $path_end) )
@edges=[$S$inst,'I'.$D$inst];
$sensGraph->add_edges(@edges);
$name=$S$inst.'->I'.$D$inst;
print "$name==>";
$SFG$name=[$S$inst,'I'.$D$inst];
$SFG_w$name=$op'gm_'.$inst+$op'gmb_'.$inst+$op'gds_'.$inst;
print "$SFG_w$name\n";
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
269
# for dioded connected MOS and whose sources are not vdd/gnd,
# includes a branch: Vgate Isource with gain of gm
# includes a branch: Vsource Idrain with gain of gm+gmb+gds
elsif ($inst=~/^PD/ or $inst=~/^ND/ or $inst=~/^MD/ or $inst=~/^TD/ )
print "diode conncted
transistor%%%%%%%%%%%%%%%%%%%%%%%\n";
print "=>$inst\[Diode Conncted COMS\]: ";
$_=$inst;
s/PD/P/;
s/ND/N/;
s/MD/M/;
s/TD/T/;
$inst=$_;
print "G:$gate$inst\t";
print "D:$D$inst\t";
print "S:$S$inst\n";
if(($S$inst ne $path_begin) and ($S$inst ne $path_end) )
my $i;
if($inst=~/^\w(\d+)/)
$i=$1;
# add edge: Vgate-->Isource
my @edges=[$gate$inst,'I'.$S$inst];
$sensGraph->add_edges(@edges);
my $name=$gate$inst.'->I'.$S$inst;
print "\tweight is: gm_$inst = $op'gm_'.$inst \n";
print "$name==>";
$SFG$name=[$gate$inst,'I'.$S$inst];
$SFG_w$name=$op'gm_'.$inst;
print "$SFG_w$name\n";
# add edge: Vsource-->Idrain
if(($D$inst ne $path_begin) and ($D$inst ne $path_end) )
@edges=[$S$inst,'I'.$D$inst];
$sensGraph->add_edges(@edges);
270
$name=$S$inst.'->I'.$D$inst;
print "\tweight is: gm_$inst = $op'gm_'.$inst, gmb_$inst =
$op'gmb_'.$inst and gds_$inst = $op'gds_'.$inst\n";
print "$name==>";
$SFG$name=[$S$inst,'I'.$D$inst];
$SFG_w$name=$op'gm_'.$inst+$op'gmb_'.$inst+$op'gds_'.$inst;
print "$SFG_w$name\n";
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSS
print "\n\n**step 5**\n";
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
# 5. Form the physical current variables
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
foreach my $inst (keys %instance_hash)
print "$inst=>@$instance_hash$inst\n";
my $prop=$instance_prop$inst;
my $i;
if($inst=~/^\w(\d+)/)
$i=$1;
if($prop=~/^pmos|^pfet|^nmos|^nfet/)
print "=>$inst\[COMS\]: ";
print "G:$gate$inst\t";
print "D:$D$inst\t";
print "S:$S$inst\n";
if(($S$inst ne $path_begin) and ($S$inst ne $path_end) )
# add edge: Vsource-->I_ins
271
my @edges=[$S$inst,'I'.$i];
$sensGraph->add_edges(@edges);
my $name=$S$inst.'->I'.$i;
print "$name==>";
$SFG$name=[$S$inst,'I'.$i];
$SFG_w$name=$op'gds_'.$inst;
print "$SFG_w$name\n";
if($gate$inst eq $D$inst )
# add edge: Vg,Vs-->I_ins
my @edges=[$gate$inst,'I'.$i];
$sensGraph->add_edges(@edges);
my $name=$gate$inst.'->I'.$i;
print "$name==>";
$SFG$name=[$gate$inst,'I'.$i];
$SFG_w$name=$op'gds_'.$inst+$op'gm_'.$inst;
print "$SFG_w$name\n";
else
# add edge: Vg-->I_ins
my @edges=[$gate$inst,'I'.$i];
$sensGraph->add_edges(@edges);
my $name=$gate$inst.'->I'.$i;
print "$name==>";
$SFG$name=[$gate$inst,'I'.$i];
$SFG_w$name=$op'gm_'.$inst;
print "$SFG_w$name\n";
# add edge: VD-->I_ins
if(($D$inst ne $path_begin) and ($D$inst ne $path_end) )
@edges=[$D$inst,'I'.$i];
$sensGraph->add_edges(@edges);
$name=$D$inst.'->I'.$i;
print "$name==>";
$SFG$name=[$D$inst,'I'.$i];
$SFG_w$name=$op'gds_'.$inst;
print "$SFG_w$name\n";
272
if($prop=~/^res/)
print "=>$inst\[RES\]: @$instance_hash$inst\n";
foreach my $term(@$instance_hash$inst)
print "$term!!!!!!\n";
if ( ($term ne $path_begin) and ($term ne $path_end))
# add edge: Vres-->I_ins
my @edges=[$term,'IR'.$i];
$sensGraph->add_edges(@edges);
my $name=$term.'->IR'.$i;
print "$name==>";
$SFG$name=[$term,'IR'.$i];
$SFG_w$name=$op$inst;
print "$SFG_w$name\n";
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
# print sensitivity graph to a file
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
open( MYSFG, ">./FPG_logfile/sg.txt") || die "Can't open sg.txt: $!";##'>' means write only,
it will clear and rewrite the file.
print "\n**SFG list**\n";
my $count=0;
my @Nodes;
my %Nodes2num;
my $N=1;
foreach my $item (keys %SFG_w)
$count++;
my @item=split(/->/,$item);
print $count;
print " \t$item[0]\t$item[1]\t";
print "$SFG_w$item\n";
print MYSFG $count;
print MYSFG " \t$item[0]\t$item[1]\t";
273
print MYSFG "$SFG_w$item\n";
####get the nodes
if(!(grep$_ eq $item[0] @Nodes))
push @Nodes,$item[0];
$Nodes2num$item[0]=$N;
$N++;
if(!(grep$_ eq $item[1] @Nodes))
push @Nodes,$item[1];
$Nodes2num$item[1]=$N;
$N++;
close(MYSFG);
open( MYSFG_NUM, ">./FPG_logfile/sg_#.txt") || die "Can't open sg_#.txt: $!";##'>' means
write only, it will clear and rewrite the file.
$count=0;
foreach my $item (keys %SFG_w)
$count++;
my @item=split(/->/,$item);
print MYSFG_NUM $count;
print MYSFG_NUM " \t$Nodes2num$item[0]\t$Nodes2num$item[1]\t";
print MYSFG_NUM "$SFG_w$item\n";
close(MYSFG_NUM);
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
# print nodes of sensitivity graph to a file
#SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
SSSSSSSS
open( MYFILE, ">./FPG_logfile/nodes.txt") || die "Can't open nodes.txt: $!";
#print "\n**Nodes list**\n";
foreach my $node (@Nodes)
#print "$node\n";
print MYFILE "$node\n";
print "\n";
close(MYFILE);
274
open( MYFILE, ">./FPG_logfile/nodes2num.txt") || die "Can't open nodes2num.txt: $!";
#print "\n**Nodes list**\n";
foreach my $node (@Nodes)
#print "$node\n";
print MYFILE "$node\t$Nodes2num$node\n";
print "\n";
close(MYFILE);
open( MYFILE, ">./FPG_logfile/nodes_impedance.txt") || die "Can't open
nodes_impedance.txt: $!";
#print "\n**Nodes list**\n";
foreach my $net (keys %node_impedance)
#print "$net=>$node_impedance$net\n";
print MYFILE "$net\t$node_impedance$net\n";
print "\n";
close(MYFILE);
print STDOUT "FINISHED\n";
3.findPath.pl
#! /usr/bin/perl
use constant LAST => -1;
use constant PATH => 0;
use constant SEEN => 1;
use strict;
use warnings;
sub find_paths
my ($beg, $end, $graph) = @_;# $graph is the ref of %graph
my @solution;
my @work;
for (@$graph->$beg) # $graph->$beg is the ref of key "$beg"
# push @solution, [$beg, $end] if $_ eq $end;
if ($_ eq $end)
push @solution, [$beg, $end];
next;
push @work, [[$beg, $_], $beg => undef, $_ => undef];
275
#the hash with undef is to check whether the node hasbeen visited
while (@work)
my $item = pop @work;
my ($path, $seen) = @$item[PATH, SEEN];
for my $node (@$graph->$path->[LAST])
next if exists $seen->$node;
my @new_path = (@$path, $node);
if ($node eq $end)
push @solution, \@new_path;
next;
my %new_seen = (%$seen, $node => undef);
push @work, [\@new_path, \%new_seen];
return \@solution;
1;
4. obtainOP.ocn
#! /bin/sh -exec awd -ocean "$@"
simulator( 'spectre )
design( "/tmp/zqliu216/simulation/Example/spectre/schematic_no_para/netlist/netlist")
resultsDir( "/tmp/zqliu216/simulation/Example/spectre/schematic_no_para" )
path( "/remote/rs/vlsi/ibm8rfcmos/IBM_PDK/cmrf8sf/relDM/Spectre/models" )
modelFile(
'("/remote/cadencelib/nda/ibm8rfcmos/IBM_PDK/cmrf8sf/relDM/Spectre/models/allModels.
scs" "tt")
'("/remote/cadencelib/nda/ibm8rfcmos/IBM_PDK/cmrf8sf/relDM/Spectre/models/design.scs
" "")
)
analysis('dc ?saveOppoint t )
envOption(
'analysisOrder list("dc" "stb")
)
option( 'temp "27.0"
)
temp( 27.0 )
run()
plot( VDC("/vout") )
plot( OP("/T31" "gm") )
plot( OP("/T30" "gm") )
276
;##########################################################################
############
;Above this line is ocean code for DC simulation to simulating the DC operating points
;obtain this part by using ADE_L with "save ocean script"
;##########################################################################
############
;=====================How to
use=========================================================
;
; 1. Open virtuoso;
; 2. set up a DC simulation for target circuit using ADE_L, then "save ocean script" and
replace the following highlighted part
; 3.
; a) At virtuoso CIW, tun following command:
;
load("/home/zqliu216/DM_template61/AnaFault_201609/FPG16/FPG/obtainOP.ocn"
)
; b) in linux terminal, run the command: system("ocean -restore ./FPG16/FPG/obtainOP.ocn
logfile_obtainOP.txt");
;
; input file list: none
; output file list:
; "./FPG_logfile/op.auto" contains the operating points of the netlist
;==================================================================
======================
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;obtain the instance list that we need to print the DC operating points
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstTable=makeTable("InstTable" nil) ;store the dimension for each SCC
let( (inport nextLine Iterm InstName)
inport=infile("/home/zqliu216/DM_template61/AnaFault_201609/FPG_logfile/inst_list.txt")
when(inport
while(gets(nextLine inport)
println(nextLine)
Iterm=parseString(nextLine)
InstName =car(Iterm)
InstTable[InstName]=append1(InstTable[InstName] cadr(Iterm))
277
);while
close(inport)
);when
);let
printf("\n**Instance Table**\n")
foreach(InstName InstTable
printf("%s=>%L\n" InstName InstTable[InstName])
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;obtain the DC operating points
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printf("\n**DC operating points**\n")
out=outfile("/home/zqliu216/DM_template61/AnaFault_201609/FPG_logfile/op.auto" "w")
foreach(InstName InstTable
printf("%s=>%L" InstName InstTable[InstName])
cellName=car(InstTable[InstName])
if(cellName=="pmos4" ||cellName=="pfet"|| cellName=="nfet"||cellName=="nmos4" ||
cellName=="pfet33"|| cellName=="nfet33"
then
println(" is a mosfet")
gm=OP(InstName "gm")
gmb=OP(InstName "gmbs")
gds=OP(InstName "gds")
printf("gm_%s\t %1.4e\n" InstName , gm)
if(gmb!=nil then
printf("gmb_%s\t %1.4e\n" InstName , gmb)
); End if
printf("gds_%s\t %1.4e\n" InstName , gds)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;print to file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
fprintf(out "gm_%s\t %1.4e\n" InstName , gm)
if(gmb!=nil then
fprintf(out "gmb_%s\t %1.4e\n" InstName , gmb)
); End if
fprintf(out "gds_%s\t %1.4e\n" InstName , gds)
);if
if(cellName=="res"
then
println("is a res")
278
res=1/OP(InstName "res")
printf("%s\t %1.4e\n" InstName , res)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;print to file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
fprintf(out "%s\t %1.4e\n" InstName , res)
); End if
); end for
close(out)
exit()
5. obtainOP_partII.ocn
;##########################################################################
############
;Above this line is ocean code for DC simulation to simulating the DC operating points
;obtain this part by using ADE_L with "save ocean script"
;##########################################################################
############
;=====================How to
use=========================================================
;
; 1. Open virtuoso;
; 2. set up a DC simulation for target circuit using ADE_L, then "save ocean script" and
replace the following highlighted part
; 3.
; a) At virtuoso CIW, tun following command:
;
load("/home/zqliu216/DM_template61/AnaFault_201609/FPG16/FPG/obtainOP.ocn"
)
; b) in linux terminal, run the command: system("ocean -restore ./FPG16/FPG/obtainOP.ocn
logfile_obtainOP.txt");
;
; input file list: none
; output file list:
; "./FPG_logfile/op.auto" contains the operating points of the netlist
;==================================================================
======================
279
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;obtain the instance list that we need to print the DC operating points
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstTable=makeTable("InstTable" nil) ;store the dimension for each SCC
let( (inport nextLine Iterm InstName)
inport=infile("/home/zqliu216/DM_template61/AnaFault_201609/FPG_logfile/inst_list.txt")
when(inport
while(gets(nextLine inport)
println(nextLine)
Iterm=parseString(nextLine)
InstName =car(Iterm)
InstTable[InstName]=append1(InstTable[InstName] cadr(Iterm))
);while
close(inport)
);when
);let
printf("\n**Instance Table**\n")
foreach(InstName InstTable
printf("%s=>%L\n" InstName InstTable[InstName])
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;obtain the DC operating points
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printf("\n**DC operating points**\n")
out=outfile("/home/zqliu216/DM_template61/AnaFault_201609/FPG_logfile/op.auto" "w")
foreach(InstName InstTable
printf("%s=>%L" InstName InstTable[InstName])
cellName=car(InstTable[InstName])
if(cellName=="pmos4" ||cellName=="pfet"|| cellName=="nfet"||cellName=="nmos4" ||
cellName=="pfet33"|| cellName=="nfet33"
then
println(" is a mosfet")
gm=OP(InstName "gm")
gmb=OP(InstName "gmbs")
gds=OP(InstName "gds")
printf("gm_%s\t %1.4e\n" InstName , gm)
if(gmb!=nil then
printf("gmb_%s\t %1.4e\n" InstName , gmb)
); End if
printf("gds_%s\t %1.4e\n" InstName , gds)
280
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;print to file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
fprintf(out "gm_%s\t %1.4e\n" InstName , gm)
if(gmb!=nil then
fprintf(out "gmb_%s\t %1.4e\n" InstName , gmb)
); End if
fprintf(out "gds_%s\t %1.4e\n" InstName , gds)
);if
if(cellName=="res"
then
println("is a res")
res=1/OP(InstName "res")
printf("%s\t %1.4e\n" InstName , res)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;print to file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
fprintf(out "%s\t %1.4e\n" InstName , res)
); End if
); end for
close(out)
exit()
6. SCCsubNetlistForOneSCC
#! /usr/bin/perl
use strict;
use warnings;
use lib './FPG16/FPG/package/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
#=====================How to
use================================================================
==============
#
# 1. At the directory where foder "FPG16" is located, open a terminal;
# 2. Run the command "perl ./FPG16/FPG/SCCsubNetlistForOneSCC.pl SCC5". It will
generate the sub-netlist for SCC5
#
# input file list:
# "./FPG_logfile/SCC_inst.txt" Reqired file contains the instances for each SCC
# created by excuate "perl ./FPG16/FPG/findSCC.pl -d 1"
# "./FPG_logfile/SCC_inputs.txt" Reqired file contains the inputs of each SCC,
281
# created by excuate "perl ./FPG16/FPG/findSCC.pl -d 1"
# "./example.scs" Reqired file contains the netlist of the desired circuit,
# created by using ADE-->simulation-->Netlist-->Create
# "./spectre.dc"
# output file list:
# "./FPG_logfile/subNetlist/input_$input2.scs" contains the sub-netlist for a
given SCC
#=================================================================
============================================
my $input1 = $ARGV[0];
my $input2 = $ARGV[1];
if ($input1 eq "")
print "\n***Usage:Generate netlist file for certain SCC***\n";
print "***Need an input1 to stand for DUT netlist***\n";
print "***E.g. ==> perl ./FPG16/FPG/SCCsubNetlistForOneSCC.pl example.scs SCC1
<===\n\n";
exit(1);
elsif ($input2 eq "")
print "\n***Usage:Generate netlist file for certain SCC***\n";
print "***Need an input2 to stand for SCC name***\n";
print "***E.g. ==> perl ./FPG16/FPG/SCCsubNetlistForOneSCC.pl example.scs SCC1
<===\n\n";
exit(1);
else
#print STDOUT "$input1\n";
###########################################################################
#####
#voltage source to be inserted
###########################################################################
#####
my $VDD="Vdd1 (VDD 0) vsource dc=1.2 type=dc\n";
my $VSS="Vss1 (0 VSS) vsource dc=1.2 type=dc\n";
282
###########################################################################
#####
#obtain the instance for each SCC
###########################################################################
#####
open( SCCInst, "./FPG_logfile/SCC_inst.txt") || die "Can't open SCC_Inst.txt: $!";
my @SCCInst=<SCCInst>;
close(SCCInst);
tie my %SCCInst, 'Tie::IxHash';
foreach (@SCCInst)
if(/^(SCC\d+)=>(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCInst$1=\@temp;
=pod
print "\n**SCC instance list**\n";
foreach (keys %SCCInst)
print "$_==> @$SCCInst$_\n";
print "current SCC is: $input1 @$SCCInst$input1\n\n";
=cut
###########################################################################
#####
#obtain the inputs for each SCC
###########################################################################
#####
open( SCCInputs, "./FPG_logfile/SCC_inputs.txt") || die "Can't open SCC_Inputs.txt: $!";
my @SCCInputs=<SCCInputs>;
close(SCCInputs);
tie my %SCCInputs, 'Tie::IxHash';
foreach (@SCCInputs)
if(/^(SCC\d+)\s+(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCInputs$1=\@temp;
=pod
print "\n**SCC inputs list**\n";
283
foreach (keys %SCCInputs)
print "$_==> @$SCCInputs$_\n";
=cut
###########################################################################
#####
#obtain the input.scs for each SCC
###########################################################################
#####
open( Netlist, "./$input1") || die "Can't open $input1: $!";
my $start1="\/\/ Generated for: spectre";
my $end1="\/\/ View name: schematic";
my @data1;
my $start2='simulatorOptions';
my $end2='saveOptions';
my @data2;
my @data3;
while (<Netlist>)
if (/^$start1/ .. /$end1/)
push @data1, $_;
next;
elsif (/^$start2/ .. /$end2/)
push @data2, $_;
next;
else
push @data3, $_;
close(Netlist);
=pod
print "\n!!!!!!!!!!!!!!!!!!!!date1 is !!!!!!!!!!!!!!!!\n";
print @data1;
print "\n!!!!!!!!!!!!!!!!!!!!date2 is !!!!!!!!!!!!!!!!\n";
print @data2;
print "\n!!!!!!!!!!!!!!!!!!!!date3 is !!!!!!!!!!!!!!!!\n";
284
#print @data3;
=cut
my $inst_name;
tie my %netlist_hash, 'Tie::IxHash';
for (my $i=0;$i<@data3;$i++)
$_=$data3[$i];
if(/^(\w+\d+)\s+\((.*)\)\s+(\w+)\s/)
$inst_name=$1;
$netlist_hash$1=$data3[$i];
if(/\\\n$/)# the backslash at the end of line means the next line is the continued
contents
$netlist_hash$inst_name=join('', $netlist_hash$inst_name, $data3[$i+1]);
foreach (keys %netlist_hash)
#print "$_=>$netlist_hash$_\n";
print "$input2\_inst => [@$SCCInst$input2]\n";
if(exists $SCCInputs$input2)
print "$input2\_input => [@$SCCInputs$input2]\n";
###########################################################################
#####
#obtain DC OP for inputs of current SCC
###########################################################################
#####
open( OP, "./spectre.dc") || die "Can't open spectre.dc.: $!";
my @OP=<OP>;
close(OP);
tie my %SCCInputs_OP, 'Tie::IxHash';
foreach my $net (@$SCCInputs$input2)
my @temp=grep /^$net\s/, @OP;
my @tt=split(/\s+/,$temp[0]);
$SCCInputs_OP$net=$tt[1];
285
foreach my $net (keys %SCCInputs_OP)
print "$net\_DC==> $SCCInputs_OP$net\n";
###########################################################################
#####
#print sub-netlist to file
###########################################################################
#####
open( OUTPUT, ">./FPG_logfile/subNetlist/input_$input2.scs") || die "Can't open myfile:
$!";##'>' means write only, it will clear and rewrite the file.
print OUTPUT @data1;
print OUTPUT $VDD;
print OUTPUT $VSS;
foreach my $net (@$SCCInputs$input2)
#print "$net=>";
my $source="V$net ($net 0) vsource dc=$SCCInputs_OP$net type=dc\n";
##print $source;
print OUTPUT $source;
foreach my $inst (@$SCCInst$input2)
#print "$inst=>";
##print $netlist_hash$inst;
print OUTPUT $netlist_hash$inst;
print OUTPUT @data2;
close( OUTPUT );
print "The sub-netlist for $input2 has been created!
=>./FPG_logfile/subNetlist/input_$input2.scs\n\n";
7. SCCsubNetlistForTwoSCC.pl
#! /usr/bin/perl
use strict;
use warnings;
use lib './FPG16/FPG/package/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
286
require './FPG16/FPG/findPath.pl';
#=====================How to
use================================================================
==============
#
# 1. At the directory where foder "FPG16" is located, open a terminal;
# 2. Run the command "perl ./FPG16/FPG/SCCsubNetlistForTwoSCC.pl example.scs
SCC10 SCC11". It will generate the sub-netlist for SCC5
#
# input file list:
# "./FPG_logfile/SCC_inst.txt" Reqired file contains the instances for each SCC
# created by excuate "perl ./FPG16/FPG/findSCC.pl -d 1"
# "./FPG_logfile/SCC_inputs.txt" Reqired file contains the inputs of each SCC,
# created by excuate "perl ./FPG16/FPG/findSCC.pl -d 1"
# "./example.scs" Reqired file contains the netlist of the desired circuit,
# created by using ADE-->simulation-->Netlist-->Create
# "./spectre.dc"
# output file list:
# "./FPG_logfile/subNetlist/input_$input2.scs" contains the sub-netlist for a
given SCC
#=================================================================
============================================
my $input1 = $ARGV[0];
my $input2 = $ARGV[1];
my $input3 = $ARGV[2];
if ($input1 eq "")
print "\n***Usage:Generate netlist file for certain SCC***\n";
print "***Need an input1 to stand for DUT netlist***\n";
print "***E.g. ==>perl ./FPG16/FPG/SCCsubNetlistForTwoSCC.pl example.scs SCC1
SCC2<===\n\n";
exit(1);
elsif (($input2 eq "") or ($input3 eq ""))
print "\n***Usage:Generate netlist file for certain SCC***\n";
print "***Need an input2 to stand for SCC name***\n";
print "***E.g. ==> perl ./FPG16/FPG/SCCsubNetlistForTwoSCC.pl example.scs SCC1
SCC2<===\n\n";
exit(1);
287
else
# print STDOUT "$input1\n";
###########################################################################
#####
#voltage source to be inserted
###########################################################################
#####
my $VDD="Vdd1 (VDD 0) vsource dc=1.2 type=dc\n";
my $VSS="Vss1 (0 VSS) vsource dc=1.2 type=dc\n";
###########################################################################
#####
#obtain the instance for each SCC
###########################################################################
#####
open( SCCInst, "./FPG_logfile/SCC_inst.txt") || die "Can't open SCC_Inst.txt: $!";
my @SCCInst=<SCCInst>;
close(SCCInst);
tie my %SCCInst, 'Tie::IxHash';
foreach (@SCCInst)
if(/^(SCC\d+)=>(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCInst$1=\@temp;
=pod
print "\n**SCC instance list**\n";
foreach (keys %SCCInst)
print "$_==> @$SCCInst$_\n";
print "current SCC is: $input1 @$SCCInst$input1\n\n";
=cut
###########################################################################
#####
#obtain the inputs for each SCC
###########################################################################
#####
288
open( SCCInputs, "./FPG_logfile/SCC_inputs.txt") || die "Can't open SCC_Inputs.txt: $!";
my @SCCInputs=<SCCInputs>;
close(SCCInputs);
tie my %SCCInputs, 'Tie::IxHash';
foreach (@SCCInputs)
if(/^(SCC\d+)\s+(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCInputs$1=\@temp;
=pod
print "\n**SCC inputs list**\n";
foreach (keys %SCCInputs)
print "$_==> @$SCCInputs$_\n";
=cut
###########################################################################
#####
#obtain the outputs for each SCC
###########################################################################
#####
open( SCCOutputs, "./FPG_logfile/SCC_outputs.txt") || die "Can't open SCC_Outputs.txt:
$!";
my @SCCOutputs=<SCCOutputs>;
close(SCCOutputs);
tie my %SCCOutputs, 'Tie::IxHash';
foreach (@SCCOutputs)
if(/^(SCC\d+)\s+(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCOutputs$1=\@temp;
=pod
print "\n**SCC outputs list**\n";
foreach (keys %SCCOutputs)
print "$_==> @$SCCOutputs$_\n";
289
=cut
###########################################################################
#####
#obtain the simple standard graph
###########################################################################
#####
open( DAG, "./FPG_logfile/standard_dag.txt") || die "Can't open standard_dag.txt: $!";
my @dag=<DAG>;
close(DAG);
tie my %dag, 'Tie::IxHash';
tie my %graph, 'Tie::IxHash';
foreach my $edge (@dag)
my @temp=split(/\s+/, $edge);
$graph$temp[0]=[] if(not exists $graph$temp[0]);
$graph$temp[0]=[@$graph$temp[0],$temp[1]];
=pod
print "\n**Simple standard graph**\n";
foreach (keys %graph)
print "$_=> @$graph$_\n";
=cut
##############################
#run the find_path function
#written in findPath.pl file
##############################
######################
#join the path to hash
######################
my $i=0;
tie my %path, 'Tie::IxHash';
my @path_begin;
push @path_begin, $input2;
my $path_end=$input3;
##print "path_begin=@path_begin\n";
##print "path_end=$path_end\n";
foreach my $path_begin(@path_begin)
my $routes = find_paths($path_begin, $path_end, \%graph);
290
#my $n=@$routes;
#print $n;
foreach my $pt (@$routes)
my $temp="path";
my $p=join("",($temp, $i++));
#print $p," => ";
#print "@$pt\n";
$path$p=[@$pt];
my @SCC_list;
my @input_list;
my @output_list;
##print "\n**path list**\n";
foreach (keys %path)
##print "$_=>@$path$_\n";
foreach my $SCC (@$path$_)
if( !grep(/^$SCC$/,@SCC_list))
push @SCC_list,$SCC;
push @input_list, @$SCCInputs$SCC if(exists
$SCCInputs$SCC);
push @output_list, @$SCCOutputs$SCC if(exists
$SCCOutputs$SCC)
##print "SCC list=> @SCC_list\n";
##print "outputs=>@output_list\n";
##print "inputs=>@input_list\n";
my %seen=();
@output_list= grep!$seen$_++ @output_list;#delete duplicated data
@input_list =grep!$seen$_++ @input_list;
##print "\noutputs=>@output_list\n";
##print "inputs=>@input_list\n";
###########################################################################
#####
#obtain the input.scs for the whole circuit
291
###########################################################################
#####
open( Netlist, "./$input1") || die "Can't open $input1: $!";
my $start1="\/\/ Generated for: spectre";
my $end1="\/\/ View name: schematic";
my @data1;
my $start2='simulatorOptions';
my $end2='saveOptions';
my @data2;
my @data3;
while (<Netlist>)
if (/^$start1/ .. /$end1/)
push @data1, $_;
next;
elsif (/^$start2/ .. /$end2/)
push @data2, $_;
next;
else
push @data3, $_;
close(Netlist);
=pod
print "\n!!!!!!!!!!!!!!!!!!!!date1 is !!!!!!!!!!!!!!!!\n";
print @data1;
print "\n!!!!!!!!!!!!!!!!!!!!date2 is !!!!!!!!!!!!!!!!\n";
print @data2;
print "\n!!!!!!!!!!!!!!!!!!!!date3 is !!!!!!!!!!!!!!!!\n";
#print @data3;
=cut
my $inst_name;
tie my %netlist_hash, 'Tie::IxHash';
for (my $i=0;$i<@data3;$i++)
$_=$data3[$i];
if(/^(\w+\d+)\s+\((.*)\)\s+(\w+)\s/)
$inst_name=$1;
292
$netlist_hash$1=$data3[$i];
if(/\\\n$/)# the backslash at the end of line means the next line is the continued
contents
$netlist_hash$inst_name=join('', $netlist_hash$inst_name, $data3[$i+1]);
foreach (keys %netlist_hash)
#print "$_=>$netlist_hash$_\n";
##print "\n**parent SCC**\n";
##print "$input2\_inst => [@$SCCInst$input2]\n";
if(exists $SCCInputs$input2)
##print "$input2\_input => [@$SCCInputs$input2]\n";
else
##print "$input2 is a sink SCC!\n";
###########################################################################
#####
#obtain DC OP for inputs of current SCC
###########################################################################
#####
open( OP, "./spectre.dc") || die "Can't open spectre.dc.: $!";
my @OP=<OP>;
close(OP);
my %input_list_OP;
foreach my $net (@input_list)
my @temp=grep /^$net\s/, @OP;
my @tt=split(/\s+/,$temp[0]);
$input_list_OP$net=$tt[1];
##print "$net\_DC==> $input_list_OP$net\n";
close(OP);
293
###########################################################################
#####
#print sub-netlist to file
###########################################################################
#####
print "\n\n**print sub-netlist to file**\n";
open( OUTPUT, ">./FPG_logfile/subNetlist/input_$input2\_$input3.scs") || die "Can't open
input_$input2\_$input3.scs: $!";##'>' means write only, it will clear and rewrite the file.
print OUTPUT @data1;
print OUTPUT $VDD;
print OUTPUT $VSS;
foreach my $net (@input_list)
my $source="V$net ($net 0) vsource dc=$input_list_OP$net type=dc\n";
print OUTPUT $source;
#print "$net=>";
##print " Added => $source";
foreach my $SCC (@SCC_list)
foreach my $inst (@$SCCInst$SCC)
#print "$inst=>";
##print $netlist_hash$inst;
print OUTPUT $netlist_hash$inst;
print OUTPUT @data2;
close( OUTPUT );
print "The sub-netlist for $input2\_$input3 has been created!
=>./FPG_logfile/subNetlist/input_$input2\_$input3.scs\n\n";
8. subNetlistForAllSCC.pl
#! /usr/bin/perl
use strict;
use warnings;
use lib './FPG16/FPG/package/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
294
require './FPG16/FPG/findPath.pl';
require './FPG16/FPG/findPathToSink.pl';
#=====================How to
use================================================================
==============
#
# 1. At the directory where foder "FPG16" is located, open a terminal;
# 2. Run the command "perl ./FPG16/FPG/subNetlistForAllSCC.pl example.scs". It will
generate the sub-netlist for all SCCs
#
# input file list:
# "./FPG_logfile/SCC_inst.txt" Reqired file contains the instances for each SCC
# created by excuate "perl ./FPG16/FPG/findSCC.pl -d 1"
# "./example.scs" Reqired file contains the netlist of the desired circuit,
# created by using ADE-->simulation-->Netlist-->Create
# "./FPG_logfile/standard_dag.txt"
# "./FPG_logfile/SCC_inputs.txt"
# "./FPG_logfile/SCC_outputs.txt"
# "./FPG16/sinkSCC_OP.txt" Desired OP at sink SCC
# output file list:
# "./FPG_logfile/subNetlist/*.scs" contains the sub-netlist for all SCCs
#=================================================================
============================================
my $input1 = $ARGV[0];
if ($input1 eq "")
print "\n***Usage:Generate netlist file for certain SCC***\n";
print "***Need an input1 to stand for DUT netlist***\n";
print "***E.g. ==> perl ./FPG16/FPG/subNetlistForAllSCC.pl example.scs<===\n\n";
exit(1);
###########################################################################
#####
#obtain the instance for each SCC
###########################################################################
#####
open( SCCInst, "./FPG_logfile/SCC_inst.txt") || die "Can't open SCC_Inst.txt: $!";
my @SCCInst=<SCCInst>;
295
close(SCCInst);
tie my %SCCInst, 'Tie::IxHash';
foreach (@SCCInst)
if(/^(SCC\d+)=>(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCInst$1=\@temp;
print "\n**SCC instance list**\n";
foreach (keys %SCCInst)
print "$_==> @$SCCInst$_\n";
#unlink glob "'./FPG_logfile/subNetlist/*.*'";
if (! -d './FPG_logfile/subNetlist')
system('mkdir -p ./FPG_logfile/subNetlist')
else
system('rm -r ./FPG_logfile/subNetlist/*');
print "Simulating the fault-free circuit...";
system("spectre .\/$input1 >.\/FPG_logfile\/spectre_faultFree_Circuit.log");
print "Simulation finished...";
foreach my $SCCi (keys %SCCInst)
#print "!!!!$SCCi==> @$SCCInst$SCCi\n";
if (@$SCCInst$SCCi)
system("perl ./FPG16/FPG/SCCsubNetlistForOneSCC.pl $input1 $SCCi");
###########################################################################
#####
#obtain the standard dat
296
###########################################################################
#####
open( DAG, "./FPG_logfile/standard_dag.txt") || die "Can't open standard_dag.txt: $!";
my @dag=<DAG>;
close(DAG);
print @dag;
tie my %graph, 'Tie::IxHash';
foreach my $edge (@dag)
my @temp=split(/\s+/, $edge);
$graph$temp[0]=[] if(not exists $graph$temp[0]);
$graph$temp[0]=[@$graph$temp[0],$temp[1]];
foreach (keys %graph)
print "$_=> @$graph$_\n";
foreach my $e (@dag)
print "For edge: $e";
system("perl ./FPG16/FPG/SCCsubNetlistForTwoSCC.pl $input1 $e");
=pod
###########################################################################
#####
#obtain the inputs for each SCC
###########################################################################
#####
open( SCCInputs, "./FPG_logfile/SCC_inputs.txt") || die "Can't open SCC_Inputs.txt: $!";
my @SCCInputs=<SCCInputs>;
close(SCCInputs);
tie my %SCCInputs, 'Tie::IxHash';
foreach (@SCCInputs)
if(/^(SCC\d+)\s+(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCInputs$1=\@temp;
297
###########################################################################
#####
#obtain the outputs for each SCC
###########################################################################
#####
open( SCCOutputs, "./FPG_logfile/SCC_outputs.txt") || die "Can't open SCC_Outputs.txt:
$!";
my @SCCOutputs=<SCCOutputs>;
close(SCCOutputs);
tie my %SCCOutputs, 'Tie::IxHash';
my @SCC_list;
foreach (@SCCOutputs)
if(/^(SCC\d+)\s+(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SCCOutputs$1=\@temp;
push @SCC_list,$1;
###########################################################################
#####
#obtain the sink SCC
###########################################################################
#####
open( SINK, "./FPG16/sinkSCC_OP.txt") || die "Can't open sinkSCC_OP.txt: $!";
my @SINK=<SINK>;
close(SINK);
tie my %SINK, 'Tie::IxHash';
my @sinkSCC_list;
my @sourceSCC_list;
foreach (@SINK)
if(/^(SCC\d+)\s+(.*)/)
#print $1,"\t",$2,"\n";
my @temp=split(/\s+/,$2);
$SINK$1=\@temp;
push @sinkSCC_list,$1;
298
print "\n**sink SCC list**\n";
foreach (keys %SINK)
print "$_==> @$SINK$_\n";
for my $SCC (@SCC_list)
if(!exists $SCCInputs$SCC)
print "$SCC is a source SCC!\n";
push @sourceSCC_list, $SCC;
##############################
#run the find_path function
#written in findPath.pl file
##############################
######################
#join the path to hash
######################
tie my %path, 'Tie::IxHash';
my $i=0;
tie my %path_endpoints, 'Tie::IxHash';
foreach my $path_begin(@SCC_list)
foreach my $path_end(@sinkSCC_list)
my $routes = find_paths($path_begin, $path_end, \%graph);
#my $n=@$routes;
#print $n;
if(@$routes)
print "$path_begin=>$path_end !!!\n";
$path_endpoints$path_begin=[] if(!exists
$path_endpoints$path_begin);
$path_endpoints$path_begin=[@$path_endpoints$path_begin,$path_end];
foreach my $pt (@$routes)
my $temp="path";
my $p=join("",($temp, $i++));
299
#print $p," => ";
#print "@$pt\n";
$path$p=[@$pt];
find_path_to_sink(\@SCC_list,\@sinkSCC_list);
=cut
9. main.pl
#! /usr/bin/perl
use strict;
use warnings;
use lib './FPG16/FPG/package/Tie-IxHash-1.23/lib';
use Tie::IxHash; ### Hashes are not ordered, but as usual, CPAN offers a solution:
Tie::IxHash
#use lib './FPG16/FPG/package/Time-HiRes-1.9739/blib/lib';
#use Time::HiRes;
#=====================How to
use================================================================
==============
# 1. run "createNetlist_hier.il" following the instruction, you will get the netlist:
./FPG_logfile/hier.netlist
# 2. At the directory where foder "FPG16" is located, open a terminal;
# Run the command "perl ./FPG16/FPG/main.pl oceanScript_TargedCircuit.ocn"
#
# input file list:
# "./FPG_logfile/hier.netlist" Reqired file contains the netlist that we want to
flatten,
# created by excuate "createNetlist_hier.il"
# output file list:
# "./FPG_logfile/fpg.txt" contains the fault propagation graph
# "./FPG_logfile/sg.txt" contains the sensitivity graph
#=================================================================
============================================
my $input1=$ARGV[0];
if ($input1 eq "")
print "\nError Command!!\n";
print "**Usage Instruction**\n";
300
print "Please specify the ocean script to simulate the DC operating points of target circuit
\n";
print "Example: perl ./FPG16/FPG/main.pl oceanScript_TargedCircuit.ocn\n\n";
exit(1);
my $ocean;
my $DUT_name;
if( $input1=~/(.*)\.ocn$/)
$DUT_name=$1;
$ocean=$input1; #determine wether to print out information
else
print "Error parameter!\n";
print "File name should end with \"\.ocn\"\n";
exit(0);
my $start_time=time();
print "input fie is: $ocean\n";
if (! -d './FPG_logfile')
system('mkdir -p ./FPG_logfile')
open FILEA, "./$ocean" || die "Cannot open $ocean.ocn: $!";
open FILEB, "./FPG16/FPG/obtainOP_partII.ocn" || die "Cannot open obtainOP_partII.ocn:
$!";
open FILEC, ">./FPG16/FPG/obtainOP.ocn" || die "Cannot open obtainOP.ocn: $!";
print FILEC "#! /bin/sh -exec awd -ocean \"\$\@\"\n\n";
print FILEC <FILEA>;
print FILEC <FILEB>;
close(FILEA);
close(FILEB);
close(FILEC);
####open the net_from_cadence that generated from Cadence.
open( MYFILE, "./FPG_logfile/hier.netlist") || die "Can't open hier.netlist: $!";
my @netlist_from_cadence=<MYFILE>;
print @netlist_from_cadence;
close(MYFILE);
301
my @netlist_usf=grep /^\w+\d/, @netlist_from_cadence;
#print @netlist_usf;
tie my %instance_prop, 'Tie::IxHash';
for (my $i=0;$i<@netlist_usf;$i++)
$_=$netlist_usf[$i];
if(/^(\w+\d+)\s+\(\"(.*)\"\)\s+(\w+)\s/)
my $inst_name=$1;
my $inst_prop=$3;
print "$inst_name\t$inst_prop\t";
if($inst_prop=~/^pmos|^pfet|^nmos|^nfet/) #means this is a coms transistor
print "is a mos\n";
$instance_prop$inst_name=$inst_prop;
elsif($inst_prop=~/^res/) #means this is a resistor
print "is a res\n";
$instance_prop$inst_name=$inst_prop;
####################print the instance name to a file
open(MYFILE, ">./FPG_logfile/inst_list.txt") || die "Cannot open inst_list.txt: $!";
print "\n**instance list**\n";
foreach (keys %instance_prop)
print "$_\t $instance_prop$_\n";
print MYFILE "$_\t $instance_prop$_\n";
close(MYFILE);
print "\n\nDC simultion is running ...\n";
system("ocean -restore ./FPG16/FPG/obtainOP.ocn >./FPG_logfile/logfile_obtainOP.txt");
print "DC simultion is finished \n";
print "Obtain DC operating points ...\n";
print "Finished\n";
302
print "createFPG...\n";
system("perl ./FPG16/FPG/createFPG.pl");
print "Finished\n";
print "create_subSG...\n";
system("perl ./FPG16/FPG/create_subSG.pl");
print "Finished\n";
print "subNetlistForAllSCC...\n";
system("perl ./FPG16/FPG/subNetlistForAllSCC.pl $DUT_name.scs");
print "Finished\n";
system('rm ./example.ahdlSimDB -r');
system('rm ./example.raw -r');
my $finish_time=time();
my $timeused=$finish_time-$start_time;
#my $dd=Time::HiRes::gettimeofday();
#print "!!!!$dd\n";
print "start_time: $start_time\n";
print "finish_time: $finish_time\n";
print "Used time: $timeused\n";
=cut
10. main.py
#!/usr/bin/python
# coding: utf-8
import re
import os
import time #for calculating the used time
#os.system('python ./FPG16/FaultSim/simFaultImpacts.py') #simulate SCC by SCC, and
fault impact for SCCs
#os.system('python ./FPG16/FaultSim/gainCalcul.py ')#calculate Gain between SCC and FC
(SCC by SCC)
os.system('python ./FPG16/FaultSim/simFaultImpacts_whole_circuit.py')#simulate whole
circuit
303
11. simFaultImpacts.py
#!/usr/bin/python
# coding: utf-8
#=====================How to
use================================================================
==============
## 0. Copy the place the folder "FaultSim" under you directory.
#
# required files before running
# (1). make sure the netlist for each SCC is generated
# in this example it is genereated byand placed under './subNetlist'
# (2). "./SCC_outputs.txt" the output nodes (or observation points set) for each SCC
# (3). "./SCC_inputs.txt" the input nodes (or observation points set) for each SCC
#
#
# 1. At the directory where foder "FaultSim" is located, open a terminal;
# 2. Run the command "python ./FaultSim/final_flattened.py"
# If you want to suppress the spectre output logs in terminal, uncomment the
suppress_output variable below,
# else leave it as empty string
# 3. A new folder called simresults will be created in the python directory; netlists and
outputs are stored here
# 4. T1_dg_input.scs indicates the netlist for a short between d(drain) and g(gate) of
transistor T1
# 5. T1_d_input.scs indicates the netlist for an open at d(drain) of transistor T1
# 6. Short is implemented by a resistor r=10 and open by a resistor r=1G ohms
#
#
# make sure the OP in SCC_output.txt is what you would like to observe and generate fault
impacts for!!
#=================================================================
============================================
import re
import os
import time #for calculating the used time
from numpy import * #for array and matrix operation,like taking inversion of a matrix
import sys
from inspect import currentframe, getframeinfo #for detecting and printing out error
information.
#=================================================================
==================================
304
#modification is needed for this section
#=================================================================
==================================
MOP_DR_array=array([2.532e-3*3,100.6e-3*3, 37.83e-3*3,24.36e-3*3])
#MOP_DR=MOP_DR_array[0]
#gain2vout=122.47
#ignore the spectre simulation and open the previous result
ignore_simulation=1 #if set to be '1', will open the previous simulated result
simul_trivial_circuit=0
MyVDD='VDD' #define the power supply node of the netlist
MyVSS='VSS' #define the ground node of the netlist
T1=0
T2=0
T_rest=0
#=================================================================
==================================
#=================================================================
==================================
###########################################################################
#########################
#specify your netlists and work directory
###########################################################################
#########################
currentdir=os.getcwd()
currentdir='/home/zqliu216/DM_template61/AnaFault_201609'
faultFreeNetlist_workdir=currentdir+'/FPG_logfile/subNetlist' #define the fault-free circuit
netlist for SCC you would like to simulate
faultyNetlist_workdir=currentdir+'/FPG_logfile/FaultSim/simresultsSCC' #store the
modified faulty circuit netlist and their DC simulation results
#os.system("mkdir -p %s"%(faultyNetlist_workdir))
#if os.path.isfile(faultyNetlist_workdir): #if there are documents, delete them
# os.system("rm -r %s/*"%(faultyNetlist_workdir))
if(ignore_simulation==0):
if not os.path.exists(faultyNetlist_workdir):
os.makedirs(faultyNetlist_workdir)
elif os.path.isfile(faultyNetlist_workdir):#if there are documents, delete them
os.system("rm -r %s/*"%(faultyNetlist_workdir))
###########################################################################
#########################
#specify your transitor and resistor master names here
305
###########################################################################
#########################
mosfet_types= ['nfet33','pfet33','nfet','pfet','ami06N','ami06P']
resistor_types= ['res', 'resistor']
###########################################################################
#########################
#some simulation options
###########################################################################
#########################
suppress_output=''
# To avoid printing spectre output logs in terminal, uncomment the line below
suppress_output='>/dev/null'
# Extra commands to give to spectre. Leave as empty string
spectre_extracommands=''
###########################################################################
#########################
filename=currentdir+'/FPG_logfile/SCC_outputs.txt'
f=open(filename,'r')
contents=f.readlines()
f.close()
SCC_outputs=
SCC_outputs_keys=[]
for i in range(len(contents)):
a=contents[i].split();
SCC_outputs[a[0]]= a[1:] #take items from 1:end in a list, like matlab a[1:end]
SCC_outputs_keys.append(a[0])
print "\n**SCC outputs**"
#for key,value in SCC_outputs.items():
# print "%s\t=> %s" %(key,value)
for key in SCC_outputs_keys:
print "%s\t=> %s" %(key,SCC_outputs[key])
###########################################################################
#########################
#read SCC nodes
###########################################################################
#########################
filename=currentdir+'/FPG_logfile/SCC_nodes.txt'
f=open(filename,'r')
contents=f.readlines()
f.close()
SCC_nodes=
for i in range(len(contents)):
306
a=contents[i].split();
SCC_nodes[a[0]]= a[1:] #take items from 1:end in a list, like matlab a[1:end]
print "\n**SCC nodes**"
for key in SCC_outputs_keys:
print "%s\t=> %s" %(key,SCC_nodes[key])
sourceSCC_virtual_input=
###########################################################################
#########################
#define a function to read data
###########################################################################
#########################
def readFile(filename,MOP,name):
f = open(filename,'r' )
dc=f.readlines()
f.close()
#########################
dc_str="".join(dc)
#print dc_str
outputs=[]
MOP_eff=[]
for i in range(len(MOP)):
v=re.search('^'+MOP[i]+r'\s+(.*)\n', dc_str, re.MULTILINE)
if v:
value=v.groups()[0]
value=float(value)
#print MOP[i],'==>',value
outputs.append(value)
MOP_eff.append(MOP[i])
else:
print '*error message*'
frameinfo = getframeinfo(currentframe())
print frameinfo.filename, 'line', frameinfo.lineno
exit (MOP[i]+' is not a valid node!')
print name,'\t:',MOP_eff,'=>',outputs
return outputs
###########################################################################
#########################
#define a function to simulate a short fault
###########################################################################
#########################
#def simulShortFault(f_string,str_inserts_short):
###########################################################################
#########################
#read output nodes of each SCC
307
###########################################################################
#########################
start_time=time.time()
f = open(currentdir+'/FPG_logfile/SCC_outputs.txt', 'r')
SCC_outputs= f.readlines()
f.close()
SCC_outputs_keys=[]
SCC_outputs_hash=
outputs_SCC= # determine the SCC name that an output node belongs to
for i in range(len(SCC_outputs)):
a=SCC_outputs[i].split();
SCC_outputs_hash[a[0]]= a[1:] #take items from 1:end in a list, like matlab a[1:end]
SCC_outputs_keys.append(a[0])
for n in a[1:]:
outputs_SCC[n]=a[0]
###########################################################################
#########################
#read input nodes of each SCC
###########################################################################
#########################
filename=currentdir+'/FPG_logfile/SCC_inputs.txt'
f=open(filename,'r')
contents=f.readlines()
f.close()
SCC_inputs=
SCC_inputs_keys=[]
for i in range(len(contents)):
a=contents[i].split();
SCC_inputs[a[0]]= a[1:]
SCC_inputs_keys.append(a[0])
###########################################################################
#########################
#define variables
###########################################################################
#########################
mos_num=0 # number of mosfet in the netlist
res_num=0 # number of resistor in the netlist
fault_tot=0 # number of faults based on 5-fault model
fault_sim=0 # number of faults that are simulated after combining the shorts with same
ending nodes
sim_time=0 # toltal simulation time
#=================================================================
==================================
308
MOP_Allshort=[] # store all the simulated short faults name
MOP_Allopen=[] # store all the simulated open faults name
DuplicateFault=[] # Duplicated faults when simulating SCC by SCC (faults same eding
nodes not detected in diff SCCs)
simulated_shorts_hash= # store all the potentioal simulated short faults name for each SCC
(based on 5-fault mode and after combining the shorts with same ending nodes)
str_inserts_added_hash= # store the short fault that need to added at the SCC output: Vo--
>vdd,Vo-->vss, When Vo is an casecode drain
WholeOpenName= # store all the true simulated open faults name for each SCC
WholeShortName= # store all the true simulated short faults name for each SCC
MOP_short= # store all the true simulated short faults impacts for each SCC
MOP_open= # store all the true simulated open faults impacts for each SCC
#============================================================
=======================================
# this part is added 2017.0308 to store the fault impacts for all node
MOP_short_allnodes= # store all the true simulated short faults impacts of all nodes
for each SCC
MOP_open_allnodes= # store all the true simulated open faults impacts of all nodes
for each SCC
MOP_desired_allnodes=
#============================================================
=======================================
faultInstToNet=
#=================================================================
==================================#
faultList_short= #fault list (short name based)
faultList_open= #fault list (open name based)
SCC_Table= #store all the information for simulation of all SCCs
for SCCn in SCC_outputs_keys:
str_inserts_added_hash[SCCn]=()
simulated_shorts_hash[SCCn]=[]
SCC_Table[SCCn]=
WholeOpenName[SCCn]=[]
WholeShortName[SCCn]=[]
MOP_short[SCCn]=[]
MOP_open[SCCn]=[]
#============================================================
=======================================
# this part is added 2017.0308 to store the fault impacts for all node
MOP_short_allnodes[SCCn]=[]
MOP_open_allnodes[SCCn]=[]
MOP_desired_allnodes[SCCn]=[]
309
#=================================================================
==================================
###########################################################################
#########################
# obtain the fault list fist based on 5-fault mode
# combine the shorts with same ending nodes
# For a SCC interconnection node Vi which will have potential short fault Vi->vdd or Vi-
>vss, only consider the fault in the source SCC
###########################################################################
#########################
for i in range(len(SCC_outputs)):
#for i in range(1):
#for i in [0]:
line=SCC_outputs[i].split()
print 'line==>',line
currentSCCName=line[0]
inputfile=faultFreeNetlist_workdir+'/input_'+currentSCCName+'.scs'
MOPi=line[1:]
#####################################################################
###############################
#simulate fault-free circuit
#obtain desired OP
#####################################################################
###############################
if(ignore_simulation==0):
os.chdir(faultFreeNetlist_workdir)
os.system("spectre "+inputfile+" %s %s"%(spectre_extracommands,
suppress_output))
os.system("cp %s/spectre.dc
%s/%s_spectre.dc"%(faultFreeNetlist_workdir,faultFreeNetlist_workdir,currentSCCName))
outputfile=faultFreeNetlist_workdir+'/%s_spectre.dc'%currentSCCName
MOP_desired=readFile(outputfile,MOPi,'MOP_Desired')
# this part is added on 2017.0308
SCCn=currentSCCName
allnodes_SCCn=SCC_nodes[SCCn]
data_allnodes=readFile(outputfile,allnodes_SCCn,'MOP_Desired')
MOP_desired_allnodes[SCCn].append(data_allnodes)
#####################################################################
###############################
#obtain fault-free netlist
#####################################################################
###############################
f = open(inputfile, 'r')
contents= f.readlines()
310
f.close()
f_string = "".join(contents)
first_element=re.search(r'(^(\S+)\s\((.*?)\)\s(\S+))(.*\n)', f_string, re.MULTILINE)
entry=first_element.span()[0]
#########################put all the information of current SCC in one table
SCCi_Table= #store all the information for simulation of current SCC
SCCi_Table['MOP_desired']=MOP_desired
SCCi_Table['f_string']=f_string
SCCi_Table['entry']=entry
SCCi_Table['MOPi']=MOPi
SCC_Table[currentSCCName]=SCCi_Table
simulated_shorts=[]
simulated_opens=[]
mainckt_netlist=re.finditer(r'(^(\S+)\s\((.*?)\)\s(\S+))(.*\n)', f_string,
re.MULTILINE)
for element in mainckt_netlist:
start=element.span()[0]
inst_name=element.group(2)
nets=element.group(3).split()
cell_type=element.group(4)
if cell_type in mosfet_types:
mos_num += 1
drain=nets[0]
gate=nets[1]
source=nets[2]
body=nets[3]
str_inserts_shorts='R_%s_dg (%s %s) resistor r=10\n'
%(inst_name,drain,gate),\
'R_%s_gs (%s %s) resistor r=10\n'
%(inst_name,gate,source),\
'R_%s_sd (%s %s) resistor r=10\n'
%(inst_name,source,drain)
str_inserts_opens='R_%s_d (%s %s_op) resistor r=1G\n' %(inst_name,
drain, drain),\
'R_%s_s (%s %s_op) resistor r=1G\n'
%(inst_name, source, source)
fault_tot +=5
for each_short in str_inserts_shorts:
FullShortName=each_short.split()[0][2:]
sn=re.search(r'\((\S+)\s(\S+)\)',each_short)
if sn.group(1) != sn.group(2): # ignore the dioed connected
ShortNets=sn.group(1),sn.group(2)
311
faultInstToNet[FullShortName]=sn.group(1)+'_'+sn.group(2)
#do not simulate the fault that one end is SCC input and another is
Vdd/Vss, #refer to its parent SCC output
if currentSCCName in SCC_inputs_keys:
##print SCC_inputs[currentSCCName]
##print source,MyVDD,MyVSS
if (gate in SCC_inputs[currentSCCName]) & ((source ==
MyVDD) | (source == MyVSS)):
##print '%s_gs: gate %s, source
%s!!!!!!!!!!!!!!!!!!!'%(inst_name,gate,source)
str_inserts_shorts='R_%s_dg (%s %s) resistor r=10\n'
%(inst_name,drain,gate),\
'R_%s_sd (%s %s) resistor
r=10\n' %(inst_name,source,drain)
DuplicateFault.append('%s_gs'%inst_name)
##print gate
for SCCn in SCC_outputs_keys: #refer to its parent
SCC output
temp=SCC_outputs_hash[SCCn]
if gate in temp:
##print SCCn,'==>',temp
str_inserts_added_hash[SCCn] +=
'R_%s_%s (%s %s) resistor r=10\n' %(gate,source,gate,source), #A single item tuple must
have a trailing comma, such as (d,).
elif (gate in SCC_inputs[currentSCCName]) & ((drain ==
MyVDD) | (drain == MyVSS)):
##print '%s_dg: gate %s, drain
%s!!!!!!!!!!!!!!!!!!!'%(inst_name,gate,drain)
str_inserts_shorts='R_%s_gs (%s %s) resistor r=10\n'
%(inst_name,gate,source),\
'R_%s_sd (%s %s) resistor
r=10\n' %(inst_name,source,drain)
DuplicateFault.append('%s_dg'%inst_name)
##print gate
for SCCn in SCC_outputs_keys: #refer to its parent
SCC output
temp=SCC_outputs_hash[SCCn]
if gate in temp:
##print SCCn,'==>',temp
str_inserts_added_hash[SCCn] +=
'R_%s_%s (%s %s) resistor r=10\n' %(gate,drain,gate,drain),#A single item tuple must have
a trailing comma, such as (d,).
for each_short in str_inserts_shorts:
312
FullShortName=each_short.split()[0][2:]
sn=re.search(r'\((\S+)\s(\S+)\)',each_short)
if sn.group(1) != sn.group(2): # ignore the dioed connected
ShortNets=sn.group(1),sn.group(2)
if ShortNets in simulated_shorts or
tuple(reversed(ShortNets)) in simulated_shorts:
continue
simulated_shorts.append(ShortNets)
simulated_shorts_hash[currentSCCName]=simulated_shorts
for each_short in str_inserts_shorts:
FullShortName=each_short.split()[0][2:]
###############store the information needed for
simultion/modifying netlist for each short fault
fi_short=
fi_short['SCC']=currentSCCName
fi_short['str_insert']=each_short
faultList_short[FullShortName]=fi_short
for each_open in str_inserts_opens:
FullOpenName=each_open.split()[0][2:]
###############store the information needed for
simultion/modifying netlist for each open fault
fi_open=
fi_open['SCC']=currentSCCName
fi_open['str_insert']=each_open
fi_open['start']=start
faultList_open[FullOpenName]=fi_open
elif cell_type in resistor_types:
res_num +=1
fault_tot += 2
str_inserts_short='R_%s_short (%s %s) resistor r=10\n' %(inst_name,
nets[0], nets[1])
FullShortName=str_inserts_short.split()[0][2:]
###############store the information needed for
simultion/modifying netlist for each short fault
fi_short=
fi_short['SCC']=currentSCCName
fi_short['str_insert']=str_inserts_short
faultList_short[FullShortName]=fi_short
str_inserts_open='R_%s_open (%s %s_op) resistor r=1G\n'
%(inst_name, nets[0], nets[0])
FullOpenName=str_inserts_open.split()[0][2:]
313
###############store the information needed for
simultion/modifying netlist for each Open fault
fi_open=
fi_open['SCC']=currentSCCName
fi_open['str_insert']=str_inserts_open
fi_open['start']=start
faultList_open[FullOpenName]=fi_open
###########################################################################
#######################
# For a SCC interconnection node Vi which will have potential short fault Vi->vdd or Vi-
>vss, only consider the fault in the source SCC
for SCCn in SCC_outputs_keys:
simulated_shorts=simulated_shorts_hash[SCCn]
#print str_inserts_added_hash[SCCn]
for each_short in str_inserts_added_hash[SCCn]:
sn=re.search(r'\((\S+)\s(\S+)\)',each_short)
ShortNets=sn.group(1),sn.group(2)
if ShortNets in simulated_shorts or tuple(reversed(ShortNets)) in
simulated_shorts:
continue
else:
FullShortName=sn.group(1)+'_'+sn.group(2)
###############store the information needed for
simultion/modifying netlist for each short fault
fi_short=
fi_short['SCC']=currentSCCName
fi_short['str_insert']=each_short
faultList_short[FullShortName]=fi_short
print FullShortName, each_short
print '\n**potential faults that needed to simulated at the SCC output: Vo-->vdd,Vo-->vss,
When Vo is an casecode drain**'
for SCCn in SCC_outputs_keys:
print str_inserts_added_hash[SCCn]
print '\n**do not simulate the fault that one end is SCC input and another is Vdd/Vss**'
print DuplicateFault
###########################################################################
#########################
#simulate open fault
###########################################################################
########################
print '\n**simulate open fault**'
simulated_opens=[]
for FullOpenName in sorted(faultList_open.keys()):
314
fi_open=faultList_open[FullOpenName]
SCCn=fi_open['SCC']
##print '%s:\t[%s \'%s\']
%s'%(FullOpenName,fi_open['SCC'],fi_open['str_insert'].strip('\n'), fi_open['start'])
f_string=SCC_Table[SCCn]['f_string']
entry=SCC_Table[SCCn]['entry']
MOPi=SCC_Table[SCCn]['MOPi']
start=fi_open['start']
simulated_opens.append(FullOpenName)
on=re.search(r'\((\S+)\s(\S+)\)',fi_open['str_insert'])
OpenNet=on.group(1)
faultInstToNet[FullOpenName]=OpenNet
#print 'OpenNet=.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',OpenNet
f_mod=re.sub(r'\b%s\b' %(OpenNet), r'%s_op' %(OpenNet),f_string[start:],
count=1)#\b Matches the empty string, but only at the beginning or end of a word. by doing
this, we can match the whole word, this is important!!!!'
f_string_mod=f_string[:start]+f_mod
if(ignore_simulation==0):
faulty=f_string_mod[:entry]+'\n'+fi_open['str_insert']+f_string_mod[entry:]
inputfile=faultyNetlist_workdir+'/'+FullOpenName+'_input.scs'
os.system("touch %s"%(inputfile))
fnew = open(inputfile, 'w')
fnew.write(faulty)
fnew.close()
if simul_trivial_circuit==0:
T2_start=time.time()
os.system("spectre
/home/zqliu216/DM_template61/AnaFault_201609/oneVdc.scs %s
%s"%(spectre_extracommands, suppress_output))
T2+=time.time()-T2_start
os.chdir(faultyNetlist_workdir)
sim_time_start=time.time()
os.system("spectre "+inputfile+" %s %s"%(spectre_extracommands,
suppress_output))
sim_time_end=time.time()
sim_time += sim_time_end-sim_time_start
os.system("cp %s/spectre.dc
%s/%s_spectre.dc"%(faultyNetlist_workdir,faultyNetlist_workdir,FullOpenName))
#########################
#read DC data
outputfile=''
if(ignore_simulation==0):
outputfile=faultyNetlist_workdir+'/spectre.dc'
else:
outputfile=faultyNetlist_workdir+'/%s_spectre.dc' %FullOpenName
315
data=readFile(outputfile,MOPi,FullOpenName)
MOP_Allopen.append(data)
MOP_open[SCCn].append(data)
fault_sim += 1
WholeOpenName[SCCn]=WholeOpenName[SCCn]+[FullOpenName]
# this part is added on 2017.0308
allnodes_SCCn=SCC_nodes[SCCn]
data_allnodes=readFile(outputfile,allnodes_SCCn,FullOpenName)
MOP_open_allnodes[SCCn].append(data_allnodes)
###########################################################################
#########################
#simulate short fault
###########################################################################
########################
print '\n**simulate short fault**'
###############################
#read the DAG
###############################
filename=currentdir+'/FPG_logfile/standard_dag.txt'
f=open(filename,'r')
dag_contents=f.readlines()
f.close()
for i in range(len(dag_contents)):
a=dag_contents[i].split();
combineSCC=a[0]+'_'+a[1]
#print a[0],a[1],combineSCC
inputfile=faultFreeNetlist_workdir+'/input_'+combineSCC+'.scs'
#print 'inputfile=.',inputfile
###############################
#obtain fault-free netlist
###############################
f = open(inputfile, 'r')
contents= f.readlines()
f.close()
f_string = "".join(contents)
first_element=re.search(r'(^(\S+)\s\((.*?)\)\s(\S+))(.*\n)', f_string, re.MULTILINE)
entry=first_element.span()[0]
#########################put all the information of current SCC in one table
SCCi_Table= #store all the information for simulation of current SCC
SCCi_Table['f_string']=f_string
SCCi_Table['entry']=entry
SCC_Table[combineSCC]=SCCi_Table
316
###############################
#read the SCC_path_endpoints
###############################
filename=currentdir+'/FPG_logfile/SCC_path_endpoints.txt'
f=open(filename,'r')
path_contents=f.readlines()
f.close()
SCC_path_endpoints=
for i in range(len(path_contents)):
a=path_contents[i].split();
print a[0],'=>',a[1:]
SCC_path_endpoints[a[0]]=a[1:]
simulated_shorts=[]
for FullShortName in sorted(faultList_short.keys()):
fi_short=faultList_short[FullShortName]
SCCn=fi_short['SCC']
##print '%s:\t[%s \'%s\']'%(FullShortName,SCCn,fi_short['str_insert'].strip('\n'))
f_string=SCC_Table[SCCn]['f_string']
entry=SCC_Table[SCCn]['entry']
MOPi=SCC_Table[SCCn]['MOPi']
sn=re.search(r'\((\S+)\s(\S+)\)',fi_short['str_insert'])
if sn.group(1) != sn.group(2): # ignore the dioed connected
ShortNets=sn.group(1),sn.group(2)
#print 'ShortNets=.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',ShortNets
if ShortNets in simulated_shorts or tuple(reversed(ShortNets)) in
simulated_shorts:
continue
simulated_shorts.append(ShortNets)
if SCCn in SCC_inputs_keys:
#print '\t!!SCC_inputs[SCCn]=',SCC_inputs[SCCn],
print '\tfalut end points=',sn.group(1),sn.group(2)
if (sn.group(1) in SCC_inputs[SCCn]) and (sn.group(1) in
outputs_SCC.keys()):
parentSCC=outputs_SCC[sn.group(1)]
combineSCC=parentSCC+'_'+SCCn
print '\t',sn.group(1),'is a input of ', SCCn,'and output of',
parentSCC
print '\t=>combineSCC=',combineSCC
f_string=SCC_Table[combineSCC]['f_string']
entry=SCC_Table[combineSCC]['entry']
if len(SCC_path_endpoints[parentSCC])>1:
print '\t',parentSCC,'has paths => ',
SCC_path_endpoints[parentSCC],'>1,thus refer fault to', parentSCC
317
SCCn=parentSCC ### This is trying to refer the fault
impact to the parent SCC, because the parent SCC may have paths to other observation
points where this fault impact may be detected
elif sn.group(2) in SCC_inputs[SCCn] and (sn.group(2) in
outputs_SCC.keys()):
parentSCC=outputs_SCC[sn.group(2)]
combineSCC=parentSCC+'_'+SCCn
print '\t',sn.group(2),'is a input of ', SCCn,'and output of',
parentSCC
print '\t=>combineSCC=',combineSCC
f_string=SCC_Table[combineSCC]['f_string']
entry=SCC_Table[combineSCC]['entry']
if len(SCC_path_endpoints[parentSCC])>1:
"\tSCC_path_endpoints[parentSCC]=",SCC_path_endpoints[parentSCC],'>1,thus refer fault
to', parentSCC
SCCn=parentSCC ### This is trying to refer the fault
impact to the parent SCC, because the parent SCC may have paths to other observation
points where this fault impact may be detected
if(ignore_simulation==0):
faulty=f_string[:entry]+'\n'+fi_short['str_insert']+f_string[entry:]
inputfile=faultyNetlist_workdir+'/'+FullShortName+'_input.scs'
os.system("touch %s"%(inputfile))
fnew = open(inputfile, 'w')
fnew.write(faulty)
fnew.close()
if simul_trivial_circuit==0:
T2_start=time.time()
os.system("spectre
/home/zqliu216/DM_template61/AnaFault_201609/oneVdc.scs %s
%s"%(spectre_extracommands, suppress_output))
T2+=time.time()-T2_start
os.chdir(faultyNetlist_workdir)
sim_time_start=time.time()
os.system("spectre "+inputfile+" %s %s"%(spectre_extracommands,
suppress_output))
sim_time_end=time.time()
sim_time += sim_time_end-sim_time_start
os.system("cp %s/spectre.dc
%s/%s_spectre.dc"%(faultyNetlist_workdir,faultyNetlist_workdir,FullShortName))
#########################
#read DC data
outputfile=''
if(ignore_simulation==0):
318
outputfile=faultyNetlist_workdir+'/spectre.dc'
else:
outputfile=faultyNetlist_workdir+'/%s_spectre.dc' %FullShortName
MOPi=SCC_Table[SCCn]['MOPi']
data=readFile(outputfile,MOPi,FullShortName)
MOP_Allshort.append(data)
MOP_short[SCCn].append(data)
# this part is added on 2017.0308
allnodes_SCCn=SCC_nodes[SCCn]
data_allnodes=readFile(outputfile,allnodes_SCCn,FullShortName)
MOP_short_allnodes[SCCn].append(data_allnodes)
fault_sim += 1
WholeShortName[SCCn]=WholeShortName[SCCn]+[FullShortName]
###########################################################################
#########################
#print out the fault impacts for all SCCs
###########################################################################
#########################
print '#print out the fault impacts for all SCCs..'
for SCCn in SCC_outputs_keys:
#print SCCn,'=>\n'
MOPi_short=asarray(MOP_short[SCCn])
MOPi_open=asarray(MOP_open[SCCn])
MOP_desired=SCC_Table[SCCn]['MOP_desired']
MOPi=SCC_Table[SCCn]['MOPi']
faultImpact=MOPi_short-MOP_desired
directory=currentdir+'/FPG_logfile/FaultSim/SCC_faultImpact'
if not os.path.exists(directory):
os.makedirs(directory)
elif os.path.isfile(directory):
os.system("rm -r %s/*"%(directory))
filename=directory+'/'+SCCn+'_faultImpact.txt'
faultname=directory+'/'+SCCn+'_faultName.txt'
fnew = open(filename, 'w')
fnew1 = open(faultname, 'w')
for i in range(len(MOPi)):
fnew.write('\t%s' %MOPi[i])
fnew.write('\n')
for i in range(faultImpact.shape[0]):
for j in range(faultImpact.shape[1]):
fnew.write('%.4e\t' %faultImpact[i][j])
319
fnew.write('\n')
fnew1.write('%s\n' %WholeShortName[SCCn][i])
faultImpact=MOPi_open-MOP_desired
for i in range(faultImpact.shape[0]):
for j in range(faultImpact.shape[1]):
fnew.write('%.4e\t' %faultImpact[i][j])
fnew.write('\n')
fnew1.write('%s\n' %WholeOpenName[SCCn][i])
#print WholeOpenName[SCCn][i]
###########################################################################
#########################
#print out the faultInstToNet for all SCCs
###########################################################################
#########################
print '#print out the faultInstToNet for all SCCs..'
filename=currentdir+'/FPG_logfile/FaultSim/SCC_faultImpact/faultInstToNet.txt'
fnew = open(filename, 'w')
for key,value in faultInstToNet.items():
##print key,value
fnew.write('%s\t%s\n' %(key,value))
elapsed_time = time.time() - start_time
print 'Finished...'
print 'mos_num:',mos_num
print 'res_num:',res_num
print 'fault_tot:',fault_tot
print 'fault_sim:',fault_sim
#print '\n**simulated_shorts**\n',simulated_shorts
##print '\n**output values for short faults**\n',MOP_short
#print '\n**simulated_opens**\n',simulated_opens '
#print '\n**tput values for open faults**\n',MOP_open
print "elapsed_time is: ", elapsed_time
T1=sim_time
T_rest=elapsed_time-T1-T2
print "T1 is: ", T1
print "T2 is: ", T2
print "T1-T2 is: ", T1-T2
print "T_rest is: ", T_rest
320
simulatedFaultList=[]
for SCCn in SCC_outputs_keys:
#print WholeShortName[SCCn]
#print WholeOpenName[SCCn]
simulatedFaultList = simulatedFaultList + WholeShortName[SCCn] +
WholeOpenName[SCCn]
#print "**\nsimulated fault list**"
#print sorted(simulatedFaultList)
'''
for SCCn in SCC_outputs_keys:
#print 'SCCn=>\t',simulated_shorts_hash[SCCn]
simulated_shorts=simulated_shorts_hash[SCCn]
#print str_inserts_added_hash[SCCn]
for each_short in str_inserts_added_hash[SCCn]:
sn=re.search(r'\((\S+)\s(\S+)\)',each_short)
ShortNets=sn.group(1),sn.group(2)
if ShortNets in simulated_shorts or tuple(reversed(ShortNets)) in
simulated_shorts:
continue
else:
print str_inserts_added_hash[SCCn]
print 'god!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
'''
###########################################################################
#########################
#print out the fault impacts of all nodes for all SCCs
###########################################################################
#########################
print '#print out the fault impacts of all nodes for all SCCs..'
for SCCn in SCC_outputs_keys:
#print SCCn,'=>\n'
MOPi_short=asarray(MOP_short_allnodes[SCCn])
MOPi_open=asarray(MOP_open_allnodes[SCCn])
MOP_desired=asarray(MOP_desired_allnodes[SCCn])
MOPi=SCC_nodes[SCCn]
print MOPi_short.shape[0],',',MOPi_short.shape[1]
print MOP_desired.shape[0],',',MOP_desired.shape[1]
faultImpact=MOPi_short-MOP_desired
directory=currentdir+'/FPG_logfile/FaultSim/SCC_faultImpact'
if not os.path.exists(directory):
os.makedirs(directory)
321
elif os.path.isfile(directory):
os.system("rm -r %s/*"%(directory))
filename=directory+'/'+SCCn+'_faultImpact_allnodes.txt'
faultname=directory+'/'+SCCn+'_faultName.txt'
fnew = open(filename, 'w')
fnew1 = open(faultname, 'w')
for i in range(len(MOPi)):
fnew.write('\t%s' %MOPi[i])
fnew.write('\n')
for i in range(faultImpact.shape[0]):
for j in range(faultImpact.shape[1]):
fnew.write('%.4e\t' %faultImpact[i][j])
fnew.write('\n')
fnew1.write('%s\n' %WholeShortName[SCCn][i])
faultImpact=MOPi_open-MOP_desired
for i in range(faultImpact.shape[0]):
for j in range(faultImpact.shape[1]):
fnew.write('%.4e\t' %faultImpact[i][j])
fnew.write('\n')
fnew1.write('%s\n' %WholeOpenName[SCCn][i])
#print WholeOpenName[SCCn][i]
12. gainCalcul.py
#!/usr/bin/python
import os
import re
from numpy import * #for array and matrix operation,like taking inversion of a matrix
import time #for calculating the used time
start_time=time.time()
currentdir=os.getcwd()
###########################################################################
#########################
#read SCC inputs
###########################################################################
#########################
filename=currentdir+'/FPG_logfile/SCC_inputs.txt'
f=open(filename,'r')
contents=f.readlines()
f.close()
SCC_inputs=
SCC_inputs_keys=[]
322
for i in range(len(contents)):
a=contents[i].split();
SCC_inputs[a[0]]= a[1:]
SCC_inputs_keys.append(a[0])
print "\n**SCC inputs**"
#for key,value in SCC_inputs.items():
# print "%s\t=> %s" %(key,value)
for key in SCC_inputs_keys:
print "%s\t=> %s" %(key,SCC_inputs[key])
###########################################################################
#########################
#read SCC outputs
###########################################################################
#########################
filename=currentdir+'/FPG_logfile/SCC_outputs.txt'
f=open(filename,'r')
contents=f.readlines()
f.close()
SCC_outputs=
SCC_outputs_keys=[]
for i in range(len(contents)):
a=contents[i].split();
SCC_outputs[a[0]]= a[1:] #take items from 1:end in a list, like matlab a[1:end]
SCC_outputs_keys.append(a[0])
print "\n**SCC outputs**"
#for key,value in SCC_outputs.items():
# print "%s\t=> %s" %(key,value)
for key in SCC_outputs_keys:
print "%s\t=> %s" %(key,SCC_outputs[key])
###########################################################################
#########################
#read SCC nodes
###########################################################################
#########################
filename=currentdir+'/FPG_logfile/SCC_nodes.txt'
f=open(filename,'r')
contents=f.readlines()
f.close()
SCC_nodes=
for i in range(len(contents)):
a=contents[i].split();
SCC_nodes[a[0]]= a[1:] #take items from 1:end in a list, like matlab a[1:end]
print a[0],'=>',a[1:]
323
print "\n**SCC nodes**"
for key in SCC_outputs_keys:
print key
for key in SCC_outputs_keys:
print "%s\t=> %s" %(key,SCC_nodes[key])
sourceSCC_virtual_input=
for currentSCC in SCC_outputs_keys:
if currentSCC not in SCC_inputs.keys():
print currentSCC,": is a source SCC=>virtual input:
",SCC_nodes[currentSCC][0]
sourceSCC_virtual_input[currentSCC]=SCC_nodes[currentSCC][0]
currentSCC='SCC13'
###########################################################################
#########################
#calculate input output gain for all SCC
###########################################################################
#########################
print "\n*******************************************************"
print "\n**calculate i/o gain for all SCC**"
print "\n*******************************************************"
Gain_hash=
for key in SCC_inputs_keys:
currentSCC=key
print currentSCC,'\t=>\t',
######################################
filename=currentdir+'/FPG_logfile/SCC_subSG/sg_%s.txt' %currentSCC
f=open(filename,'r')
sg=f.readlines()
f.close()
sg_hash=
sg_nodes=[]
for i in range(len(sg)):
a=re.search(r'(\S+)\s+(\S+)\s+(\S+)', sg[i])
sg_hash[a.group(1)+'_'+a.group(2)]=a.group(3)
if a.group(1) not in sg_nodes:
sg_nodes.append(a.group(1))
if a.group(2) not in sg_nodes:
sg_nodes.append(a.group(2))
#sg_inter_nodes=list(set(sg_nodes)-set(SCC_inputs[currentSCC]))
sg_input_nodes=SCC_inputs[currentSCC]
324
sg_inter_nodes=[item for item in sg_nodes if item not in sg_input_nodes]
sg_output_nodes=SCC_outputs[currentSCC]
#print 'sg_nodes=>', sg_nodes
#print 'sg_inter_nodes=>', sg_inter_nodes
#print 'SCC_inputs=>',sg_input_nodes
#print 'SCC_outputs=>',sg_output_nodes
dim=len(sg_inter_nodes)
A=zeros((dim,dim))
for i in range(dim):
for j in range(dim):
if sg_inter_nodes[i]+'_'+sg_inter_nodes[j] in sg_hash.keys():
A[j][i]=sg_hash[sg_inter_nodes[i]+'_'+sg_inter_nodes[j]]
dim2=len(sg_input_nodes)
B=zeros((dim,dim2))
for i in range(dim2):
for j in range(dim):
if sg_input_nodes[i]+'_'+sg_inter_nodes[j] in sg_hash.keys():
B[j][i]=sg_hash[sg_input_nodes[i]+'_'+sg_inter_nodes[j]]
dim3=len(sg_output_nodes)
C=zeros((dim3,dim))
for i in range(dim3):
node=sg_output_nodes[i]
index=sg_inter_nodes.index(node)
#C[i,:]=A[index,:] #take items from row 'i', any coloum in a matrix, same as
matlab
C[i,index]=1 #take items from row 'i', any coloum in a matrix, same as matlab
A=mat(A)
B=mat(B)
I=mat(eye(A.shape[0]))
V=(I-A).I*B
Gain=C*V
'''
print 'A=>',A
print 'B=>',B
print "C=",C
print '!!!'
#print "I=",I
#print '(I-A).I*B = ',V
'''
print 'Gain: %s=>%s = %s ' %(sg_input_nodes, sg_output_nodes,Gain)
for i in range(len(sg_input_nodes)):
325
for j in range(len(sg_output_nodes)):
Gain_hash[sg_input_nodes[i]+'_'+sg_output_nodes[j]]=Gain[j,i]
#for key,value in Gain_hash.items():
# print '%s => %s' %(key,value)
###########################################################################
#########################
#calculate internal gain of SCC outputs for all SCC
###########################################################################
#########################
print "\n*******************************************************"
print "\n**calculate internal gain of SCC outputs for all SCC**"
print "\n*******************************************************"
inter_gain_hash=
for key in SCC_outputs_keys:
currentSCC=key
print '\n--For:',currentSCC
######################################
filename=currentdir+'/FPG_logfile/SCC_subSG/sg_%s.txt' %currentSCC
f=open(filename,'r')
sg=f.readlines()
f.close()
sg_hash=
sg_nodes=[]
for i in range(len(sg)):
a=re.search(r'(\S+)\s+(\S+)\s+(\S+)', sg[i])
sg_hash[a.group(1)+'_'+a.group(2)]=a.group(3)
if a.group(1) not in sg_nodes:
sg_nodes.append(a.group(1))
if a.group(2) not in sg_nodes:
sg_nodes.append(a.group(2))
#sg_inter_nodes=list(set(sg_nodes)-set(SCC_inputs[currentSCC]))
sg_input_nodes=[]
if currentSCC in SCC_inputs.keys():
sg_input_nodes=SCC_inputs[currentSCC]
sg_inter_nodes=[item for item in sg_nodes if item not in sg_input_nodes]
sg_output_nodes=SCC_outputs[currentSCC]
#print 'sg_nodes=>', sg_nodes
#print 'sg_inter_nodes=>', sg_inter_nodes
#print 'SCC_inputs=>',sg_input_nodes
#print 'SCC_outputs=>',sg_output_nodes
326
if len(sg_output_nodes)>1:
print '\tmutiple outputs: ',
if currentSCC in SCC_inputs.keys():
print "non-source SCC!!"
print '\t',SCC_inputs[currentSCC],'=>',SCC_outputs[currentSCC]
for i in range(len(sg_output_nodes)):
for j in range(len(sg_output_nodes)):
if i!=j:
vi=SCC_inputs[currentSCC][0]
v1=sg_output_nodes[i]
v2=sg_output_nodes[j]
gain_vi_v1=Gain_hash[vi+'_'+v1]
gain_vi_v2=Gain_hash[vi+'_'+v2]
gain_v1_v2=gain_vi_v2/gain_vi_v1
print '\t',vi,'=>',v1,'=',gain_vi_v1,
print '\t', vi,'=>',v2,'=',gain_vi_v2,
print '\tgain_%s_%s=%s'%(v1,v2,gain_v1_v2)
Gain_hash[v1+'_'+v2]=gain_v1_v2
else:
print "scource SCC!!"
'\t',sourceSCC_virtual_input[currentSCC],'=>',SCC_outputs[currentSCC]
dim=len(sg_inter_nodes)
A=zeros((dim,dim))
for i in range(dim):
for j in range(dim):
if sg_inter_nodes[i]+'_'+sg_inter_nodes[j] in
sg_hash.keys():
A[j][i]=sg_hash[sg_inter_nodes[i]+'_'+sg_inter_nodes[j]]
B=zeros((dim,1))
vi=sourceSCC_virtual_input[currentSCC]
index=sg_inter_nodes.index(vi)
B[index]=1
#print sg_inter_nodes
#print node,B
dim3=len(sg_output_nodes)
C=zeros((dim3,dim))
for i in range(dim3):
node=sg_output_nodes[i]
index=sg_inter_nodes.index(node)
#C[i,:]=A[index,:] #take items from row 'i', any coloum in a
matrix, same as matlab
327
C[i,index]=1 #take items from row 'i', any coloum in a matrix,
same as
A=mat(A)
B=mat(B)
I=mat(eye(A.shape[0]))
V=(I-A).I*B
Gain=C*V
#print '\tGain: %s=%s * %s ' %(vi,Gain, sg_output_nodes)
for i in range(len(sg_output_nodes)):
for j in range(len(sg_output_nodes)):
if i!=j:
vi=sourceSCC_virtual_input[currentSCC]
v1=sg_output_nodes[i]
v2=sg_output_nodes[j]
gain_vi_v1=Gain[i,0]
gain_vi_v2=Gain[j,0]
gain_v1_v2=gain_vi_v2/gain_vi_v1
print '\t',vi,'=>',v1,'=',gain_vi_v1,
print '\t',vi,'=>',v2,'=',gain_vi_v2,
print '\tgain_%s_%s=%s'%(v1,v2,gain_v1_v2)
Gain_hash[v1+'_'+v2]=gain_v1_v2
'''
dim=len(sg_inter_nodes)
A=zeros((dim,dim))
for i in range(dim):
for j in range(dim):
if sg_inter_nodes[i]+'_'+sg_inter_nodes[j] in sg_hash.keys():
A[j][i]=sg_hash[sg_inter_nodes[i]+'_'+sg_inter_nodes[j]]
dim2=len(sg_output_nodes)
B=zeros((dim,dim2))
for i in range(dim2):
node=sg_output_nodes[i]
index=sg_inter_nodes.index(node)
B[index][i]=1
dim3=len(sg_output_nodes)
C=zeros((dim3,dim))
for i in range(dim3):
node=sg_output_nodes[i]
index=sg_inter_nodes.index(node)
328
C[i,:]=A[index,:] #take items from row 'i', any coloum in a matrix,
same as matlab
A=mat(A)
B=mat(B)
I=mat(eye(A.shape[0]))
V=(I-A).I*B
Gain=C*V
print '\tGain: %s=%s * %s ' %(sg_output_nodes,Gain, sg_output_nodes)
for i in range(len(sg_output_nodes)):
for j in range(len(sg_output_nodes)):
if i != j:
Gain_hash[sg_output_nodes[i]+'_'+sg_output_nodes[j]]=Gain[j,i]
for i in range(dim3):
for j in range(dim3):
if i != j:
print '\t', sg_output_nodes[i],'=>',
sg_output_nodes[j],Gain[j,i]
'''
#for key,value in Gain_hash.items():
# print '%s => %s' %(key,value)
###########################################################################
#########################
#deine sink SCC, detecting range, MOP
###########################################################################
#########################
#sinkSCC=['SCC13','SCC7','SCC8','SCC10']
sinkSCC=['SCC13','SCC10','SCC4','SCC8']
MOP_sink=['vout','Vref','p6','n8']
MOP_DR_array=array([2.298e-3*3,505.5e-3*3, 37.13e-3*3,24.39e-3*3])
i=0;
SCC=sinkSCC[i]
MOP=MOP_sink[i]
MOP_DR=MOP_DR_array[i];
329
print SCC,MOP,MOP_DR
###########################################################################
#########################
#define a function to calculate FC for a given fault impact list at given MOP_DR
###########################################################################
#########################
def detectbility(faultImpact_mat, MOP_DR):
#print '\n**faultImpact_mat**\n',faultImpact_mat
temp=faultImpact_mat/MOP_DR
#print temp
logical=(abs(temp)>1)-0
#print logical
total=logical.shape[0]
detect=0
for i in range(logical.shape[0]):
temp=sum(logical[i,:])
if temp >0:
detect += 1
############
ll=zeros((logical.shape[0],1))
for i in range(logical.shape[1]):
ll=ll + logical[:,i]
ll=(ll>=1)-0
detect2=sum(ll)
############
#print 'detect=',detect
#print 'total=',total # number of rows
return total,detect,detect2,ll
###########################################################################
#########################
#read the fault impacts for all SCCs
###########################################################################
#########################
SCC_faultImpact=
for currentSCC in SCC_outputs_keys:
filename=currentdir+'/FPG_logfile/FaultSim/SCC_faultImpact/'+currentSCC+'_faultI
mpact.txt'
f=open(filename,'r')
contents=f.readlines()
f.close()
faultImpact=
current_MOP=contents[0].split()
dim1=len(contents)-1
dim2=len(current_MOP)
330
#print current_MOP
faultImpact_mat=zeros((dim1,dim2))
faultImpact_mat=mat(faultImpact_mat)
for i in range(len(contents)-1):
#print 'contents[i+1]=>',contents[i+1].split()
temp=[float(n) for n in contents[i+1].split()]# convert string into numbers
faultImpact_mat[i,:]=mat(temp)
#faultImpact_mat.append(contents[i+1].strip()) #.strip() is like chomp() will
remove all spaces at the end
#print "faultImpact_mat => ",faultImpact_mat
SCC_faultImpact[currentSCC]=[current_MOP, faultImpact_mat]
print '\n**Fault impacts for all SCCs'
SCC_final_label=
total2=0
for key in SCC_outputs_keys:
# print key, SCC_faultImpact[key]
SCC_final_label[key]=SCC_faultImpact[key][1]*0
total2 += SCC_faultImpact[key][1].shape[0]
#print SCC
#print SCC_faultImpact[SCC][1]
#a=detectbility(SCC_faultImpact['SCC5'][1], MOP_DR)
#print 'a=',a
###########################################################################
########################
#find the preceeding SCC for all SCC
###########################################################################
########################
preceeding_SCC=
succeeding_SCC=
for n in SCC_inputs_keys:
preceeding_SCC[n]=[]
for n in SCC_outputs_keys:
succeeding_SCC[n]=[]
for n in SCC_outputs_keys:
#print n, SCC_outputs[n]
for m in SCC_inputs_keys:
adj= False
#common=[i for i in SCC_outputs[n] if i in SCC_inputs[m]]
#common=set(SCC_outputs[n]) & set(SCC_inputs[m])
if set(SCC_outputs[n]) & set(SCC_inputs[m]):
331
adj=True
#print '\t',m, SCC_inputs[m]
#print '\t',adj
preceeding_SCC[m]=preceeding_SCC[m]+[n]
succeeding_SCC[n]=succeeding_SCC[n]+[m]
print '\n**preceeding SCC'
for key,value in preceeding_SCC.items():
print value, '=>', key
print '\n**succeeding or Standard DAG'
for key,value in succeeding_SCC.items():
print key, '=>', value
###########################################################################
#########################
#Breadth first search
###########################################################################
#########################
print "\n*******************************************************"
print '\n**BFS search'
print "\n*******************************************************"
SCC_dist=
SCC_parent=
SCC_DR=
SCC_faultDectect=
for n,value in SCC_outputs.items():
SCC_dist[n]=100000
SCC_parent[n]=''
SCC_faultDectect[n]=''
SCC_DR[n]=[]
Q=[]
#sinkSCC=['SCC12','SCC8','SCC4','SCC13']
#MOP_sink=['vout','Vref','p6','n8']
#MOP_DR_array=array([2.532e-3*3,100.6e-3*3, 37.83e-3*3,24.36e-3*3])
for i in range(len(sinkSCC)):
SCC=sinkSCC[i]
MOP=MOP_sink[i]
MOP_DR=MOP_DR_array[i];
SCC_dist[SCC]=0
SCC_DR[SCC].append([MOP_DR,MOP,MOP]) #second is the MOP at the sink
SCC, third is the 'virtual' OP that will be kept for current SCC
332
Q.insert(0,SCC)
while Q:
currentSCC=Q.pop()
print '\ncurrentSCC',currentSCC
print 'SCC_dist_',currentSCC,'=>Lv',SCC_dist[currentSCC]
if SCC_dist[currentSCC] == 0: # sink scc
a=detectbility(SCC_faultImpact[currentSCC][1],
SCC_DR[currentSCC][0][0])
print 'a=',a
if currentSCC in SCC_inputs_keys: #this is not a source SCC
currentSCC_input=SCC_inputs[currentSCC]
print '\t%s_inputs = '%currentSCC,currentSCC_input
print '\t%s_preceeding_SCC = ' %currentSCC,preceeding_SCC[currentSCC]
for parentSCC in preceeding_SCC[currentSCC]: #SCC that is preceeding to
currentSCC
print '\t',parentSCC,'Lv.',SCC_dist[parentSCC],'succeeding_SCC =
',succeeding_SCC[parentSCC]
if SCC_dist[parentSCC] == 100000:# 1st time to reach this SCC
SCC_dist[parentSCC] = SCC_dist[currentSCC] +1
#do backward
print '\t',
SCC_outputs[parentSCC],'=>',SCC_outputs[currentSCC],'\tSCC_DR[%s]='%currentSCC,S
CC_DR[currentSCC]
DR_checked=[]
for DR_vec in SCC_DR[currentSCC]:
print '\t\tDR_vec[1]:', DR_vec[1]
if DR_vec[1] not in DR_checked: # if have multiple paths from
parentSCC-->currentSCC, only check one
DR_checked.append(DR_vec[1])
virtualOP=DR_vec[2]
print '\t\tvirtual OP of currentSCC=>', virtualOP
for v1 in SCC_outputs[parentSCC]: #DRv1=
DRvout/(gain_v1_vout+gain_v1_v2*gain_v2_vout)
eqival_gain=Gain_hash[v1+'_'+virtualOP]
print '\t\t\teqival_gain: gain_%s_%s =
%s'%(v1,virtualOP, Gain_hash[v1+'_'+virtualOP])
for v2 in SCC_outputs[parentSCC]:
if v2 !=v1:
'\t\t\teqival_gain+=:gain_%s_%s(%s)'%(v1,v2, Gain_hash[v1+'_'+v2]),
eqival_gain +=
Gain_hash[v1+'_'+v2]*Gain_hash[v2+'_'+virtualOP]
333
print '*gain_%s_%s (%s) =
%s'%(v2,virtualOP, Gain_hash[v2+'_'+virtualOP], eqival_gain)
DRv1=DR_vec[0]/eqival_gain
'\t\tDR_%s=DR_%s/eqival_gain=%s'%(v1, DR_vec[2], DRv1)
print '\t\t',[DRv1,DR_vec[1],v1]
SCC_DR[parentSCC].append([DRv1,DR_vec[1],v1])#we may have multiple
succeeding_SCC[parentSCC].remove(currentSCC) #remove the
current SCC,means this path has beeen traveled, we will not Quene the parentCC until all
succeeding SCC are travelled
if not succeeding_SCC[parentSCC]:
print "\tQuene %s into Q since all succeeding SCC are
travelled" %parentSCC
Q.insert(0,parentSCC)
print '\t\tbefore combination, SCC_DR[%s]=%s' %(parentSCC,
SCC_DR[parentSCC])
DR_hash=
for DR_vec in SCC_DR[parentSCC]:
name=DR_vec[1]+'_'+DR_vec[2]
if name in DR_hash.keys(): #means we have multiple
paths from parentSCC-->sinkSCC
#print '!!!',DR_hash[name],'!!!!'
algebraic_gain=DR_hash[name][0]+1/DR_vec[0]# take the algebraic gain
DR_hash[name]=[algebraic_gain,DR_vec[1],DR_vec[2]]
else:
DR_hash[name]=[1/DR_vec[0],DR_vec[1],DR_vec[2]] #initilize the positive gain for
mutiple path
SCC_DR[parentSCC]=[] #reset the DR for parentSCC
for key,value in DR_hash.items():
SCC_DR[parentSCC].append([1/value[0],value[1],value[2]])
print '\t\tafter combination, SCC_DR[%s]=%s' %(parentSCC,
SCC_DR[parentSCC])
else:
print '\t',currentSCC,'is a source SCC!'
###########################################################################
#########################
#Calculate fault coverage
334
###########################################################################
#########################
print "\n*******************************************************"
print '\n**Calculate fault coverage'
print "\n*******************************************************"
for SCCn in SCC_outputs_keys:
print 'SCC_DR[%s]=%s' %(SCCn,SCC_DR[SCCn])
print 'SCC_outputs[%s]=%s' %(SCCn,SCC_outputs[SCCn])
OP=[]
for DR_vec in SCC_DR[SCCn]:
if DR_vec[1] not in OP:
OP.append(DR_vec[1])
print OP
dim=len(SCC_outputs[SCCn])
dim2=len(OP)
A=zeros((dim2,dim))
DR_hash=
for DR_vec in SCC_DR[SCCn]:
i=OP.index(DR_vec[1])
j=SCC_outputs[SCCn].index(DR_vec[2])
A[i][j]=DR_vec[0]
print A
for i in range(dim2):
print A[i][:],'!!!!'
a=detectbility(SCC_faultImpact[SCCn][1], mat(A[i][:]))
print '\ta=',a
SCC_final_label[SCCn] += a[3] #as long as one node can detect then
detectable
###########################################################################
#########################
#read the fault name for all SCCs
###########################################################################
#########################
wholeFaultName=
wholeFaultName_propsed=[]
for currentSCC in SCC_outputs_keys:
filename=currentdir+'/FPG_logfile/FaultSim/SCC_faultImpact/'+currentSCC+'_fault
Name.txt'
f=open(filename,'r')
contents=f.readlines()
f.close()
335
f_string = "".join(contents)
f_string_vec=f_string.split()
print '\n--%s\n%s'%(currentSCC,f_string_vec)
wholeFaultName[currentSCC]=f_string_vec
wholeFaultName_propsed=wholeFaultName_propsed+f_string_vec
total=0
detect=0
Undetect=[]
print "\n**undetected fault list**\n"
for SCCn in SCC_outputs_keys:
#print SCCn, '=>', SCC_final_label[SCCn]
print SCCn
logical=SCC_final_label[SCCn]
total+=logical.shape[0]
ll=zeros((logical.shape[0],1))
for i in range(logical.shape[1]):
ll=ll + logical[:,i]
ll=(ll>=1)-0
detect += sum(ll)
for i in range(len(ll)):
if ll[i][0] == 0:
print '\t',i,
print wholeFaultName[SCCn][i]
Undetect.append(wholeFaultName[SCCn][i])
for SCCn in SCC_outputs_keys:
print SCCn, '=>!!!!!!!!!!!!'
current_MOP=SCC_faultImpact[SCCn][0]
faultImpact_mat=SCC_faultImpact[SCCn][1]
#print faultImpact_mat
for i in range(len(wholeFaultName[SCCn])):
print '%s:\t%s => %s\n' %(wholeFaultName[SCCn][i], current_MOP,
faultImpact_mat[i])
elapsed_time = time.time() - start_time
print 'detect=',detect
print 'total=',total # number of rows
FC=float(detect)/total*100
print "FC=%.2f" %FC+'%\n'
print 'total2=',total2
print "elapsed_time is: ", elapsed_time
wholeFaultName_method1=[]
336
filename=currentdir+'/FPG_logfile/FaultSim/wholeFaultName.txt'
f = open(filename, 'r')
contents=f.readlines()
f.close()
f_string = "".join(contents)
wholeFaultName_method1=f_string.split()
'''
print sorted(wholeFaultName_method1)
print '\n\n'
print sorted(wholeFaultName_propsed)
print '\n\n'
'''
t=set(wholeFaultName_method1)
s = set(wholeFaultName_propsed)
diff1 = [x for x in t if x not in s]
diff2 = [x for x in s if x not in t]
print 'whole=',diff1
print 'SCC_by_SCC=',diff2
print '\n\n'
undetecedFaultName_method1=[]
filename=currentdir+'/FPG_logfile/FaultSim/undetecedFaultName.txt'
f = open(filename, 'r')
contents=f.readlines()
f.close()
f_string = "".join(contents)
undetecedFaultName_method1=f_string.split()
print sorted(undetecedFaultName_method1)
print '\n\n'
print sorted(Undetect)
print '\n\n'
t=set(undetecedFaultName_method1)
s = set(Undetect)
diff3 = sorted([x for x in t if x not in s])
diff4 = sorted([x for x in s if x not in t])
#print 'whole=',sorted(diff3)
#print 'SCC_by_SCC=',sorted(diff4)
'''
filename=currentdir+'/FPG_logfile/FaultSim/SCC_faultImpact/faultInstToNet.txt'
f = open(filename, 'r')
contents=f.readlines()
f.close()
faultInstToNet=
for i in contents:
337
print i,
a=i.split()
faultInstToNet[a[0]]=a[1]
print 'whole=',
for i in diff3:
print '%s(%s), '%(i,faultInstToNet[i]),
print '\n\nSCC_by_SCC=',
for i in diff4:
print '%s(%s), '%(i,faultInstToNet[i]),
print '\n'
aa=[faultInstToNet[i] for i in diff3]
bb=[faultInstToNet[i] for i in diff4]
i
print 'whole=[',
for i in diff3:
if faultInstToNet[i] not in bb:
print '%s(%s), '%(i,faultInstToNet[i]),
print ']\n\nSCC_by_SCC=[',
for i in diff4:
if faultInstToNet[i] not in aa:
print '%s(%s), '%(i,faultInstToNet[i]),
print ']\n'
'''